Squashed 'third_party/allwpilib/' changes from e4b91005cf..83f1860047
83f1860047 [wpilib] Add/update documentation to PneumaticBase and subclasses (NFC) (#4881)
9872e676d8 [commands] Make Subsystem destructor virtual (#4892)
25db20e49d [hal] Fix segfault in various HAL functions (#4891)
b0c6724eed [glass] Add hamburger menu icon to titlebars (#4874)
f0fa8205ac Add missing compiler flags and fix warnings (#4889)
42fc4cb6bc [wpiutil] SafeThread: Provide start/stop hooks (#4880)
cc166c98d2 [templates] Add Command-based skeleton template (#4861)
3f51f10ad3 [build] Update to 2023v3 image (#4886)
1562eae74a [ntcore] Refactor meta-topic decoding from glass (#4809)
b632b288a3 Fix usages of std::min and std::max to be windows safe (#4887)
c11bd2720f [wpilibc] Add internal function to reset Shuffleboard instance (#4884)
f1151d375f [ntcore] Add method to get server time offset (#4847)
fe1b62647f [hal,wpilib] Update documentation for getComments (NFC) (#4879)
c49a45abbd [build] Fix examples linking in incorrect jni library (#4873)
bc3d01a721 [build] Add platform check to doxygen plugin (#4862)
bc473240ae Add Jetbrains Fleet folder to .gitignore (#4872)
2121bd5fb8 [wpimath] Remove RKF45 (#4870)
835f8470d6 [build] Fix roborio cross-compiler on arm hosts (#4864)
6cfe5de00d [ntcore] Don't deadlock server on early destroy (#4863)
2ac41f3edc [hal, wpilib] Add RobotController.getComments() (#4463)
26bdbf3d41 Java optimization and formatting fixes (#4857)
92149efa11 Spelling and grammar cleanups (#4849)
176fddeb4c [commands] Add functions to HID classes to allow use of axes as BooleanEvents/Triggers (#4762)
87a34af367 [templates] Add bindings to command-based template (#4838)
4534e75787 [examples] Remove redundant MotorControl example (#4837)
1cbebaa2f7 [commands] Remove final semicolon from test macro definition (#4859)
6efb9ee405 [commands] Add constructor for SwerveControllerCommand that takes a HolonomicDriveController (#4785)
1e7fcd5637 [cscore] Change run loop functions to not be mac specific (#4854)
1f940e2b60 [apriltag] Add C++ wrappers, rewrite Java/JNI to match (#4842)
a6d127aedf [build] Add missing task dependency in wpilibjExamples (#4852)
b893b3d6d3 [cscore] Add support for USB cameras on macOS (#4846)
1696a490fa [glass] Add support for alternate NT ports (#4848)
40a22d69bc [glass] Add support for alternate NT ports (#4848)
e84dbfede0 [wpilib] GenericHID: Add rumble both option (#4843)
8aa9dbfa90 [examples] Link apriltag package in examples build.gradle (#4845)
eda2fa8a17 [build] Update Spotless (#4840)
d20594db0d Fix typos (#4839)
dd8ecfdd54 [commands] Fix typo in waitUntil docs (NFC) (#4841)
17ceebfff4 [apriltag] Clean up apriltag JNI (#4823)
8b74ab389d [examples] RapidReactCommandBot: Fix array indices (#4833)
1aad3489c2 [sim] Implement PD total current and power (#4830)
2744991771 [wpimath] Fix docs in SwerveModulePosition (#4825)
ffbf6a1fa2 [commands] Disable regularly failing unit test (#4824)
fbabd0ef15 [commands] Enhance Command Sendable implementations (#4822)
7713f68772 [hal] Use atomic rather then mutex for DS Data updates (#4787)
701995d6cc [examples] Update Command-based starter project (#4778)
bf7068ac27 [wpilibc] Add missing PPS implementation for C++ (#4821)
aae0f52ca6 [ntcore] NetworkTable: fix visibility of get/set value (#4820)
ee02fb7ba7 [hal] Add support for Pulse-Per-Second signal (#4819)
518916ba02 [wpilib] Fix DS mode thread event being manual reset accidentally (#4818)
3997c6635b [hal] Update to new image, use new TCP notify callback and new duty cycle API (#4774)
cc8675a4e5 [examples] Add comment on how to view elevator sim (NFC) (#4482)
fb2c170b6e [ntcore] Simplify local startup (#4803)
7ba8a9ee1f [wpimath] ProfiledPIDController: Add to SendableRegistry (#4656)
c569d8e523 [wpilib] Joystick.getMagnitude(): use hypot() function (#4816)
2a5e89fa97 [apriltag] Improve description of pose coordinates (NFC) (#4810)
cc003c6c38 [apriltag] Fix AprilTagFieldLayout JSON name (#4814)
5522916123 [commands] CommandXBoxController bumper documentation fix (NFC) (#4815)
967b30de3a [glass] Fix NT view UpdateClients() bug (#4808)
3270d4fc86 [wpimath] Rewrite pose estimator docs (#4807)
be39678447 [apriltag] Add test to ensure apriltagjni loads (#4805)
61c75deb2a [commands] Test no-op behavior of scheduling a scheduled command (#4806)
a865f48e96 [ntcore] Pass pub/sub options as a unified PubSubOptions struct (#4794)
f66a667321 [commands] Fix incorrect Trigger docs (NFC) (#4792)
f8d4e9866e [ntcore] Clean up ntcore_test.h (#4804)
7e84ea891f [wpimath] Fix ComputerVisionUtil transform example in parameter docs (NFC) (#4800)
da3ec1be10 [wpimath] Change terminology for ArmFeedforward gravity gain (NFC) (#4791)
944dd7265d [wpilibc] Add C++ Notifier error handling, update java notifier error message (#4795)
6948cea67a [wpiutil] Fix MemoryBuffer initialization (#4797)
a31459bce6 [wpiutil] Fix UnescapeCString overflow when inputSize < 2 (#4796)
4a0ad6b48c [wpimath] Rotation2d: Add reference to angleModulus in docs (NFC) (#4786)
e6552d272e [ntcore] Remove table multi-subscriber (#4789)
bde383f763 [hal] Replace const char* with std::string_view in Driver Station sim functions (#4532)
5a52b51443 [hal] Add RobotController.getSerialNumber() (#4783)
69a66ec5ec [wpilib] Fix multiple motor safety issues (#4784)
989c9fb29a [wpimath] Revert Rotation2D change that limits angles (#4781)
0f5b08ec69 [wpigui] Update imgui to 1.89.1+ (#4780)
fba191099c [examples] AddressableLED: Add unit test (#4779)
b390cad095 [wpilibj] Consistently use ErrorMessages.requireNonNullParam (#4776)
b9772214d9 [wpilib] Sendable: Don't call setter for getter changes
342c375a71 [ntcore] Add subscriber option to exclude single publisher
b0e4053087 [ntcore] Use int for options instead of double
f3e666b7bb [cscore] Convert YUYV and UYVY directly to grayscale (#4777)
b300518bd1 [hal] Add CAN Stream API to Java through JNI bindings (#4193)
be27171236 [wpilibj] Shuffleboard: Check for null sendable (#4772)
4bbdbdfb48 [commands] Move GroupedCommands to CommandScheduler (#4728)
f18fd41ac3 [wpimath] Remove broken and obsoleted ComputerVisionUtil functions (#4775)
2d0faecf4f [glass] DataSource: Add spinlock to protect value (#4771)
348bd107fc [hal] Add CANManufacturer for The Thrifty Bot (#4773)
3149dc64b8 [examples] HatchbotInlined: Use Subsystem factories (#4765)
8618dd4160 [glass, wpilib] Replace remaining references to Speed Controller with Motor Controller (#4769)
72e21a1ed1 [apriltag] Use wpilibsuite fork of apriltag (#4764)
eab0d929e6 [commands] CommandGenericHID POV methods: Fix docs (NFC) (#4760)
6789869663 [wpilib] Call set(0) rather than disable for stopMotor (#4763)
c9dea2968d [cscore] Emit warning that USB Camera isn't supported on OSX (#4766)
8f402645f5 [commands] Fix PIDSubsystem setSetpoint behavior (#4759)
f24ad1d715 [build] Upgrade to googletest 1.12.1 (#4752)
ff88756864 [wpimath] Add new DCMotor functions for alternative calculations and reduction calculation (#4749)
f58873db8e [wpimath] Remove extra terms in matrix for pose estimator docs (#4756)
37e969b41a [wpimath] Add constructors to pose estimators with default standard deviations (#4754)
13cdc29382 [ci] Rename comment command from "/wpiformat" to "/format" (#4755)
6e23985ae6 [examples] Add main include directory to test builds (#4751)
66bb0ffb2c [examples] Add unit testing infrastructure (#4646)
74cc86c4c5 [wpimath] Make transform tests use pose/transform equality operators (#4675)
e22d8cc343 [wpimath] Use Odometry for internal state in Pose Estimation (#4668)
68dba92630 [ci] Update mac and windows builds to Java 17 (#4750)
23bfc2d9ab [sim] Remove unmaintained Gazebo support (#4736)
1f1461e254 [wpilib] Add method to enable/disable LiveWindow in test mode (#4678)
eae68fc165 [wpimath] Add tolerance for Rotation3d rotation matrix special orthogonality (#4744)
4c4545fb4b [apriltag] Suppress warning (#4743)
16ffaa754d [docs] Generate docs for apriltag subproject (#4745)
5e74ff26d8 [apriltag, build] Update native utils, add apriltag impl and JNI (#4733)
53875419a1 [hal] Allow overriding stderr printing by HAL_SendError (#4742)
aa6499e920 [ntcore] Fix special topic multi-subscriber handling (#4740)
df70351107 [build] Fix cmake install of thirdparty includes (#4741)
e9bd50ff9b [glass] NT view: clear meta-topic info on disconnect (#4732)
9b319fd56b [ntcore] Add sub option for local vs remote changes (#4731)
18d28ec5e3 [ntcore] Remove duplicate value checking from ClientImpl
bdfb625211 [ntcore] Send duplicate values to network if necessary
21003e34eb [commands] Update Subsystem factories and example to return CommandBase (#4729)
70080457d5 [commands] Refactor ProxyScheduleCommand, SelectCommand into ProxyCommand (#4534)
e82cd5147b [wpilib] Tweak Color HSV formula and use in AddressableLED (#4724)
ec124bb662 [commands] Allow unsetting a subsystem's default command (#4621)
2b2aa8eef7 [examples] Update all examples to use NWU coordinate conventions (#4725)
cb38bacfe8 [commands] Revert to original Trigger implementation (#4673)
15561338d5 [commands] Remove one more default command isFinished check (#4727)
ca35a2e097 Add simgui files to .gitignore (#4726)
20dbae0cee [examples] Renovate command-based examples (#4409)
1a59737f40 [commands] Add convenience factories (#4460)
42b6d4e3f7 Use defaulted comparison operators in C++ (#4723)
135c13958f [wpigui] Add FontAwesome (#4713)
ffbfc61532 [ntcore] Add NetworkTable table-specific listeners (#4640)
8958b2a4da [commands] Add property tests for command compositions (#4715)
e4ac09077c [wpilib] Add link to MotorSafety article (#4720)
f40de0c120 [commands] Add C++ factory templates (#4686)
51fa3e851f [build] cmake: Use FetchContent instead of ExternalProject (#4714)
1da84b2255 [wpigui] Reload fonts to scale rather than preloading (#4712)
e43e2fbc84 [wpiutil] StringExtras: Add UnescapeCString (#4707)
5804d8fa84 [ntcore] Server: Properly handle multiple subscribers (#4717)
169ef5fabf [glass] Update NT view for topicsOnly and sendAll changes (#4718)
148759ef54 [examples] CANPDP: Expand properties shown (#4687)
58ed112b51 [commands] RepeatCommand: restart on following iteration (#4706)
dd1da77d20 [readme] Fix broken CI badge (#4710)
7cda85df20 [build] Check Gradle plugin repo last to fix CI (#4711)
7ed9b13277 [build] Bump version plugin to fix null tag (#4705)
6b4f26225d [apriltag] Fix pluralization of apriltag artifacts (#4671)
b2d2924b72 [cscore] Add Y16 image support (#4702)
34ec89c041 [wpilibc] Shuffleboard SimpleWidget: Return pointer instead of reference (#4703)
e15200068d [ci] Disable HW testbench runs (#4704)
d5200db6cd [wpimath] Rename HolonomicDriveController.calculate params (#4683)
2ee3d86de4 [wpimath] Clarify Rotation3d roll-pitch-yaw direction (#4699)
9f0a8b930f [cscore] Use MFVideoFormat_L8 for Gray on Windows (#4701)
2bca43779e [cscore] Add UYVY image support (#4700)
4307d0ee8b [glass] Plot: allow for more than 11 plots (#4685)
3fe8d355a1 [examples] StateSpaceDifferentialDriveSimulation: Use encoder reversed constants (#4682)
b44034dadc [ntcore] Allow duplicate client IDs on server (#4676)
52d2c53888 [commands] Rename Java factory wait() to waitSeconds() (#4684)
76e918f71e [build] Fix JNI artifacts linking to incorrect libraries (#4680)
0bee875aff [commands] Change C++ CommandPtr to use CommandBase (#4677)
98e922313b [glass] Don't check IsConnected for NT widgets (#4674)
9a36373b8f [apriltag] Switch 2022 apriltag layout length and width values (#4670)
cf8faa9e67 [wpilib] Update values on controllable sendables (#4667)
5ec067c1f8 [ntcore] Implement keep duplicates pub/sub flag (#4666)
e962fd2916 [ntcore] Allow numeric-compatible value sets (#4620)
88bd67e7de [ci] Update clang repositories to jammy (#4665)
902e8686d3 [wpimath] Rework odometry APIs to improve feature parity (#4645)
e2d49181da Update to native utils 2023.8.0 (#4664)
149bac55b1 [cscore] Add Arducam OV9281 exposure quirk (#4663)
88f7a3ccb9 [wpimath] Fix Pose relativeTo documentation (#4661)
8acce443f0 [examples] Fix swerve examples to use getDistance for turning encoder (#4652)
295a1f8f3b [ntcore] Fix WaitForListenerQueue (#4662)
388e7a4265 [ntcore] Provide mechanism to reset internals of NT instance (#4653)
13aceea8dc [apriltag] Fix FieldDimensions argument order (#4659)
c203f3f0a9 [apriltag] Fix documentation for AprilTagFieldLayout (#4657)
f54d495c90 Fix non initialized hal functionality during motor safety init (#4658)
e6392a1570 [cmd] Change factories return type to CommandBase (#4655)
53904e7cf4 [apriltag] Split AprilTag functionality to a separate library (#4578)
2e88a496c2 [wpimath] Add support for swerve joystick normalization (#4516)
ce4c45df13 [wpimath] Rework function signatures for Pose Estimation / Odometry (#4642)
0401597d3b [readme] Add wpinet to MavenArtifacts.md (#4651)
2e5f9e45bb [wpimath] Remove encoder reset comments on Swerve, Mecanum Odometry and Pose Estimation (#4643)
e4b5795fc7 [docs] Disable Doxygen for memory to fix search (#4636)
03d0ea188c [build] cmake: Add missing wpinet to installed config file (#4637)
3082bd236b [build] Move version file to its own source set (#4638)
b7ca860417 [build] Use build cache for sign step (#4635)
64838e6367 [commands] Remove unsafe default command isFinished check (#4411)
1269d2b901 [myRobot] Disable spotbugs (#4565)
14d8506b72 [wpimath] Fix units docs for LinearSystemId::IdentifyDrivetrainSystem() (#4600)
d1d458db2b [wpimath] Constrain Rotation2d range to -pi to pi (#4611)
f656e99245 [readme] Add links to development build documentation (#4481)
6dd937cef7 [commands] Fix Trigger API docs (NFC) (#4599)
49047c85b9 [commands] Report error on C++ CommandPtr use-after-move (#4575)
d07267fed1 [ci] Upgrade containers to Ubuntu 22.04 and remove libclang installation (#4633)
b53ce1d3f0 [build, wpiutil] Switch macos to universal binaries (#4628)
5a320c326b [upstream_util, wpiutil] Refactor python scripts (#4614)
c4e526d315 [glass] Fix NT Mechanism2D (#4626)
d122e4254f [ci] Run spotlessApply after wpiformat in comment command (#4623)
5a1e7ea036 [wpilibj] FieldObject2d: Add null check to close() (#4619)
179f569113 [ntcore] Notify locally on SetDefault (#4617)
b0f6dc199d [wpilibc] ShuffleboardComponent.WithProperties: Update type (#4615)
7836f661cd [wpimath] Add missing open curly brace to units/base.h (#4613)
dbcc1de37f [wpimath] Add DifferentialDriveFeedforward classes which wrap LinearPlantInversionFeedforward (#4598)
93890c528b [wpimath] Add additional angular acceleration units (#4610)
3d8d5936f9 [wpimath] Add macro for disabling units fmt support (#4609)
2b04159dec [wpimath] Update units/base.h license header (#4608)
2764004fad [wpinet] Fix incorrect jni definitions (#4605)
85f1bb8f2b [wpiutil] Reenable jni check task (#4606)
231ae2c353 [glass] Plot: Fix Y-axis not being saved (#4594)
e92b6dd5f9 [wpilib] Fix AprilTagFieldLayout JSON property name typos (#4597)
2a8e0e1cc8 Update all dependencies that use grgit (#4596)
7d06e517e9 [commands] Move SelectCommand factory impl to header (#4581)
323524fed6 [wpimath] Remove deprecated units/units.h header (#4572)
d426873ed1 [commands] Add missing PS4 triangle methods (#4576)
5be5869b2f [apriltags] Use map as internal data model (#4577)
b1b4c1e9e7 [wpimath] Fix Pose3d transformBy rotation type (#4545)
a4054d702f [commands] Allow composing two triggers directly (#4580)
0190301e09 [wpilibc] Explicitly mark EventLoop as non-copyable/non-movable (#4579)
9d1ce6a6d9 [ntcore] Catch file open error when saving preferences (#4571)
5005e2ca04 [ntcore] Change Java event mask to EnumSet (#4564)
fa44a07938 [upstream-utils][mpack] Add upstream util for mpack (#4500)
4ba16db645 [ntcore] Various fixes and cleanups (#4544)
837415abfd [hal] Fix joysticks either crashing or returning 0 (#4570)
2c20fd0d09 [wpilib] SingleJointedArmSim: Check angle equals limit on wouldHit (#4567)
64a7136e08 [wpimath] SwerveDrivePoseEstimator: Restore comment about encoder reset (#4569)
b2b473b24a [wpilib] Add AprilTag and AprilTagFieldLayout (#4421)
7aab8fa93a [build] Update to Native Utils 2023.6.0 (#4563)
12c2851856 [commands] WrapperCommand: inherit from CommandBase (#4561)
0da169dd84 [wpimath] Remove template argument from ElevatorFeedforward (#4554)
2416827c25 [wpimath] Fix docs for pose estimator local measurement models (#4558)
1177a3522e [wpilib] Fix Xbox/PS4 POV sim for port number constructors (#4548)
102344e27a [commands] HID classes: Add missing methods, tweak return types (#4557)
1831ef3e19 [wpilib] Fix Shuffleboard SuppliedValueWidget (#4559)
a9606ce870 [wpilib] Fix Xbox/PS4 POV sim (#4546)
6c80d5eab3 [wpimath] Remove unused SymbolExports.h include from units/base.h (#4541)
b114006543 [ntcore] Unify listeners (#4536)
32fbfb7da6 [build] cmake: Install ntcore generated include files (#4540)
02465920fb [build] Update native utils to 2023.4.0 (#4539)
3a5a376465 [wpimath] Increase constexpr support in geometry data types (#4231)
1c3c86e9f1 [ntcore] Cache GetEntry(name) values (#4531)
dcda09f90a [command] Rename trigger methods (#4210)
66157397c1 [wpilib] Make drive classes follow NWU axes convention (#4079)
9e22ffbebf [ntcore] Fix null deref in NT3 client (#4530)
648ab6115c [wpigui,dlt,glass,ov] Support arm in GUI tools (#4527)
8bc3b04f5b [wpimath] Make ComputerVisionUtil use 3D geometry classes (#4528)
cfb84a6083 [wpilibc] Don't hang waiting for NT server to start (#4524)
02c47726e1 [wpimath] Remove unused odometry instance from DifferentialDrivePoseEstimator test (#4522)
b2a0093294 [ci] Revert upgrade of github-pages-deploy-action (#4521)
2a98d6b5d7 [wpimath] PIDController: Add getters for position & velocity tolerances (#4458)
9f36301dc8 [ci] Write wpiformat patch to job summary (#4519)
901fc555f4 [wpimath] Position Delta Odometry for Mecanum (#4514)
4170ec6107 [wpimath] Position Delta Odometry for Swerve (#4493)
fe400f68c5 [docs] Add wpinet to docs build (#4517)
794669b346 [ntcore] Revamp listeners (#4511)
dcfa85a5d5 [ci] Build sanitizers with clang-14 (#4518)
15ad855f1d [ntcore] Add UnitTopic<T> (C++ only) (#4497)
11244a49d9 [wpilib] Add IsConnected function to all gyros (#4465)
1d2e8eb153 [build] Update myRobot deployment (#4515)
ad53fb19b4 [hal] Use new HMB api for addressable LED (#4479)
ba850bac3b [hal] Add more shutdown checks and motor safety shutdown (#4510)
023a5989f8 [ntcore] Fix typo in NetworkServer client connect message (#4512)
c970011ccc [docs] Add Doxygen aliases used by Foonathan memory (#4509)
07a43c3d9a [readme] Document clang-format version and /wpiformat (#4503)
a05b212b04 [ci] Revert changes to wpiformat task from #4501 (#4508)
09faf31b67 [commands] Replace Command HID inheritance with delegation (#4470)
9e1f9c1133 [commands] Add command factories (#4476)
f19d2b9b84 [ci] Add NUMBER environment variable to comment command commit script (#4507)
a28f93863c [ci] Push comment command commit directly to PR (#4506)
c9f61669b8 [ci] Fix comment command commit push (#4505)
dcce5ad3b3 [ci] Update github-script API usage (#4504)
6836e5923d [wpilibc] Restore get duty cycle scale factor (#4502)
335188c652 [dlt] Add deselect/select all buttons to download view (#4499)
60a29dcb99 [glass] Field2D: Add "hidden" option for objects (#4498)
b55d5b3034 [ci] Update deprecated github actions (#4501)
10ed4b3969 [ntcore] Various NT4 fixes (#4474)
4a401b89d7 [hal, wpilib] New DS thread model and implementation (#3787)
c195b4fc46 [wpimath] Clean up PoseEstimator nominal dt docs (#4496)
8f2e34c6a3 [build] Remove wpilib prefix from CMake flat install (#4492)
150d692df7 [wpimath] Remove unused private PoseEstimator function (#4495)
3e5bfff1b5 [wpimath] FromFieldRelativeSpeeds: Add ChassisSpeeds overload (#4494)
9c7e66a27d [commands] C++: Add CommandPtr overload for SetDefaultCommand (#4488)
0ca274866b [build] Fix CMake system library opt-ins (#4487)
dc037f8d41 [commands] Remove EndlessCommand (#4483)
16cdc741cf [wpimath] Add Pose3d(Pose2d) constructor (#4485)
9d5055176d [build] cmake: Allow disabling ntcore build (#4486)
d1e66e1296 [build] Compile all java code with inline string concatenation (#4490)
1fc098e696 Enable log macros to work with no args (#4475)
878cc8defb [wpilib] LiveWindow: Add enableAllTelemetry() (#4480)
8153911160 [build] Fix MSVC runtime archiver to grab default runtime (#4478)
fbdc810887 Upgrade to C++20 (#4239)
396143004c [ntcore] Add ntcoreffi binary (#4471)
1f45732700 [build] Update to 2023.2.4 native-utils and new dependencies (#4473)
574cb41c18 [ntcore] Various fixes (#4469)
d9d6c425e7 [build] Force Java 11 source compatibility (#4472)
58b6484dbe Switch away from NI interrupt manager to custom implementation (#3705)
ca43fe2798 [wpimath] Use Units conversions in ComputerVisionUtil docs (NFC) (#4464)
87a64ccedc [hal] Convert DutyCycle Raw output to be a high time measurement (#4466)
89a3d00297 [commands] Add FinallyDo and HandleInterrupt decorators (#4412)
1497665f96 [commands] Add C++ versions of Java-only decorators (#4457)
27b173374e [wpimath] Add minLinearAccel parameter to DifferentialDriveAccelerationLimiter (#4422)
2a13dba8ac [wpilib] TrajectoryUtil: Fix ambiguous documentation (NFC) (#4461)
77301b126c [ntcore] NetworkTables 4 (#3217)
90cfa00115 [build] cmake: Fix libssh include directory order (#4459)
5cf961edb9 [commands] Refactor lambda-based commands to inherit FunctionalCommand (#4451)
b2276e47de [wpimath] Enable continuous angle input for HolonomicDriveController (#4453)
893b46139a [fieldImages] Add utilities to simplify loading of fields (#4456)
60e29627c0 [commands] C++ unique_ptr migration (#4319)
3b81cf6c35 [wpilib] Improve Color.toString (#4450)
5c067d30a0 [wpinet] WebSocket: Add SendFrames() (#4445)
ceaf493811 [wpiutil] MakeJByteArray: Use span<uint8> instead of string_view (#4446)
10e04e2b13 [examples] FrisbeeBot: Fix reference capture (#4449)
726f67c64b [build] Add exeSplitSetup (#4444)
c7b7624c1c [wpiutil] Add MessagePack utility functions (#4448)
d600529ec0 [wpinet] uv::Async: Add UnsafeSend() (#4447)
b53b3526a2 [wpimath] Add CoordinateSystem conversion for Transform3d (#4443)
38bb23eb18 [wpimath] Add scalar multiply and divide operators to all geometry classes (#4438)
3937ff8221 [wpilib] Remove deprecated Controller class (#4440)
abbfe244b5 [wpilib] Improve Color FromHSV (#4439)
4ddb8aa0dd [sim] Provide function that resets all simulation data (#4016)
a791470de7 Clean up Java warning suppressions (#4433)
17f504f548 [hal,wpilib] Fix SPI Mode Setting (#4434)
773198537c [wpiutil] Add wpi::scope_exit (#4432)
5ac658c8f0 [wpiutil] Logger: Conditionalize around WPI_LOG (#4431)
8767e4a941 [wpiutil] DataLog: Fix SetMetadata output (#4430)
8c4af073f4 [wpiutil] Synchronization: shutdown race protection (#4429)
c79f38584a [build] Fix Java integration tests (#4428)
36c08dd97c [build] Fix cmake install of fmtlib (#4426)
69b7b3dd7d [ci] Remove the Windows cmake job (#4425)
738c75fed8 [readme] Fix formatting/linting link (#4423)
4eb1d03fb3 [wpimath] Document C++ LinearFilter exception (#4417)
ba4ec6c967 [build] Fix clang-tidy false positive on Linux (#4406)
97836f0e55 [commands] Fix ProfiledPIDSubsystem setGoal behavior (#4414)
fdfb85f695 [wpimath] Remove Java LQR constructor that takes a controller gain matrix (#4419)
ab1baf4832 [wpimath] Add rotation matrix constructor to Rotation3d (#4413)
9730032866 [wpimath] Document LQR and KalmanFilter exceptions (#4418)
5b656eecf6 [wpimath] Fix HTML5 entity (#4420)
9ae38eaa7c [commands] Add owning overload to ProxyScheduleCommand (#4405)
cb33bd71df [commands] deprecate withInterrupt decorator (#4407)
d9b4e7b8bf [commands] Revert "Change grouping decorator impl to flatten nested group structures (#3335)" (#4402)
0389bf5214 [hal] REVPH: Improve handling of disconnected CAN Bus (#4169)
4267fa08d1 [wpilibc] ADIS IMUs: Fix memory leak (#4170)
65c8fbd452 [wpilib] MotorControllerGroup: Override setVoltage (#4403)
f36162fddc [wpimath] Improve Discretization internal docs (#4400)
5149f7d894 [wpimath] Add two-vector Rotation3d constructor (#4398)
20b5bed1cb [wpimath] Clean up Java Quaternion class (#4399)
f18dd1905d [build] Include all thirdparty sources in distribution (#4397)
aa9d7f1cdc [wpiutil] Import foonathan memory (#4306)
2742662254 [ci] Remove a couple of obsolete clang-tidy checks (#4396)
a5df391166 [hal, wpilib] Fix up DIO pulse API (#4387)
59e6706b75 [glass] Turn on docking by default
8461bb1e03 [glass] Add support for saving docking info
b873e208b4 [wpigui] Add support for imgui config flags
873e72df8c [build] Update imgui to 1.88 docking branch
c8bd6fc5b4 [ci] Fix comment-command (take 2) (#4395)
fed68b83b4 [ci] Fix comment-command action not running runners (#4393)
0ef8a4e1df [wpimath] Support formatting more Eigen types (#4391)
c393b3b367 [build] Update to native utils 2023.1.0 and Gradle 7.5.1 (#4392)
b5a17f762c [wpimath] Add direction to slew rate limiter (#4377)
fafc81ed1a [wpiutil] Upgrade to fmt 9.1.0 (#4389)
cc56bdc787 [wpiutil] SafeThread: Add Synchronization object variant (#4382)
4254438d8d [commands] Mark command group lifecycle methods as final (#4385)
97c15af238 [wpimath] LinearSystemId: Fix docs, move C++ impls out of header (#4388)
d22ff8a158 [wpiutil] Add JNI access to C++ stderr (#4381)
fdb5a2791f [wpiutil] jni_util: Add Mac-friendly MakeJLongArray/JArrayRef (#4383)
c3a93fb995 [commands] Revamp Interruptible (#4192)
f2a8d38d2a [commands] Rename Command.repeat to repeatedly (#4379)
9e24c6eac0 [wpiutil] Logger: paren-protect instance usage in macro (#4384)
fe4d12ce22 [wpimath] Add LTV controller derivations and make enums private (#4380)
eb08486039 [build] Fix MacOS binary rpath generation (#4376)
ccf83c634a [build] Use native-utils platform names instead of raw strings (#4375)
3fd69749e7 [docs] Upgrade to doxygen 1.9.4 (#4370)
594df5fc08 [wpinet] uv/util.h: Pull in ws2_32.lib on Windows for ntohs (#4371)
539070820d [ci] Enable asan for wpinet and wpiutil (#4369)
564a56d99b [wpinet] Fix memory leak in WorkerThreadTest (#4368)
5adf50d93c [upstream_utils] Refactor upstream_utils scripts (#4367)
d80e8039d7 [wpiutil] Suppress fmtlib clang-tidy warning in C++20 consteval contexts (#4364)
0e6d67b23b [upstream_utils] Remove yapf format disable comment (#4366)
be5270697a [build] Suppress enum-enum deprecation warning in OpenCV (#4365)
8d28851263 Add Rosetta install command to build requirements (#4363)
3d2115c93e [wpinet] include-what-you-use in MulticastTest (#4360)
91002ae3cc [wpimath] Upgrade to Drake 1.6.0 (#4361)
148c18e658 [wpinet] Upgrade to libuv 1.44.2 (#4362)
a2a5c926b6 Fix clang-tidy warnings (#4359)
ea6b1d8449 [wpiutil] Remove unused ManagedStatic class (#4358)
ac9be78e27 Use stricter C++ type conversions (#4357)
151dabb2af [wpiutil] Upgrade to fmt 9.0.0 (#4337)
340465c929 [ci] Upgrade to clang-format and clang-tidy 14 (NFC) (#4347)
d45bcddd15 [examples] Add comments to StateSpaceDifferentialDrive (#4341)
0e0786331a Update LLVM libraries to 14.0.6 (#4350)
c5db23f296 [wpimath] Add Eigen sparse matrix and iterative solver support (#4349)
44abc8dfa6 [upstream_utils] Remove git version from upstream patches (#4351)
3fdb2f767d [wpimath] Add comments with Ramsete equations (#4348)
0485f05da9 [wpilibjExamples] Upgrade jacoco to match allwpilib (#4346)
0a5eb65231 [wpinet] Handle empty txt block for mdns announcer (#4072)
19ffebaf3e [wpilib] Add reference to I2C Lockup to API Docs (NFC) (#4340)
ce1a90d639 [hal] Replace SerialHelper "goto done" with continue (#4342)
d25af48797 [ci] Make upstream_utils CI fail on untracked files (#4339)
ebb836dacb [examples] Fix negations in event loop examples (#4334)
d83e202f00 [upstream_utils] Update paths in update_fmt.py (#4338)
3ccf806064 [wpimath] Remove redundant LinearFilter.finiteDifference() argument (#4335)
6f1e01f8bd [wpimath] Document example of online filtering for LinearFilter.finiteDifference() (#4336)
1023c34b1c [readme] Update location of ni-libraries (#4333)
faa29d596c [wpilib] Improve Notifier docs (NFC) (#4326)
add00a96ed [wpimath] Improve DifferentialDriveAccelerationLimiter docs (NFC) (#4323)
82fac41244 [wpimath] Better document trackwidth parameters (NFC) (#4324)
5eb44e22a9 Format Python scripts with black (NFC) (#4325)
2e09fa7325 [build] Fix mpack cmake (#4322)
fe3c24b1ee [command] Add ignoringDisable decorator (#4305)
aa221597bc [build] Add M1 builds, change arm name, update to 2023 deps (#4315)
579a8ee229 [ci] Use one worker for Windows release Gradle build (#4318)
5105c5eab6 [wpilibj] Change "final" to "exit" in the IterativeRobotBase JavaDoc (NFC) (#4317)
787fe6e7a5 [wpiutil] Separate third party libraries (#4190)
6671f8d099 [wpigui] Update portable file dialogs (#4316)
9ac9b69aa2 [command] Reorder Scheduler operations (#4261)
e61028cb18 [build] halsim_gui: Add wpinet dependency (#4313)
661d23eaf5 [glass] Add precision setting for NetworkTable view (#4311)
666040e3e5 [hal] Throw exceptions for invalid sizes in I2C and SPI JNI (#4312)
aebc272449 [build] Upgrade to spotbugs Gradle plugin 5.0.8 (#4310)
fd884581e4 [wpilib] Add BooleanEvent/Trigger factories on HID classes (#4247)
9b1bf5c7f1 [wpimath] Move Drake and Eigen to thirdparty folders (#4307)
c9e620a920 [wpilibc] Change EventLoop data structure to vector (#4304)
41d40dd62f [wpinet] Fix libuv unused variable warning on Mac (#4299)
30f5b68264 [wpinet] Fix JNI loading error (#4295)
f7b3f4b90e [examples] Getting Started: Change Joystick to XboxController (#4194)
a99c11c14c [wpimath] Replace UKF implementation with square root form (#4168)
45b7fc445b [wpilib] Add EventLoop (#4104)
16a4888c52 [wpilib] Default off LiveWindow telemetry (#4301)
17752f1337 [ci] Split debug and release Windows builds (#4277)
abb45a68db [commands] Remove custom test wrappers (#4296)
1280a54ef3 [upstream_utils]: Make work with Python 3.8 (#4298)
f2d243fa68 [build] Change defaults for Java lints (#4300)
a4787130f4 Update using development build to work with 2023 gradlerio (#4294)
af7985e46c [wpiutil] Use invoke_result_t instead of result_of in future.h (#4293)
e9d1b5c2d0 [hal] Remove deprecated SimDevice functions (#4209)
45b598d236 [wpilibj] Add toString() methods to Color and Color8Bit (#4286)
fc37265da5 [wpimath] Add angle measurement convention to ArmFeedforward docs (NFC) (#4285)
a4ec13eb0e [wpilibjexamples] Remove unnecessary voltage desaturation
2fa52007af [wpilibc] Use GetBatteryVoltage() in MotorController::SetVoltage
d9f9cd1140 [wpimath] Reset prev_time on pose estimator reset (#4283)
8b6df88783 [wpilibj] Tachometer.getFrequency(): Fix bug (#4281)
345cff08c0 [wpiutil] Make wpi::array constexpr (#4278)
57428112ac [wpimath] Upgrade to Drake v1.3.0 (#4279)
a18d4ff154 [build] Fix tools not being copied when built with -Ponly* (#4276)
d1cd07b9f3 [wpigui] Add OpenURL (#4273)
e67f8e917a [glass] Use glfwSetKeyCallback for Enter key remap (#4275)
be2fedfe50 [wpimath] Add stdexcept include for std::invalid_argument (IWYU) (#4274)
7ad2be172e [build] Update native-utils to 2023.0.1 (#4272)
abc605c9c9 [ci] Update workflows to 20.04 base image (#4271)
3e94805220 [wpiutil] Reduce llvm collections patches (#4268)
db2e1d170e [upstream_utils] Document how to update thirdparty libraries (#4253)
96ebdcaf16 [wpimath] Remove unused Eigen AutoDiff module (#4267)
553b2a3b12 [upstream_utils] Fix stackwalker (#4265)
3e13ef42eb [wpilibc] Add missing std::array #include (include-what-you-use) (#4266)
d651a1fcec Fix internal deprecation warnings (#4257)
b193b318c1 [commands] Add unless() decorator (#4244)
ef3714223b [commands] Remove docs reference to obsolete interrupted() method (NFC) (#4262)
3d8dbbbac3 [readme] Add quickstart (#4225)
013efdde25 [wpinet] Wrap a number of newer libuv features (#4260)
816aa4e465 [wpilib] Add Pneumatics sim classes (#4033)
046c2c8972 [wpilibc] Rename SpeedControllerGroupTest.cpp (#4258)
d80e9cdf64 [upstream_utils] Use shallow clones for thirdparty repos (#4255)
7576136b4a [upstream_utils] Make update_llvm.py executable (#4254)
c3b223ce60 [wpiutil] Vendor llvm and update to 13.0.0 (#4224)
5aa67f56e6 [wpimath] Clean up math comments (#4252)
fff4d1f44e [wpimath] Extend Eigen warning suppression to GCC 12 (#4251)
0d9956273c [wpimath] Add CoordinateSystem.convert() translation and rotation overloads (#4227)
3fada4e0b4 [wpinet] Update to libuv 1.44.1 (#4232)
65b23ac45e [wpilibc] Fix return value of DriverStation::GetJoystickAxisType() (#4230)
4ac34c0141 [upstream_utils] Cleanup update_libuv.py (#4249)
8bd614bb1e [upstream_utils] Use "git am" instead of "git apply" for patches (#4248)
4253d6d5f0 [upstream_utils] Apply "git am" patches individually (#4250)
6a4752dcdc Fix GCC 12.1 warning false positives (#4246)
5876b40f08 [wpimath] Memoize CoordinateSystem and CoordinateAxis statics (#4241)
5983434a70 [cameraserver] Replace IterativeRobot in comment sample code with TimedRobot (#4238)
a3d44a1e69 [wpimath] Add Translation2d.getAngle() (#4217)
d364bbd5a7 [upstream_utils] Give vendor update scripts execute permissions (#4226)
f341e1b2be [wpimath] Document standard coordinate systems better (NFC) (#4228)
9af389b200 [wpinet] AddrToName: Initialize name (#4229)
2ae4adf2d7 [ci] Add wpiformat command to PRs (#4223)
178b2a1e88 Contributing.md: Correct version of clang-format used (#4222)
18db343cdc [wpiutil, wpinet] Vendor libuv, stack walker (#4219)
f0c821282a [build] Use artifactory mirror (#4220)
d673ead481 [wpinet] Move network portions of wpiutil into new wpinet library (#4077)
b33715db15 [wpimath] Add CoordinateSystem class (#4214)
99424ad562 [sim] Allow creating a PWMSim object from a PWMMotorController (#4039)
dc6f641fd2 [wpimath] PIDController: Reset position and velocity error when reset() is called. (#4064)
f20a20f3f1 [wpimath] Add 3D geometry classes (#4175)
708a4bc3bc [wpimath] Conserve previously calculated swerve module angles when updating states for stationary ChassisSpeeds (#4208)
ef7ed21a9d [wpimath] Improve accuracy of ComputerVisionUtil.calculateDistanceToTarget() (#4215)
b1abf455c1 [wpimath] LTVUnicycleController: Use LUT, provide default hyperparameters (#4213)
d5456cf278 [wpimath] LTVDifferentialDriveController: Remove unused variable (#4212)
99343d40ba [command] Remove old command-based framework (#4211)
ee03a7ad3b Remove most 2022 deprecations (#4205)
ce1a7d698a [wpimath] Refactor WheelVoltages inner class to a separate file (#4203)
87bf70fa8e [wpimath] Add LTV controllers (#4094)
ebd2a303bf [wpimath] Remove deprecated MakeMatrix() function (#4202)
e28776d361 [wpimath] LinearSystemLoop: Add extern templates for common cases
dac1429aa9 [wpimath] LQR: Use extern template instead of Impl class
e767605e94 [wpimath] Add typedefs for common types
97c493241f [wpimath] UnscentedKalmanFilter: Move implementation out-of-line
8ea90d8bc9 [wpimath] ExtendedKalmanFilter: Move implementation out-of-line
ae7b1851ec [wpimath] KalmanFilter: Use extern template instead of Impl class
e3d62c22d3 [wpimath] Add extern templates for common cases
7200c4951d [wpiutil] SymbolExports: Add WPILIB_IMPORTS for dllimport
84056c9347 [wpiutil] SymbolExports: Add EXPORT_TEMPLATE_DECLARE/DEFINE
09cf6eeecb [wpimath] ApplyDeadband: add a scale param (#3865)
03230fc842 [build,ci] Enable artifactory build cache (#4200)
63cf3aaa3f [examples] Don't square ArcadeDrive inputs in auto (#4201)
18ff694f02 [wpimath] Add Rotation2d.fromRadians factory (#4178)
4f79ceedd9 [wpilibc] Add missing #include (#4198)
f7ca72fb41 [command] Rename PerpetualCommand to EndlessCommand (#4177)
a06b3f0307 [hal] Correct documentation on updateNotifierAlarm (#4156)
d926dd1610 [wpimath] Fix pose estimator performance (#4111)
51bc893bc5 [wpiutil] CircularBuffer: Change Java package-private methods to public (#4181)
fbe761f7f6 [build] Increase Gradle JVM heap size (#4172)
5ebe911933 [wpimath] Add DifferentialDriveAccelerationLimiter (#4091)
3919250da2 [wpilibj] Remove finalizers (#4158)
b3aee28388 [commands] Allow BooleanSupplier for Trigger operations (#4103)
9d20ab3024 [wpilib] Allow disabling ElevatorSim gravity (#4145)
aaa69f6717 [ci] Remove 32-bit Windows builds (#4078)
355a11a414 Update Java linters and fix new PMD errors (#4157)
ffc69d406c [examples] Reduce suggested acceleration in Ramsete example (#4171)
922d50079a [wpimath] Units: fix comment in degreesToRotations (NFC) (#4159)
dd163b62ae [wpimath] Rotation2d: Add factory method that uses rotations (#4166)
bd80e220b9 [ci] Upgrade CMake actions (#4161)
aef4b16d4c [wpimath] Remove unnecessary NOLINT in LinearPlantInversionFeedforward (NFC) (#4155)
975171609e [wpilib] Compressor: Rename enabled to isEnabled (#4147)
5bf46a9093 [wpimath] Add ComputerVisionUtil (#4124)
f27a1f9bfb [commands] Fix JoystickButton.getAsBoolean (#4131)
1b26e2d5da [commands] Add RepeatCommand (#4009)
88222daa3d [hal] Fix misspelling in AnalogInput/Output docs (NFC) (#4153)
81c5b41ce1 [wpilibj] Document MechanismLigament2d angle unit (NFC) (#4142)
9650e6733e [wpiutil] DataLog: Document finish and thread safety (NFC) (#4140)
c8905ec29a [wpimath] Remove ImplicitModelFollower dt argument (#4119)
b4620f01f9 [wpimath] Fix Rotation2d interpolation in Java (#4125)
2e462a19d3 [wpimath] Constexprify units unary operators (#4138)
069f932e59 [build] Fix gl3w cmake build (#4139)
126e3de91a [wpilibc] Remove unused SetPriority() call from Ultrasonic (#4123)
ba0dccaae4 [wpimath] Fix reference to Rotation2d.fromRadians() (#4118)
e1b6e5f212 [wpilib] Improve MotorSafety documentation (NFC) (#4120)
8d79dc8738 [wpimath] Add ImplicitModelFollower (#4056)
78108c2aba [wpimath] Fix PIDController having incorrect error after calling SetSetpoint() (#4070)
cdafc723fb [examples] Remove unused LinearPlantInversionFeedforward includes (#4069)
0d70884dce [wpimath] Add InterpolatedTreeMap (#4073)
765efa325e [wpimath] Remove redundant column index from vectors (#4116)
89ffcbbe41 [wpimath] Update TrapezoidProfile class name in comment (NFC) (#4107)
95ae23b0e7 [wpimath] Improve EKF numerical stability (#4093)
d5cb6fed67 [wpimath] Support zero cost entries in MakeCostMatrix() (#4100)
d0fef18378 [wpimath] Remove redundant `this.` from ExtendedKalmanFilter.java (#4115)
d640c0f41f [wpimath] Fix pose estimator local measurement standard deviation docs (NFC) (#4113)
a2fa5e3ff7 [wpilibc] BatterySim: Provide non-initializer list versions of Calculate (#4076)
a3eea9958e [hal] Add link to FRC CAN Spec (NFC) (#4086)
db27331d7b [wpilib] Update DifferentialDrive docs (NFC) (#4085)
fdfb31f164 [dlt] Export boolean[] values (#4082)
f93c3331b3 [wpigui] disable changing directory when initializing on MacOS (#4092)
ab7ac4fbb9 [build] Fix various warnings in cmake builds (#4081)
bc39a1a293 [wpilibc] Fix moved pneumatics objects not destructing properly (#4068)
2668130e70 [wpimath] Remove SwerveDrivePoseEstimator encoder reset warning (#4066)
d27ed3722b [ci] Set actions workflow concurrency (#4060)
dae18308c9 [wpimath] Minor fixes to Rotation2d docs (NFC) (#4055)
d66555e42f [datalogtool] Add datalogtool
9f52d8a3b1 [wpilib] DriverStation: Add DataLog support for modes and joystick data
757ea91932 [wpilib] Add DataLogManager
02a804f1c5 [ntcore] Add DataLog support
9b500df0d9 [wpiutil] Add high speed data logging
5a89575b3a [wpiutil] Import customized LLVM MemoryBuffer
b8c4d7527b [wpiutil] Add MappedFileRegion
ac5d46cfa7 [wpilibc] Fix ProfiledPID SetTolerance default velocity value (#4054)
bc9e96e86f [wpilib] Absolute Encoder API and behavior fixes (#4052)
f88c435dd0 [hal] Add mechanism to cancel all periodic callbacks (#4049)
Change-Id: I49aa5b08abbefc7a045e99e19d48ce2cd8fc4d1b
git-subtree-dir: third_party/allwpilib
git-subtree-split: 83f1860047c86aa3330fcb41caf3b2047e074804
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/wpilibc/src/dev/native/cpp/main.cpp b/wpilibc/src/dev/native/cpp/main.cpp
index 28fac9d..fcc55b1 100644
--- a/wpilibc/src/dev/native/cpp/main.cpp
+++ b/wpilibc/src/dev/native/cpp/main.cpp
@@ -9,6 +9,6 @@
int main() {
fmt::print("Hello World\n");
- fmt::print("{}\n", HAL_GetRuntimeType());
+ fmt::print("{}\n", static_cast<int32_t>(HAL_GetRuntimeType()));
fmt::print("{}\n", GetWPILibVersion());
}
diff --git a/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp b/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp
index 25d674f..7048720 100644
--- a/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp
+++ b/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp
@@ -22,11 +22,11 @@
#include <algorithm>
#include <cmath>
+#include <numbers>
#include <string>
#include <hal/HAL.h>
#include <networktables/NTSendableBuilder.h>
-#include <wpi/numbers>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/Errors.h"
@@ -56,14 +56,14 @@
const char* function, const S& format,
Args&&... args) {
frc::ReportErrorV(status, file, line, function, format,
- fmt::make_args_checked<Args...>(format, args...));
+ fmt::make_format_args(args...));
}
} // namespace
#define REPORT_WARNING(msg) \
- ADISReportError(warn::Warning, __FILE__, __LINE__, __FUNCTION__, "{}", msg);
+ ADISReportError(warn::Warning, __FILE__, __LINE__, __FUNCTION__, msg);
#define REPORT_ERROR(msg) \
- ADISReportError(err::Error, __FILE__, __LINE__, __FUNCTION__, "{}", msg)
+ ADISReportError(err::Error, __FILE__, __LINE__, __FUNCTION__, msg)
ADIS16448_IMU::ADIS16448_IMU()
: ADIS16448_IMU(kZ, SPI::Port::kMXP, CalibrationTime::_512ms) {}
@@ -74,6 +74,8 @@
m_spi_port(port),
m_simDevice("Gyro:ADIS16448", port) {
if (m_simDevice) {
+ m_connected =
+ m_simDevice.CreateBoolean("connected", hal::SimDevice::kInput, true);
m_simGyroAngleX =
m_simDevice.CreateDouble("gyro_angle_x", hal::SimDevice::kInput, 0.0);
m_simGyroAngleY =
@@ -102,8 +104,8 @@
DigitalOutput* m_reset_out = new DigitalOutput(18); // Drive MXP DIO8 low
Wait(10_ms); // Wait 10ms
delete m_reset_out;
- new DigitalInput(18); // Set MXP DIO8 high
- Wait(500_ms); // Wait 500ms for reset to complete
+ m_reset_in = new DigitalInput(18); // Set MXP DIO8 high
+ Wait(500_ms); // Wait 500ms for reset to complete
ConfigCalTime(cal_time);
@@ -143,13 +145,21 @@
// TODO: Find what the proper pin is to turn this LED
// Drive MXP PWM5 (IMU ready LED) low (active low)
- new DigitalOutput(19);
+ m_status_led = new DigitalOutput(19);
}
// Report usage and post data to DS
HAL_Report(HALUsageReporting::kResourceType_ADIS16448, 0);
wpi::SendableRegistry::AddLW(this, "ADIS16448", port);
+ m_connected = true;
+}
+
+bool ADIS16448_IMU::IsConnected() const {
+ if (m_simConnected) {
+ return m_simConnected.Get();
+ }
+ return m_connected;
}
/**
@@ -186,7 +196,7 @@
while (data_count > 0) {
/* Dequeue 200 at a time, or the remainder of the buffer if less than
* 200 */
- m_spi->ReadAutoReceivedData(trashBuffer, std::min(200, data_count),
+ m_spi->ReadAutoReceivedData(trashBuffer, (std::min)(200, data_count),
0_s);
/* Update remaining buffer count */
data_count = m_spi->ReadAutoReceivedData(trashBuffer, 0, 0_s);
@@ -197,9 +207,7 @@
if (m_spi == nullptr) {
m_spi = new SPI(m_spi_port);
m_spi->SetClockRate(1000000);
- m_spi->SetMSBFirst();
- m_spi->SetSampleDataOnTrailingEdge();
- m_spi->SetClockActiveLow();
+ m_spi->SetMode(frc::SPI::Mode::kMode3);
m_spi->SetChipSelectActiveLow();
ReadRegister(PROD_ID); // Dummy read
@@ -323,7 +331,7 @@
void ADIS16448_IMU::Calibrate() {
std::scoped_lock sync(m_mutex);
// Calculate the running average
- int gyroAverageSize = std::min(m_accum_count, m_avg_size);
+ int gyroAverageSize = (std::min)(m_accum_count, m_avg_size);
double accum_gyro_rate_x = 0.0;
double accum_gyro_rate_y = 0.0;
double accum_gyro_rate_z = 0.0;
@@ -387,6 +395,14 @@
}
void ADIS16448_IMU::Close() {
+ if (m_reset_in != nullptr) {
+ delete m_reset_in;
+ m_reset_in = nullptr;
+ }
+ if (m_status_led != nullptr) {
+ delete m_status_led;
+ m_status_led = nullptr;
+ }
if (m_thread_active) {
m_thread_active = false;
if (m_acquire_task.joinable()) {
@@ -624,29 +640,29 @@
/* Complementary filter functions */
double ADIS16448_IMU::FormatFastConverge(double compAngle, double accAngle) {
- if (compAngle > accAngle + wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
- } else if (accAngle > compAngle + wpi::numbers::pi) {
- compAngle = compAngle + 2.0 * wpi::numbers::pi;
+ if (compAngle > accAngle + std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
+ } else if (accAngle > compAngle + std::numbers::pi) {
+ compAngle = compAngle + 2.0 * std::numbers::pi;
}
return compAngle;
}
double ADIS16448_IMU::FormatRange0to2PI(double compAngle) {
- while (compAngle >= 2 * wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
+ while (compAngle >= 2 * std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
}
while (compAngle < 0.0) {
- compAngle = compAngle + 2.0 * wpi::numbers::pi;
+ compAngle = compAngle + 2.0 * std::numbers::pi;
}
return compAngle;
}
double ADIS16448_IMU::FormatAccelRange(double accelAngle, double accelZ) {
if (accelZ < 0.0) {
- accelAngle = wpi::numbers::pi - accelAngle;
+ accelAngle = std::numbers::pi - accelAngle;
} else if (accelZ > 0.0 && accelAngle < 0.0) {
- accelAngle = 2.0 * wpi::numbers::pi + accelAngle;
+ accelAngle = 2.0 * std::numbers::pi + accelAngle;
}
return accelAngle;
}
@@ -657,8 +673,8 @@
compAngle =
m_alpha * (compAngle + omega * m_dt) + (1.0 - m_alpha) * accelAngle;
compAngle = FormatRange0to2PI(compAngle);
- if (compAngle > wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
+ if (compAngle > std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
}
return compAngle;
}
@@ -673,7 +689,8 @@
/* Check max */
if (DecimationSetting > 9) {
- REPORT_ERROR("Attemted to write an invalid decimation value. Capping at 9");
+ REPORT_ERROR(
+ "Attempted to write an invalid decimation value. Capping at 9");
DecimationSetting = 9;
}
@@ -867,8 +884,6 @@
**/
void ADIS16448_IMU::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("ADIS16448 IMU");
- auto yaw_angle = builder.GetEntry("Yaw Angle").GetHandle();
- builder.SetUpdateTable([=]() {
- nt::NetworkTableEntry(yaw_angle).SetDouble(GetAngle().value());
- });
+ builder.AddDoubleProperty(
+ "Yaw Angle", [=, this] { return GetAngle().value(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp b/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp
index f48d827..e1cd986 100644
--- a/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp
+++ b/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp
@@ -19,11 +19,11 @@
#include <frc/Timer.h>
#include <cmath>
+#include <numbers>
#include <string>
#include <hal/HAL.h>
#include <networktables/NTSendableBuilder.h>
-#include <wpi/numbers>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/Errors.h"
@@ -50,14 +50,14 @@
const char* function, const S& format,
Args&&... args) {
frc::ReportErrorV(status, file, line, function, format,
- fmt::make_args_checked<Args...>(format, args...));
+ fmt::make_format_args(args...));
}
} // namespace
#define REPORT_WARNING(msg) \
- ADISReportError(warn::Warning, __FILE__, __LINE__, __FUNCTION__, "{}", msg);
+ ADISReportError(warn::Warning, __FILE__, __LINE__, __FUNCTION__, msg);
#define REPORT_ERROR(msg) \
- ADISReportError(err::Error, __FILE__, __LINE__, __FUNCTION__, "{}", msg)
+ ADISReportError(err::Error, __FILE__, __LINE__, __FUNCTION__, msg)
/**
* Constructor.
@@ -72,6 +72,8 @@
m_calibration_time(static_cast<uint16_t>(cal_time)),
m_simDevice("Gyro:ADIS16470", port) {
if (m_simDevice) {
+ m_connected =
+ m_simDevice.CreateBoolean("connected", hal::SimDevice::kInput, true);
m_simGyroAngleX =
m_simDevice.CreateDouble("gyro_angle_x", hal::SimDevice::kInput, 0.0);
m_simGyroAngleY =
@@ -101,8 +103,8 @@
new DigitalOutput(27); // Drive SPI CS2 (IMU RST) low
Wait(10_ms); // Wait 10ms
delete m_reset_out;
- new DigitalInput(27); // Set SPI CS2 (IMU RST) high
- Wait(500_ms); // Wait 500ms for reset to complete
+ m_reset_in = new DigitalInput(27); // Set SPI CS2 (IMU RST) high
+ Wait(500_ms); // Wait 500ms for reset to complete
// Configure standard SPI
if (!SwitchToStandardSPI()) {
@@ -140,13 +142,21 @@
REPORT_WARNING("ADIS16470 IMU Successfully Initialized!");
// Drive SPI CS3 (IMU ready LED) low (active low)
- new DigitalOutput(28);
+ m_status_led = new DigitalOutput(28);
}
// Report usage and post data to DS
HAL_Report(HALUsageReporting::kResourceType_ADIS16470, 0);
wpi::SendableRegistry::AddLW(this, "ADIS16470", port);
+ m_connected = true;
+}
+
+bool ADIS16470_IMU::IsConnected() const {
+ if (m_simConnected) {
+ return m_simConnected.Get();
+ }
+ return m_connected;
}
/**
@@ -183,9 +193,9 @@
while (data_count > 0) {
/* Receive data, max of 200 words at a time (prevent potential segfault)
*/
- m_spi->ReadAutoReceivedData(trashBuffer, std::min(data_count, 200),
+ m_spi->ReadAutoReceivedData(trashBuffer, (std::min)(data_count, 200),
0_s);
- /*Get the reamining data count */
+ /*Get the remaining data count */
data_count = m_spi->ReadAutoReceivedData(trashBuffer, 0, 0_s);
}
}
@@ -194,9 +204,7 @@
if (m_spi == nullptr) {
m_spi = new SPI(m_spi_port);
m_spi->SetClockRate(2000000);
- m_spi->SetMSBFirst();
- m_spi->SetSampleDataOnTrailingEdge();
- m_spi->SetClockActiveLow();
+ m_spi->SetMode(frc::SPI::Mode::kMode3);
m_spi->SetChipSelectActiveLow();
ReadRegister(PROD_ID); // Dummy read
@@ -441,6 +449,14 @@
}
void ADIS16470_IMU::Close() {
+ if (m_reset_in != nullptr) {
+ delete m_reset_in;
+ m_reset_in = nullptr;
+ }
+ if (m_status_led != nullptr) {
+ delete m_status_led;
+ m_status_led = nullptr;
+ }
if (m_thread_active) {
m_thread_active = false;
if (m_acquire_task.joinable()) {
@@ -469,7 +485,7 @@
* @brief Main acquisition loop. Typically called asynchronously and free-wheels
*while the robot code is active.
*
- * This is the main acquisiton loop for the IMU. During each iteration, data
+ * This is the main acquisition loop for the IMU. During each iteration, data
*read using auto SPI is extracted from the FPGA FIFO, split, scaled, and
*integrated. Each X, Y, and Z value is 32-bits split across 4 indices (bytes)
*in the buffer. Auto SPI puts one byte in each index location. Each index is
@@ -641,29 +657,29 @@
/* Complementary filter functions */
double ADIS16470_IMU::FormatFastConverge(double compAngle, double accAngle) {
- if (compAngle > accAngle + wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
- } else if (accAngle > compAngle + wpi::numbers::pi) {
- compAngle = compAngle + 2.0 * wpi::numbers::pi;
+ if (compAngle > accAngle + std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
+ } else if (accAngle > compAngle + std::numbers::pi) {
+ compAngle = compAngle + 2.0 * std::numbers::pi;
}
return compAngle;
}
double ADIS16470_IMU::FormatRange0to2PI(double compAngle) {
- while (compAngle >= 2 * wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
+ while (compAngle >= 2 * std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
}
while (compAngle < 0.0) {
- compAngle = compAngle + 2.0 * wpi::numbers::pi;
+ compAngle = compAngle + 2.0 * std::numbers::pi;
}
return compAngle;
}
double ADIS16470_IMU::FormatAccelRange(double accelAngle, double accelZ) {
if (accelZ < 0.0) {
- accelAngle = wpi::numbers::pi - accelAngle;
+ accelAngle = std::numbers::pi - accelAngle;
} else if (accelZ > 0.0 && accelAngle < 0.0) {
- accelAngle = 2.0 * wpi::numbers::pi + accelAngle;
+ accelAngle = 2.0 * std::numbers::pi + accelAngle;
}
return accelAngle;
}
@@ -674,8 +690,8 @@
compAngle =
m_alpha * (compAngle + omega * m_dt) + (1.0 - m_alpha) * accelAngle;
compAngle = FormatRange0to2PI(compAngle);
- if (compAngle > wpi::numbers::pi) {
- compAngle = compAngle - 2.0 * wpi::numbers::pi;
+ if (compAngle > std::numbers::pi) {
+ compAngle = compAngle - 2.0 * std::numbers::pi;
}
return compAngle;
}
@@ -802,8 +818,6 @@
**/
void ADIS16470_IMU::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("ADIS16470 IMU");
- auto yaw_angle = builder.GetEntry("Yaw Angle").GetHandle();
- builder.SetUpdateTable([=]() {
- nt::NetworkTableEntry(yaw_angle).SetDouble(GetAngle().value());
- });
+ builder.AddDoubleProperty(
+ "Yaw Angle", [=, this] { return GetAngle().value(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp
index 484e690..a23846d 100644
--- a/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp
+++ b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp
@@ -5,6 +5,7 @@
#include "frc/ADXL345_I2C.h"
#include <hal/FRCUsageReporting.h>
+#include <networktables/DoubleTopic.h>
#include <networktables/NTSendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
@@ -93,13 +94,13 @@
void ADXL345_I2C::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("3AxisAccelerometer");
- auto x = builder.GetEntry("X").GetHandle();
- auto y = builder.GetEntry("Y").GetHandle();
- auto z = builder.GetEntry("Z").GetHandle();
- builder.SetUpdateTable([=] {
- auto data = GetAccelerations();
- nt::NetworkTableEntry(x).SetDouble(data.XAxis);
- nt::NetworkTableEntry(y).SetDouble(data.YAxis);
- nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
- });
+ builder.SetUpdateTable(
+ [this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
+ y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
+ z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
+ auto data = GetAccelerations();
+ x.Set(data.XAxis);
+ y.Set(data.YAxis);
+ z.Set(data.ZAxis);
+ });
}
diff --git a/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp
index 9a95bcc..1dc4c5b 100644
--- a/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp
+++ b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp
@@ -5,6 +5,7 @@
#include "frc/ADXL345_SPI.h"
#include <hal/FRCUsageReporting.h>
+#include <networktables/DoubleTopic.h>
#include <networktables/NTSendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
@@ -21,9 +22,7 @@
m_simZ = m_simDevice.CreateDouble("z", hal::SimDevice::kInput, 0.0);
}
m_spi.SetClockRate(500000);
- m_spi.SetMSBFirst();
- m_spi.SetSampleDataOnTrailingEdge();
- m_spi.SetClockActiveLow();
+ m_spi.SetMode(frc::SPI::Mode::kMode3);
m_spi.SetChipSelectActiveHigh();
uint8_t commands[2];
@@ -120,13 +119,13 @@
void ADXL345_SPI::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("3AxisAccelerometer");
- auto x = builder.GetEntry("X").GetHandle();
- auto y = builder.GetEntry("Y").GetHandle();
- auto z = builder.GetEntry("Z").GetHandle();
- builder.SetUpdateTable([=] {
- auto data = GetAccelerations();
- nt::NetworkTableEntry(x).SetDouble(data.XAxis);
- nt::NetworkTableEntry(y).SetDouble(data.YAxis);
- nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
- });
+ builder.SetUpdateTable(
+ [this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
+ y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
+ z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
+ auto data = GetAccelerations();
+ x.Set(data.XAxis);
+ y.Set(data.YAxis);
+ z.Set(data.ZAxis);
+ });
}
diff --git a/wpilibc/src/main/native/cpp/ADXL362.cpp b/wpilibc/src/main/native/cpp/ADXL362.cpp
index deda965..fa0a8a3 100644
--- a/wpilibc/src/main/native/cpp/ADXL362.cpp
+++ b/wpilibc/src/main/native/cpp/ADXL362.cpp
@@ -5,6 +5,7 @@
#include "frc/ADXL362.h"
#include <hal/FRCUsageReporting.h>
+#include <networktables/DoubleTopic.h>
#include <networktables/NTSendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
@@ -43,9 +44,7 @@
}
m_spi.SetClockRate(3000000);
- m_spi.SetMSBFirst();
- m_spi.SetSampleDataOnTrailingEdge();
- m_spi.SetClockActiveLow();
+ m_spi.SetMode(frc::SPI::Mode::kMode3);
m_spi.SetChipSelectActiveLow();
uint8_t commands[3];
@@ -56,7 +55,7 @@
commands[2] = 0;
m_spi.Transaction(commands, commands, 3);
if (commands[2] != 0xF2) {
- FRC_ReportError(err::Error, "{}", "could not find ADXL362");
+ FRC_ReportError(err::Error, "could not find ADXL362");
m_gsPerLSB = 0.0;
return;
}
@@ -184,13 +183,13 @@
void ADXL362::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("3AxisAccelerometer");
- auto x = builder.GetEntry("X").GetHandle();
- auto y = builder.GetEntry("Y").GetHandle();
- auto z = builder.GetEntry("Z").GetHandle();
- builder.SetUpdateTable([=] {
- auto data = GetAccelerations();
- nt::NetworkTableEntry(x).SetDouble(data.XAxis);
- nt::NetworkTableEntry(y).SetDouble(data.YAxis);
- nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
- });
+ builder.SetUpdateTable(
+ [this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
+ y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
+ z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
+ auto data = GetAccelerations();
+ x.Set(data.XAxis);
+ y.Set(data.YAxis);
+ z.Set(data.ZAxis);
+ });
}
diff --git a/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp
index 5a2f625..4d4b22d 100644
--- a/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp
+++ b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp
@@ -32,21 +32,21 @@
ADXRS450_Gyro::ADXRS450_Gyro(SPI::Port port)
: m_spi(port), m_port(port), m_simDevice("Gyro:ADXRS450", port) {
if (m_simDevice) {
+ m_simConnected =
+ m_simDevice.CreateBoolean("connected", hal::SimDevice::kInput, true);
m_simAngle =
m_simDevice.CreateDouble("angle_x", hal::SimDevice::kInput, 0.0);
m_simRate = m_simDevice.CreateDouble("rate_x", hal::SimDevice::kInput, 0.0);
}
m_spi.SetClockRate(3000000);
- m_spi.SetMSBFirst();
- m_spi.SetSampleDataOnLeadingEdge();
- m_spi.SetClockActiveHigh();
+ m_spi.SetMode(frc::SPI::Mode::kMode0);
m_spi.SetChipSelectActiveLow();
if (!m_simDevice) {
// Validate the part ID
if ((ReadRegister(kPIDRegister) & 0xff00) != 0x5200) {
- FRC_ReportError(err::Error, "{}", "could not find ADXRS450 gyro");
+ FRC_ReportError(err::Error, "could not find ADXRS450 gyro");
return;
}
@@ -59,6 +59,14 @@
HAL_Report(HALUsageReporting::kResourceType_ADXRS450, port + 1);
wpi::SendableRegistry::AddLW(this, "ADXRS450_Gyro", port);
+ m_connected = true;
+}
+
+bool ADXRS450_Gyro::IsConnected() const {
+ if (m_simConnected) {
+ return m_simConnected.Get();
+ }
+ return m_connected;
}
static bool CalcParity(int v) {
@@ -139,5 +147,5 @@
void ADXRS450_Gyro::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Gyro");
builder.AddDoubleProperty(
- "Value", [=] { return GetAngle(); }, nullptr);
+ "Value", [=, this] { return GetAngle(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/AddressableLED.cpp b/wpilibc/src/main/native/cpp/AddressableLED.cpp
index 759c386..538dc10 100644
--- a/wpilibc/src/main/native/cpp/AddressableLED.cpp
+++ b/wpilibc/src/main/native/cpp/AddressableLED.cpp
@@ -51,9 +51,9 @@
static_assert(sizeof(AddressableLED::LEDData) == sizeof(HAL_AddressableLEDData),
"LED Structs MUST be the same size");
-void AddressableLED::SetData(wpi::span<const LEDData> ledData) {
+void AddressableLED::SetData(std::span<const LEDData> ledData) {
int32_t status = 0;
- HAL_WriteAddressableLEDData(m_handle, ledData.begin(), ledData.size(),
+ HAL_WriteAddressableLEDData(m_handle, ledData.data(), ledData.size(),
&status);
FRC_CheckErrorStatus(status, "Port {}", m_port);
}
diff --git a/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp
index 0b39e64..ca8af7d 100644
--- a/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp
@@ -21,7 +21,7 @@
AnalogAccelerometer::AnalogAccelerometer(AnalogInput* channel)
: m_analogInput(channel, wpi::NullDeleter<AnalogInput>()) {
if (!channel) {
- throw FRC_MakeError(err::NullParameter, "{}", "channel");
+ throw FRC_MakeError(err::NullParameter, "channel");
}
InitAccelerometer();
}
@@ -29,7 +29,7 @@
AnalogAccelerometer::AnalogAccelerometer(std::shared_ptr<AnalogInput> channel)
: m_analogInput(channel) {
if (!channel) {
- throw FRC_MakeError(err::NullParameter, "{}", "channel");
+ throw FRC_MakeError(err::NullParameter, "channel");
}
InitAccelerometer();
}
@@ -49,7 +49,7 @@
void AnalogAccelerometer::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Accelerometer");
builder.AddDoubleProperty(
- "Value", [=] { return GetAcceleration(); }, nullptr);
+ "Value", [=, this] { return GetAcceleration(); }, nullptr);
}
void AnalogAccelerometer::InitAccelerometer() {
diff --git a/wpilibc/src/main/native/cpp/AnalogEncoder.cpp b/wpilibc/src/main/native/cpp/AnalogEncoder.cpp
index 5f26e87..0c29bea 100644
--- a/wpilibc/src/main/native/cpp/AnalogEncoder.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogEncoder.cpp
@@ -10,6 +10,7 @@
#include "frc/AnalogInput.h"
#include "frc/Counter.h"
#include "frc/Errors.h"
+#include "frc/RobotController.h"
using namespace frc;
@@ -42,6 +43,8 @@
if (m_simDevice) {
m_simPosition = m_simDevice.CreateDouble("Position", false, 0.0);
+ m_simAbsolutePosition =
+ m_simDevice.CreateDouble("absPosition", hal::SimDevice::kInput, 0.0);
}
m_analogTrigger.SetLimitsVoltage(1.25, 3.75);
@@ -54,6 +57,11 @@
m_analogInput->GetChannel());
}
+static bool DoubleEquals(double a, double b) {
+ constexpr double epsilon = 0.00001;
+ return std::abs(a - b) < epsilon;
+}
+
units::turn_t AnalogEncoder::Get() const {
if (m_simPosition) {
return units::turn_t{m_simPosition.Get()};
@@ -66,7 +74,8 @@
auto pos = m_analogInput->GetVoltage();
auto counter2 = m_counter.Get();
auto pos2 = m_analogInput->GetVoltage();
- if (counter == counter2 && pos == pos2) {
+ if (counter == counter2 && DoubleEquals(pos, pos2)) {
+ pos = pos / frc::RobotController::GetVoltage5V();
units::turn_t turns{counter + pos - m_positionOffset};
m_lastPosition = turns;
return turns;
@@ -74,16 +83,28 @@
}
FRC_ReportError(
- warn::Warning, "{}",
+ warn::Warning,
"Failed to read Analog Encoder. Potential Speed Overrun. Returning last "
"value");
return m_lastPosition;
}
+double AnalogEncoder::GetAbsolutePosition() const {
+ if (m_simAbsolutePosition) {
+ return m_simAbsolutePosition.Get();
+ }
+
+ return m_analogInput->GetVoltage() / frc::RobotController::GetVoltage5V();
+}
+
double AnalogEncoder::GetPositionOffset() const {
return m_positionOffset;
}
+void AnalogEncoder::SetPositionOffset(double offset) {
+ m_positionOffset = std::clamp(offset, 0.0, 1.0);
+}
+
void AnalogEncoder::SetDistancePerRotation(double distancePerRotation) {
m_distancePerRotation = distancePerRotation;
}
@@ -98,7 +119,8 @@
void AnalogEncoder::Reset() {
m_counter.Reset();
- m_positionOffset = m_analogInput->GetVoltage();
+ m_positionOffset =
+ m_analogInput->GetVoltage() / frc::RobotController::GetVoltage5V();
}
int AnalogEncoder::GetChannel() const {
diff --git a/wpilibc/src/main/native/cpp/AnalogGyro.cpp b/wpilibc/src/main/native/cpp/AnalogGyro.cpp
index 106293b..cab9f94 100644
--- a/wpilibc/src/main/native/cpp/AnalogGyro.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogGyro.cpp
@@ -33,7 +33,7 @@
AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel)
: m_analog(channel) {
if (!channel) {
- throw FRC_MakeError(err::NullParameter, "{}", "channel");
+ throw FRC_MakeError(err::NullParameter, "channel");
}
InitGyro();
Calibrate();
@@ -48,7 +48,7 @@
double offset)
: m_analog(channel) {
if (!channel) {
- throw FRC_MakeError(err::NullParameter, "{}", "channel");
+ throw FRC_MakeError(err::NullParameter, "channel");
}
InitGyro();
int32_t status = 0;
@@ -140,5 +140,5 @@
void AnalogGyro::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Gyro");
builder.AddDoubleProperty(
- "Value", [=] { return GetAngle(); }, nullptr);
+ "Value", [=, this] { return GetAngle(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/AnalogInput.cpp b/wpilibc/src/main/native/cpp/AnalogInput.cpp
index dfa5764..2ecb2df 100644
--- a/wpilibc/src/main/native/cpp/AnalogInput.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogInput.cpp
@@ -180,13 +180,13 @@
void AnalogInput::SetSampleRate(double samplesPerSecond) {
int32_t status = 0;
HAL_SetAnalogSampleRate(samplesPerSecond, &status);
- FRC_CheckErrorStatus(status, "{}", "SetSampleRate");
+ FRC_CheckErrorStatus(status, "SetSampleRate");
}
double AnalogInput::GetSampleRate() {
int32_t status = 0;
double sampleRate = HAL_GetAnalogSampleRate(&status);
- FRC_CheckErrorStatus(status, "{}", "GetSampleRate");
+ FRC_CheckErrorStatus(status, "GetSampleRate");
return sampleRate;
}
@@ -197,5 +197,5 @@
void AnalogInput::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Analog Input");
builder.AddDoubleProperty(
- "Value", [=] { return GetAverageVoltage(); }, nullptr);
+ "Value", [=, this] { return GetAverageVoltage(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/AnalogOutput.cpp b/wpilibc/src/main/native/cpp/AnalogOutput.cpp
index a391271..90f538b 100644
--- a/wpilibc/src/main/native/cpp/AnalogOutput.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogOutput.cpp
@@ -61,6 +61,6 @@
void AnalogOutput::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Analog Output");
builder.AddDoubleProperty(
- "Value", [=] { return GetVoltage(); },
- [=](double value) { SetVoltage(value); });
+ "Value", [=, this] { return GetVoltage(); },
+ [=, this](double value) { SetVoltage(value); });
}
diff --git a/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp
index ba94613..d43c84f 100644
--- a/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp
@@ -46,5 +46,5 @@
void AnalogPotentiometer::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Analog Input");
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, nullptr);
+ "Value", [=, this] { return Get(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp b/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp
index 93d1969..ccb44b5 100644
--- a/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp
+++ b/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp
@@ -18,7 +18,7 @@
bool result = HAL_GetAnalogTriggerOutput(
m_trigger->m_trigger, static_cast<HAL_AnalogTriggerType>(m_outputType),
&status);
- FRC_CheckErrorStatus(status, "{}", "Get");
+ FRC_CheckErrorStatus(status, "Get");
return result;
}
diff --git a/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp b/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp
index 1b8da85..4284e89 100644
--- a/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp
+++ b/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp
@@ -23,7 +23,7 @@
void BuiltInAccelerometer::SetRange(Range range) {
if (range == kRange_16G) {
- throw FRC_MakeError(err::ParameterOutOfRange, "{}",
+ throw FRC_MakeError(err::ParameterOutOfRange,
"16G range not supported (use k2G, k4G, or k8G)");
}
@@ -47,9 +47,9 @@
void BuiltInAccelerometer::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("3AxisAccelerometer");
builder.AddDoubleProperty(
- "X", [=] { return GetX(); }, nullptr);
+ "X", [=, this] { return GetX(); }, nullptr);
builder.AddDoubleProperty(
- "Y", [=] { return GetY(); }, nullptr);
+ "Y", [=, this] { return GetY(); }, nullptr);
builder.AddDoubleProperty(
- "Z", [=] { return GetZ(); }, nullptr);
+ "Z", [=, this] { return GetZ(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/CAN.cpp b/wpilibc/src/main/native/cpp/CAN.cpp
index e26ca37..fc4a821 100644
--- a/wpilibc/src/main/native/cpp/CAN.cpp
+++ b/wpilibc/src/main/native/cpp/CAN.cpp
@@ -45,20 +45,20 @@
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
int32_t status = 0;
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
- FRC_CheckErrorStatus(status, "{}", "WritePacket");
+ FRC_CheckErrorStatus(status, "WritePacket");
}
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
int repeatMs) {
int32_t status = 0;
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
- FRC_CheckErrorStatus(status, "{}", "WritePacketRepeating");
+ FRC_CheckErrorStatus(status, "WritePacketRepeating");
}
void CAN::WriteRTRFrame(int length, int apiId) {
int32_t status = 0;
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
- FRC_CheckErrorStatus(status, "{}", "WriteRTRFrame");
+ FRC_CheckErrorStatus(status, "WriteRTRFrame");
}
int CAN::WritePacketNoError(const uint8_t* data, int length, int apiId) {
@@ -83,7 +83,7 @@
void CAN::StopPacketRepeating(int apiId) {
int32_t status = 0;
HAL_StopCANPacketRepeating(m_handle, apiId, &status);
- FRC_CheckErrorStatus(status, "{}", "StopPacketRepeating");
+ FRC_CheckErrorStatus(status, "StopPacketRepeating");
}
bool CAN::ReadPacketNew(int apiId, CANData* data) {
@@ -94,7 +94,7 @@
return false;
}
if (status != 0) {
- FRC_CheckErrorStatus(status, "{}", "ReadPacketNew");
+ FRC_CheckErrorStatus(status, "ReadPacketNew");
return false;
} else {
return true;
@@ -109,7 +109,7 @@
return false;
}
if (status != 0) {
- FRC_CheckErrorStatus(status, "{}", "ReadPacketLatest");
+ FRC_CheckErrorStatus(status, "ReadPacketLatest");
return false;
} else {
return true;
@@ -125,7 +125,7 @@
return false;
}
if (status != 0) {
- FRC_CheckErrorStatus(status, "{}", "ReadPacketTimeout");
+ FRC_CheckErrorStatus(status, "ReadPacketTimeout");
return false;
} else {
return true;
diff --git a/wpilibc/src/main/native/cpp/Compressor.cpp b/wpilibc/src/main/native/cpp/Compressor.cpp
index d994b14..2479ffc 100644
--- a/wpilibc/src/main/native/cpp/Compressor.cpp
+++ b/wpilibc/src/main/native/cpp/Compressor.cpp
@@ -29,18 +29,16 @@
: Compressor{PneumaticsBase::GetDefaultForType(moduleType), moduleType} {}
Compressor::~Compressor() {
- m_module->UnreserveCompressor();
-}
-
-void Compressor::Start() {
- EnableDigital();
-}
-
-void Compressor::Stop() {
- Disable();
+ if (m_module) {
+ m_module->UnreserveCompressor();
+ }
}
bool Compressor::Enabled() const {
+ return IsEnabled();
+}
+
+bool Compressor::IsEnabled() const {
return m_module->GetCompressor();
}
@@ -85,7 +83,7 @@
void Compressor::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Compressor");
builder.AddBooleanProperty(
- "Enabled", [=] { return Enabled(); }, nullptr);
+ "Enabled", [this] { return IsEnabled(); }, nullptr);
builder.AddBooleanProperty(
- "Pressure switch", [=]() { return GetPressureSwitchValue(); }, nullptr);
+ "Pressure switch", [this] { return GetPressureSwitchValue(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/Counter.cpp b/wpilibc/src/main/native/cpp/Counter.cpp
index a1ad9e7..2e9c916 100644
--- a/wpilibc/src/main/native/cpp/Counter.cpp
+++ b/wpilibc/src/main/native/cpp/Counter.cpp
@@ -22,7 +22,7 @@
int32_t status = 0;
m_counter = HAL_InitializeCounter(static_cast<HAL_Counter_Mode>(mode),
&m_index, &status);
- FRC_CheckErrorStatus(status, "{}", "InitializeCounter");
+ FRC_CheckErrorStatus(status, "InitializeCounter");
SetMaxPeriod(0.5_s);
@@ -64,7 +64,7 @@
std::shared_ptr<DigitalSource> downSource, bool inverted)
: Counter(kExternalDirection) {
if (encodingType != k1X && encodingType != k2X) {
- throw FRC_MakeError(err::ParameterOutOfRange, "{}",
+ throw FRC_MakeError(err::ParameterOutOfRange,
"Counter only supports 1X and 2X quadrature decoding");
}
SetUpSource(upSource);
@@ -79,7 +79,7 @@
HAL_SetCounterAverageSize(m_counter, 2, &status);
}
- FRC_CheckErrorStatus(status, "{}", "Counter constructor");
+ FRC_CheckErrorStatus(status, "Counter constructor");
SetDownSourceEdge(inverted, true);
}
@@ -92,7 +92,7 @@
int32_t status = 0;
HAL_FreeCounter(m_counter, &status);
- FRC_ReportError(status, "{}", "Counter destructor");
+ FRC_ReportError(status, "Counter destructor");
}
void Counter::SetUpSource(int channel) {
@@ -124,7 +124,7 @@
static_cast<HAL_AnalogTriggerType>(
source->GetAnalogTriggerTypeForRouting()),
&status);
- FRC_CheckErrorStatus(status, "{}", "SetUpSource");
+ FRC_CheckErrorStatus(status, "SetUpSource");
}
void Counter::SetUpSource(DigitalSource& source) {
@@ -135,19 +135,19 @@
void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) {
if (m_upSource == nullptr) {
throw FRC_MakeError(
- err::NullParameter, "{}",
+ err::NullParameter,
"Must set non-nullptr UpSource before setting UpSourceEdge");
}
int32_t status = 0;
HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
- FRC_CheckErrorStatus(status, "{}", "SetUpSourceEdge");
+ FRC_CheckErrorStatus(status, "SetUpSourceEdge");
}
void Counter::ClearUpSource() {
m_upSource.reset();
int32_t status = 0;
HAL_ClearCounterUpSource(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "ClearUpSource");
+ FRC_CheckErrorStatus(status, "ClearUpSource");
}
void Counter::SetDownSource(int channel) {
@@ -184,37 +184,37 @@
static_cast<HAL_AnalogTriggerType>(
source->GetAnalogTriggerTypeForRouting()),
&status);
- FRC_CheckErrorStatus(status, "{}", "SetDownSource");
+ FRC_CheckErrorStatus(status, "SetDownSource");
}
void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
if (m_downSource == nullptr) {
throw FRC_MakeError(
- err::NullParameter, "{}",
+ err::NullParameter,
"Must set non-nullptr DownSource before setting DownSourceEdge");
}
int32_t status = 0;
HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
- FRC_CheckErrorStatus(status, "{}", "SetDownSourceEdge");
+ FRC_CheckErrorStatus(status, "SetDownSourceEdge");
}
void Counter::ClearDownSource() {
m_downSource.reset();
int32_t status = 0;
HAL_ClearCounterDownSource(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "ClearDownSource");
+ FRC_CheckErrorStatus(status, "ClearDownSource");
}
void Counter::SetUpDownCounterMode() {
int32_t status = 0;
HAL_SetCounterUpDownMode(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "SetUpDownCounterMode");
+ FRC_CheckErrorStatus(status, "SetUpDownCounterMode");
}
void Counter::SetExternalDirectionMode() {
int32_t status = 0;
HAL_SetCounterExternalDirectionMode(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "SetExternalDirectionMode");
+ FRC_CheckErrorStatus(status, "SetExternalDirectionMode");
}
void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
@@ -227,7 +227,7 @@
void Counter::SetPulseLengthMode(double threshold) {
int32_t status = 0;
HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
- FRC_CheckErrorStatus(status, "{}", "SetPulseLengthMode");
+ FRC_CheckErrorStatus(status, "SetPulseLengthMode");
}
void Counter::SetReverseDirection(bool reverseDirection) {
@@ -252,7 +252,7 @@
int Counter::GetSamplesToAverage() const {
int32_t status = 0;
int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "GetSamplesToAverage");
+ FRC_CheckErrorStatus(status, "GetSamplesToAverage");
return samples;
}
@@ -263,51 +263,51 @@
int Counter::Get() const {
int32_t status = 0;
int value = HAL_GetCounter(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "Get");
+ FRC_CheckErrorStatus(status, "Get");
return value;
}
void Counter::Reset() {
int32_t status = 0;
HAL_ResetCounter(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "Reset");
+ FRC_CheckErrorStatus(status, "Reset");
}
units::second_t Counter::GetPeriod() const {
int32_t status = 0;
double value = HAL_GetCounterPeriod(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "GetPeriod");
+ FRC_CheckErrorStatus(status, "GetPeriod");
return units::second_t{value};
}
void Counter::SetMaxPeriod(units::second_t maxPeriod) {
int32_t status = 0;
HAL_SetCounterMaxPeriod(m_counter, maxPeriod.value(), &status);
- FRC_CheckErrorStatus(status, "{}", "SetMaxPeriod");
+ FRC_CheckErrorStatus(status, "SetMaxPeriod");
}
void Counter::SetUpdateWhenEmpty(bool enabled) {
int32_t status = 0;
HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
- FRC_CheckErrorStatus(status, "{}", "SetUpdateWhenEmpty");
+ FRC_CheckErrorStatus(status, "SetUpdateWhenEmpty");
}
bool Counter::GetStopped() const {
int32_t status = 0;
bool value = HAL_GetCounterStopped(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "GetStopped");
+ FRC_CheckErrorStatus(status, "GetStopped");
return value;
}
bool Counter::GetDirection() const {
int32_t status = 0;
bool value = HAL_GetCounterDirection(m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "GetDirection");
+ FRC_CheckErrorStatus(status, "GetDirection");
return value;
}
void Counter::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Counter");
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, nullptr);
+ "Value", [=, this] { return Get(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/DMA.cpp b/wpilibc/src/main/native/cpp/DMA.cpp
index 80c0adb..ce6c532 100644
--- a/wpilibc/src/main/native/cpp/DMA.cpp
+++ b/wpilibc/src/main/native/cpp/DMA.cpp
@@ -27,7 +27,7 @@
DMA::DMA() {
int32_t status = 0;
dmaHandle = HAL_InitializeDMA(&status);
- FRC_CheckErrorStatus(status, "{}", "InitializeDMA");
+ FRC_CheckErrorStatus(status, "InitializeDMA");
}
DMA::~DMA() {
@@ -37,74 +37,74 @@
void DMA::SetPause(bool pause) {
int32_t status = 0;
HAL_SetDMAPause(dmaHandle, pause, &status);
- FRC_CheckErrorStatus(status, "{}", "SetPause");
+ FRC_CheckErrorStatus(status, "SetPause");
}
void DMA::SetTimedTrigger(units::second_t seconds) {
int32_t status = 0;
HAL_SetDMATimedTrigger(dmaHandle, seconds.value(), &status);
- FRC_CheckErrorStatus(status, "{}", "SetTimedTrigger");
+ FRC_CheckErrorStatus(status, "SetTimedTrigger");
}
void DMA::SetTimedTriggerCycles(int cycles) {
int32_t status = 0;
HAL_SetDMATimedTriggerCycles(dmaHandle, cycles, &status);
- FRC_CheckErrorStatus(status, "{}", "SetTimedTriggerCycles");
+ FRC_CheckErrorStatus(status, "SetTimedTriggerCycles");
}
void DMA::AddEncoder(const Encoder* encoder) {
int32_t status = 0;
HAL_AddDMAEncoder(dmaHandle, encoder->m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "AddEncoder");
+ FRC_CheckErrorStatus(status, "AddEncoder");
}
void DMA::AddEncoderPeriod(const Encoder* encoder) {
int32_t status = 0;
HAL_AddDMAEncoderPeriod(dmaHandle, encoder->m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "AddEncoderPeriod");
+ FRC_CheckErrorStatus(status, "AddEncoderPeriod");
}
void DMA::AddCounter(const Counter* counter) {
int32_t status = 0;
HAL_AddDMACounter(dmaHandle, counter->m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "AddCounter");
+ FRC_CheckErrorStatus(status, "AddCounter");
}
void DMA::AddCounterPeriod(const Counter* counter) {
int32_t status = 0;
HAL_AddDMACounterPeriod(dmaHandle, counter->m_counter, &status);
- FRC_CheckErrorStatus(status, "{}", "AddCounterPeriod");
+ FRC_CheckErrorStatus(status, "AddCounterPeriod");
}
void DMA::AddDigitalSource(const DigitalSource* digitalSource) {
int32_t status = 0;
HAL_AddDMADigitalSource(dmaHandle, digitalSource->GetPortHandleForRouting(),
&status);
- FRC_CheckErrorStatus(status, "{}", "AddDigitalSource");
+ FRC_CheckErrorStatus(status, "AddDigitalSource");
}
void DMA::AddDutyCycle(const DutyCycle* dutyCycle) {
int32_t status = 0;
HAL_AddDMADutyCycle(dmaHandle, dutyCycle->m_handle, &status);
- FRC_CheckErrorStatus(status, "{}", "AddDutyCycle");
+ FRC_CheckErrorStatus(status, "AddDutyCycle");
}
void DMA::AddAnalogInput(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAnalogInput(dmaHandle, analogInput->m_port, &status);
- FRC_CheckErrorStatus(status, "{}", "AddAnalogInput");
+ FRC_CheckErrorStatus(status, "AddAnalogInput");
}
void DMA::AddAveragedAnalogInput(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAveragedAnalogInput(dmaHandle, analogInput->m_port, &status);
- FRC_CheckErrorStatus(status, "{}", "AddAveragedAnalogInput");
+ FRC_CheckErrorStatus(status, "AddAveragedAnalogInput");
}
void DMA::AddAnalogAccumulator(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAnalogAccumulator(dmaHandle, analogInput->m_port, &status);
- FRC_CheckErrorStatus(status, "{}", "AddAnalogAccumulator");
+ FRC_CheckErrorStatus(status, "AddAnalogAccumulator");
}
int DMA::SetExternalTrigger(DigitalSource* source, bool rising, bool falling) {
@@ -114,7 +114,7 @@
static_cast<HAL_AnalogTriggerType>(
source->GetAnalogTriggerTypeForRouting()),
rising, falling, &status);
- FRC_CheckErrorStatus(status, "{}", "SetExternalTrigger");
+ FRC_CheckErrorStatus(status, "SetExternalTrigger");
return idx;
}
@@ -124,7 +124,7 @@
int32_t idx = HAL_SetDMAExternalTrigger(
dmaHandle, source->GetPwm()->m_handle,
HAL_AnalogTriggerType::HAL_Trigger_kInWindow, rising, falling, &status);
- FRC_CheckErrorStatus(status, "{}", "SetPWmEdgeTrigger");
+ FRC_CheckErrorStatus(status, "SetPWmEdgeTrigger");
return idx;
}
@@ -133,30 +133,30 @@
int32_t idx = HAL_SetDMAExternalTrigger(
dmaHandle, source->m_handle, HAL_AnalogTriggerType::HAL_Trigger_kInWindow,
rising, falling, &status);
- FRC_CheckErrorStatus(status, "{}", "SetPWmEdgeTrigger");
+ FRC_CheckErrorStatus(status, "SetPWmEdgeTrigger");
return idx;
}
void DMA::ClearSensors() {
int32_t status = 0;
HAL_ClearDMASensors(dmaHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "ClearSensors");
+ FRC_CheckErrorStatus(status, "ClearSensors");
}
void DMA::ClearExternalTriggers() {
int32_t status = 0;
HAL_ClearDMAExternalTriggers(dmaHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "ClearExternalTriggers");
+ FRC_CheckErrorStatus(status, "ClearExternalTriggers");
}
void DMA::Start(int queueDepth) {
int32_t status = 0;
HAL_StartDMA(dmaHandle, queueDepth, &status);
- FRC_CheckErrorStatus(status, "{}", "Start");
+ FRC_CheckErrorStatus(status, "Start");
}
void DMA::Stop() {
int32_t status = 0;
HAL_StopDMA(dmaHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "Stop");
+ FRC_CheckErrorStatus(status, "Stop");
}
diff --git a/wpilibc/src/main/native/cpp/DataLogManager.cpp b/wpilibc/src/main/native/cpp/DataLogManager.cpp
new file mode 100644
index 0000000..b92faa3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DataLogManager.cpp
@@ -0,0 +1,317 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/DataLogManager.h"
+
+#include <algorithm>
+#include <ctime>
+#include <random>
+
+#include <fmt/chrono.h>
+#include <fmt/format.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/DataLog.h>
+#include <wpi/SafeThread.h>
+#include <wpi/StringExtras.h>
+#include <wpi/fs.h>
+#include <wpi/timestamp.h>
+
+#include "frc/DriverStation.h"
+#include "frc/Filesystem.h"
+
+using namespace frc;
+
+namespace {
+
+struct Thread final : public wpi::SafeThread {
+ Thread(std::string_view dir, std::string_view filename, double period);
+
+ void Main() final;
+
+ void StartNTLog();
+ void StopNTLog();
+
+ std::string m_logDir;
+ bool m_filenameOverride;
+ wpi::log::DataLog m_log;
+ bool m_ntLoggerEnabled = false;
+ NT_DataLogger m_ntEntryLogger = 0;
+ NT_ConnectionDataLogger m_ntConnLogger = 0;
+ wpi::log::StringLogEntry m_messageLog;
+};
+
+struct Instance {
+ Instance(std::string_view dir, std::string_view filename, double period);
+ wpi::SafeThreadOwner<Thread> owner;
+};
+
+} // namespace
+
+// if less than this much free space, delete log files until there is this much
+// free space OR there are this many files remaining.
+static constexpr uintmax_t kFreeSpaceThreshold = 50000000;
+static constexpr int kFileCountThreshold = 10;
+
+static std::string MakeLogDir(std::string_view dir) {
+ if (!dir.empty()) {
+ return std::string{dir};
+ }
+#ifdef __FRC_ROBORIO__
+ // prefer a mounted USB drive if one is accessible
+ constexpr std::string_view usbDir{"/u"};
+ std::error_code ec;
+ auto s = fs::status(usbDir, ec);
+ if (!ec && fs::is_directory(s) &&
+ (s.permissions() & fs::perms::others_write) != fs::perms::none) {
+ return std::string{usbDir};
+ }
+#endif
+ return frc::filesystem::GetOperatingDirectory();
+}
+
+static std::string MakeLogFilename(std::string_view filenameOverride) {
+ if (!filenameOverride.empty()) {
+ return std::string{filenameOverride};
+ }
+ static std::random_device dev;
+ static std::mt19937 rng(dev());
+ std::uniform_int_distribution<int> dist(0, 15);
+ const char* v = "0123456789abcdef";
+ std::string filename = "FRC_TBD_";
+ for (int i = 0; i < 16; i++) {
+ filename += v[dist(rng)];
+ }
+ filename += ".wpilog";
+ return filename;
+}
+
+Thread::Thread(std::string_view dir, std::string_view filename, double period)
+ : m_logDir{dir},
+ m_filenameOverride{!filename.empty()},
+ m_log{dir, MakeLogFilename(filename), period},
+ m_messageLog{m_log, "messages"} {
+ StartNTLog();
+}
+
+void Thread::Main() {
+ // based on free disk space, scan for "old" FRC_*.wpilog files and remove
+ {
+ uintmax_t freeSpace = fs::space(m_logDir).free;
+ if (freeSpace < kFreeSpaceThreshold) {
+ // Delete oldest FRC_*.wpilog files (ignore FRC_TBD_*.wpilog as we just
+ // created one)
+ std::vector<fs::directory_entry> entries;
+ std::error_code ec;
+ for (auto&& entry : fs::directory_iterator{m_logDir, ec}) {
+ auto stem = entry.path().stem().string();
+ if (wpi::starts_with(stem, "FRC_") &&
+ entry.path().extension() == ".wpilog" &&
+ !wpi::starts_with(stem, "FRC_TBD_")) {
+ entries.emplace_back(entry);
+ }
+ }
+ std::sort(entries.begin(), entries.end(),
+ [](const auto& a, const auto& b) {
+ return a.last_write_time() < b.last_write_time();
+ });
+
+ int count = entries.size();
+ for (auto&& entry : entries) {
+ --count;
+ if (count < kFileCountThreshold) {
+ break;
+ }
+ auto size = entry.file_size();
+ if (fs::remove(entry.path(), ec)) {
+ freeSpace += size;
+ if (freeSpace >= kFreeSpaceThreshold) {
+ break;
+ }
+ } else {
+ fmt::print(stderr, "DataLogManager: could not delete {}\n",
+ entry.path().string());
+ }
+ }
+ }
+ }
+
+ int timeoutCount = 0;
+ bool paused = false;
+ int dsAttachCount = 0;
+ int fmsAttachCount = 0;
+ bool dsRenamed = m_filenameOverride;
+ bool fmsRenamed = m_filenameOverride;
+ int sysTimeCount = 0;
+ wpi::log::IntegerLogEntry sysTimeEntry{
+ m_log, "systemTime",
+ "{\"source\":\"DataLogManager\",\"format\":\"time_t_us\"}"};
+
+ wpi::Event newDataEvent;
+ DriverStation::ProvideRefreshedDataEventHandle(newDataEvent.GetHandle());
+
+ for (;;) {
+ bool timedOut = false;
+ bool newData =
+ wpi::WaitForObject(newDataEvent.GetHandle(), 0.25, &timedOut);
+ if (!m_active) {
+ break;
+ }
+ if (!newData) {
+ ++timeoutCount;
+ // pause logging after being disconnected for 10 seconds
+ if (timeoutCount > 40 && !paused) {
+ timeoutCount = 0;
+ paused = true;
+ m_log.Pause();
+ }
+ continue;
+ }
+ // when we connect to the DS, resume logging
+ timeoutCount = 0;
+ if (paused) {
+ paused = false;
+ m_log.Resume();
+ }
+
+ if (!dsRenamed) {
+ // track DS attach
+ if (DriverStation::IsDSAttached()) {
+ ++dsAttachCount;
+ } else {
+ dsAttachCount = 0;
+ }
+ if (dsAttachCount > 50) { // 1 second
+ std::time_t now = std::time(nullptr);
+ auto tm = std::gmtime(&now);
+ if (tm->tm_year > 100) {
+ // assume local clock is now synchronized to DS, so rename based on
+ // local time
+ m_log.SetFilename(fmt::format("FRC_{:%Y%m%d_%H%M%S}.wpilog", *tm));
+ dsRenamed = true;
+ } else {
+ dsAttachCount = 0; // wait a bit and try again
+ }
+ }
+ }
+
+ if (!fmsRenamed) {
+ // track FMS attach
+ if (DriverStation::IsFMSAttached()) {
+ ++fmsAttachCount;
+ } else {
+ fmsAttachCount = 0;
+ }
+ if (fmsAttachCount > 100) { // 2 seconds
+ // match info comes through TCP, so we need to double-check we've
+ // actually received it
+ auto matchType = DriverStation::GetMatchType();
+ if (matchType != DriverStation::kNone) {
+ // rename per match info
+ char matchTypeChar;
+ switch (matchType) {
+ case DriverStation::kPractice:
+ matchTypeChar = 'P';
+ break;
+ case DriverStation::kQualification:
+ matchTypeChar = 'Q';
+ break;
+ case DriverStation::kElimination:
+ matchTypeChar = 'E';
+ break;
+ default:
+ matchTypeChar = '_';
+ break;
+ }
+ std::time_t now = std::time(nullptr);
+ m_log.SetFilename(
+ fmt::format("FRC_{:%Y%m%d_%H%M%S}_{}_{}{}.wpilog",
+ *std::gmtime(&now), DriverStation::GetEventName(),
+ matchTypeChar, DriverStation::GetMatchNumber()));
+ fmsRenamed = true;
+ dsRenamed = true; // don't override FMS rename
+ }
+ }
+ }
+
+ // Write system time every ~5 seconds
+ ++sysTimeCount;
+ if (sysTimeCount >= 250) {
+ sysTimeCount = 0;
+ sysTimeEntry.Append(wpi::GetSystemTime(), wpi::Now());
+ }
+ }
+ DriverStation::RemoveRefreshedDataEventHandle(newDataEvent.GetHandle());
+}
+
+void Thread::StartNTLog() {
+ if (!m_ntLoggerEnabled) {
+ m_ntLoggerEnabled = true;
+ auto inst = nt::NetworkTableInstance::GetDefault();
+ m_ntEntryLogger = inst.StartEntryDataLog(m_log, "", "NT:");
+ m_ntConnLogger = inst.StartConnectionDataLog(m_log, "NTConnection");
+ }
+}
+
+void Thread::StopNTLog() {
+ if (m_ntLoggerEnabled) {
+ m_ntLoggerEnabled = false;
+ nt::NetworkTableInstance::StopEntryDataLog(m_ntEntryLogger);
+ nt::NetworkTableInstance::StopConnectionDataLog(m_ntConnLogger);
+ }
+}
+
+Instance::Instance(std::string_view dir, std::string_view filename,
+ double period) {
+ // Delete all previously existing FRC_TBD_*.wpilog files. These only exist
+ // when the robot never connects to the DS, so they are very unlikely to
+ // have useful data and just clutter the filesystem.
+ auto logDir = MakeLogDir(dir);
+ std::error_code ec;
+ for (auto&& entry : fs::directory_iterator{logDir, ec}) {
+ if (wpi::starts_with(entry.path().stem().string(), "FRC_TBD_") &&
+ entry.path().extension() == ".wpilog") {
+ if (!fs::remove(entry, ec)) {
+ fmt::print(stderr, "DataLogManager: could not delete {}\n",
+ entry.path().string());
+ }
+ }
+ }
+
+ owner.Start(logDir, filename, period);
+}
+
+static Instance& GetInstance(std::string_view dir = "",
+ std::string_view filename = "",
+ double period = 0.25) {
+ static Instance instance(dir, filename, period);
+ return instance;
+}
+
+void DataLogManager::Start(std::string_view dir, std::string_view filename,
+ double period) {
+ GetInstance(dir, filename, period);
+}
+
+void DataLogManager::Log(std::string_view message) {
+ GetInstance().owner.GetThread()->m_messageLog.Append(message);
+ fmt::print("{}\n", message);
+}
+
+wpi::log::DataLog& DataLogManager::GetLog() {
+ return GetInstance().owner.GetThread()->m_log;
+}
+
+std::string DataLogManager::GetLogDir() {
+ return GetInstance().owner.GetThread()->m_logDir;
+}
+
+void DataLogManager::LogNetworkTables(bool enabled) {
+ if (auto thr = GetInstance().owner.GetThread()) {
+ if (enabled) {
+ thr->StartNTLog();
+ } else if (!enabled) {
+ thr->StopNTLog();
+ }
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp b/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp
index 3294a99..4abb7cf 100644
--- a/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp
+++ b/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp
@@ -56,7 +56,7 @@
// We don't support GlitchFilters on AnalogTriggers.
if (input->IsAnalogTrigger()) {
throw FRC_MakeError(
- -1, "{}", "Analog Triggers not supported for DigitalGlitchFilters");
+ -1, "Analog Triggers not supported for DigitalGlitchFilters");
}
int32_t status = 0;
HAL_SetFilterSelect(input->GetPortHandleForRouting(), requestedIndex,
diff --git a/wpilibc/src/main/native/cpp/DigitalInput.cpp b/wpilibc/src/main/native/cpp/DigitalInput.cpp
index 86f1c3a..0275741 100644
--- a/wpilibc/src/main/native/cpp/DigitalInput.cpp
+++ b/wpilibc/src/main/native/cpp/DigitalInput.cpp
@@ -69,5 +69,5 @@
void DigitalInput::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Digital Input");
builder.AddBooleanProperty(
- "Value", [=] { return Get(); }, nullptr);
+ "Value", [=, this] { return Get(); }, nullptr);
}
diff --git a/wpilibc/src/main/native/cpp/DigitalOutput.cpp b/wpilibc/src/main/native/cpp/DigitalOutput.cpp
index 5810e30..fc69e35 100644
--- a/wpilibc/src/main/native/cpp/DigitalOutput.cpp
+++ b/wpilibc/src/main/native/cpp/DigitalOutput.cpp
@@ -76,9 +76,9 @@
return m_channel;
}
-void DigitalOutput::Pulse(double length) {
+void DigitalOutput::Pulse(units::second_t pulseLength) {
int32_t status = 0;
- HAL_Pulse(m_handle, length, &status);
+ HAL_Pulse(m_handle, pulseLength.to<double>(), &status);
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
}
@@ -95,6 +95,23 @@
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
}
+void DigitalOutput::EnablePPS(double dutyCycle) {
+ if (m_pwmGenerator != HAL_kInvalidHandle) {
+ return;
+ }
+
+ int32_t status = 0;
+
+ m_pwmGenerator = HAL_AllocateDigitalPWM(&status);
+ FRC_CheckErrorStatus(status, "Channel {}", m_channel);
+
+ HAL_SetDigitalPWMPPS(m_pwmGenerator, dutyCycle, &status);
+ FRC_CheckErrorStatus(status, "Channel {}", m_channel);
+
+ HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, m_channel, &status);
+ FRC_CheckErrorStatus(status, "Channel {}", m_channel);
+}
+
void DigitalOutput::EnablePWM(double initialDutyCycle) {
if (m_pwmGenerator != HAL_kInvalidHandle) {
return;
@@ -143,5 +160,6 @@
void DigitalOutput::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Digital Output");
builder.AddBooleanProperty(
- "Value", [=] { return Get(); }, [=](bool value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](bool value) { Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp
index 212673a..c111622 100644
--- a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp
+++ b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp
@@ -65,7 +65,9 @@
forwardChannel, reverseChannel} {}
DoubleSolenoid::~DoubleSolenoid() {
- m_module->UnreserveSolenoids(m_mask);
+ if (m_module) {
+ m_module->UnreserveSolenoids(m_mask);
+ }
}
void DoubleSolenoid::Set(Value value) {
@@ -127,10 +129,10 @@
void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Double Solenoid");
builder.SetActuator(true);
- builder.SetSafeState([=] { Set(kOff); });
+ builder.SetSafeState([=, this] { Set(kOff); });
builder.AddSmallStringProperty(
"Value",
- [=](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
+ [=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
switch (Get()) {
case kForward:
return "Forward";
@@ -140,7 +142,7 @@
return "Off";
}
},
- [=](std::string_view value) {
+ [=, this](std::string_view value) {
Value lvalue = kOff;
if (value == "Forward") {
lvalue = kForward;
diff --git a/wpilibc/src/main/native/cpp/DriverStation.cpp b/wpilibc/src/main/native/cpp/DriverStation.cpp
index 37fc65f..aead343 100644
--- a/wpilibc/src/main/native/cpp/DriverStation.cpp
+++ b/wpilibc/src/main/native/cpp/DriverStation.cpp
@@ -9,6 +9,7 @@
#include <array>
#include <atomic>
#include <chrono>
+#include <span>
#include <string>
#include <string_view>
#include <thread>
@@ -19,11 +20,16 @@
#include <hal/DriverStationTypes.h>
#include <hal/HALBase.h>
#include <hal/Power.h>
+#include <networktables/BooleanTopic.h>
+#include <networktables/IntegerTopic.h>
#include <networktables/NetworkTable.h>
-#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableInstance.h>
+#include <networktables/StringTopic.h>
+#include <wpi/DataLog.h>
+#include <wpi/EventVector.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
+#include <wpi/timestamp.h>
#include "frc/Errors.h"
#include "frc/MotorSafety.h"
@@ -34,63 +40,87 @@
namespace {
// A simple class which caches the previous value written to an NT entry
// Used to prevent redundant, repeated writes of the same value
-template <class T>
+template <typename Topic>
class MatchDataSenderEntry {
public:
MatchDataSenderEntry(const std::shared_ptr<nt::NetworkTable>& table,
- std::string_view key, const T& initialVal) {
- static_assert(std::is_same_v<T, bool> || std::is_same_v<T, double> ||
- std::is_same_v<T, std::string>,
- "Invalid type for MatchDataSenderEntry - must be "
- "to bool, double or std::string");
-
- ntEntry = table->GetEntry(key);
- if constexpr (std::is_same_v<T, bool>) {
- ntEntry.ForceSetBoolean(initialVal);
- } else if constexpr (std::is_same_v<T, double>) {
- ntEntry.ForceSetDouble(initialVal);
- } else if constexpr (std::is_same_v<T, std::string>) {
- ntEntry.ForceSetString(initialVal);
- }
- prevVal = initialVal;
+ std::string_view key,
+ typename Topic::ParamType initialVal)
+ : publisher{Topic{table->GetTopic(key)}.Publish()}, prevVal{initialVal} {
+ publisher.Set(initialVal);
}
- void Set(const T& val) {
+ void Set(typename Topic::ParamType val) {
if (val != prevVal) {
- SetValue(val);
+ publisher.Set(val);
prevVal = val;
}
}
private:
- nt::NetworkTableEntry ntEntry;
- T prevVal;
-
- void SetValue(bool val) { ntEntry.SetBoolean(val); }
- void SetValue(double val) { ntEntry.SetDouble(val); }
- void SetValue(std::string_view val) { ntEntry.SetString(val); }
+ typename Topic::PublisherType publisher;
+ typename Topic::ValueType prevVal;
};
struct MatchDataSender {
std::shared_ptr<nt::NetworkTable> table =
nt::NetworkTableInstance::GetDefault().GetTable("FMSInfo");
- MatchDataSenderEntry<std::string> typeMetaData{table, ".type", "FMSInfo"};
- MatchDataSenderEntry<std::string> gameSpecificMessage{
+ MatchDataSenderEntry<nt::StringTopic> typeMetaData{table, ".type", "FMSInfo"};
+ MatchDataSenderEntry<nt::StringTopic> gameSpecificMessage{
table, "GameSpecificMessage", ""};
- MatchDataSenderEntry<std::string> eventName{table, "EventName", ""};
- MatchDataSenderEntry<double> matchNumber{table, "MatchNumber", 0.0};
- MatchDataSenderEntry<double> replayNumber{table, "ReplayNumber", 0.0};
- MatchDataSenderEntry<double> matchType{table, "MatchType", 0.0};
- MatchDataSenderEntry<bool> alliance{table, "IsRedAlliance", true};
- MatchDataSenderEntry<double> station{table, "StationNumber", 1.0};
- MatchDataSenderEntry<double> controlWord{table, "FMSControlData", 0.0};
+ MatchDataSenderEntry<nt::StringTopic> eventName{table, "EventName", ""};
+ MatchDataSenderEntry<nt::IntegerTopic> matchNumber{table, "MatchNumber", 0};
+ MatchDataSenderEntry<nt::IntegerTopic> replayNumber{table, "ReplayNumber", 0};
+ MatchDataSenderEntry<nt::IntegerTopic> matchType{table, "MatchType", 0};
+ MatchDataSenderEntry<nt::BooleanTopic> alliance{table, "IsRedAlliance", true};
+ MatchDataSenderEntry<nt::IntegerTopic> station{table, "StationNumber", 1};
+ MatchDataSenderEntry<nt::IntegerTopic> controlWord{table, "FMSControlData",
+ 0};
+};
+
+class JoystickLogSender {
+ public:
+ void Init(wpi::log::DataLog& log, unsigned int stick, int64_t timestamp);
+ void Send(uint64_t timestamp);
+
+ private:
+ void AppendButtons(HAL_JoystickButtons buttons, uint64_t timestamp);
+ void AppendPOVs(const HAL_JoystickPOVs& povs, uint64_t timestamp);
+
+ unsigned int m_stick;
+ HAL_JoystickButtons m_prevButtons;
+ HAL_JoystickAxes m_prevAxes;
+ HAL_JoystickPOVs m_prevPOVs;
+ wpi::log::BooleanArrayLogEntry m_logButtons;
+ wpi::log::FloatArrayLogEntry m_logAxes;
+ wpi::log::IntegerArrayLogEntry m_logPOVs;
+};
+
+class DataLogSender {
+ public:
+ void Init(wpi::log::DataLog& log, bool logJoysticks, int64_t timestamp);
+ void Send(uint64_t timestamp);
+
+ private:
+ std::atomic_bool m_initialized{false};
+
+ HAL_ControlWord m_prevControlWord;
+ wpi::log::BooleanLogEntry m_logEnabled;
+ wpi::log::BooleanLogEntry m_logAutonomous;
+ wpi::log::BooleanLogEntry m_logTest;
+ wpi::log::BooleanLogEntry m_logEstop;
+
+ bool m_logJoysticks;
+ std::array<JoystickLogSender, DriverStation::kJoystickPorts> m_joysticks;
};
struct Instance {
Instance();
~Instance();
+ wpi::EventVector refreshEvents;
MatchDataSender matchDataSender;
+ std::atomic<DataLogSender*> dataLogSender{nullptr};
// Joystick button rising/falling edge flags
wpi::mutex buttonEdgeMutex;
@@ -99,14 +129,6 @@
std::array<uint32_t, DriverStation::kJoystickPorts> joystickButtonsPressed;
std::array<uint32_t, DriverStation::kJoystickPorts> joystickButtonsReleased;
- // Internal Driver Station thread
- std::thread dsThread;
- std::atomic<bool> isRunning{false};
-
- mutable wpi::mutex waitForDataMutex;
- wpi::condition_variable waitForDataCond;
- int waitForDataCounter = 0;
-
bool silenceJoystickWarning = false;
// Robot state status variables
@@ -126,7 +148,6 @@
return instance;
}
-static void Run();
static void SendMatchData();
/**
@@ -140,8 +161,7 @@
template <typename S, typename... Args>
static inline void ReportJoystickUnpluggedError(const S& format,
Args&&... args) {
- ReportJoystickUnpluggedErrorV(
- format, fmt::make_args_checked<Args...>(format, args...));
+ ReportJoystickUnpluggedErrorV(format, fmt::make_format_args(args...));
}
/**
@@ -155,17 +175,7 @@
template <typename S, typename... Args>
static inline void ReportJoystickUnpluggedWarning(const S& format,
Args&&... args) {
- ReportJoystickUnpluggedWarningV(
- format, fmt::make_args_checked<Args...>(format, args...));
-}
-
-static int& GetDSLastCount() {
- // There is a rollover error condition here. At Packet# = n * (uintmax), this
- // will return false when instead it should return true. However, this at a
- // 20ms rate occurs once every 2.7 years of DS connected runtime, so not
- // worth the cycles to check.
- thread_local int lastCount{0};
- return lastCount;
+ ReportJoystickUnpluggedWarningV(format, fmt::make_format_args(args...));
}
Instance::Instance() {
@@ -179,21 +189,12 @@
previousButtonStates[i].count = 0;
previousButtonStates[i].buttons = 0;
}
-
- dsThread = std::thread(&Run);
}
Instance::~Instance() {
- isRunning = false;
- // Trigger a DS mutex release in case there is no driver station running.
- HAL_ReleaseDSMutex();
- dsThread.join();
-}
-
-DriverStation& DriverStation::GetInstance() {
- ::GetInstance();
- static DriverStation instance;
- return instance;
+ if (dataLogSender) {
+ delete dataLogSender.load();
+ }
}
bool DriverStation::GetStickButton(int stick, int button) {
@@ -419,11 +420,15 @@
FRC_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick);
return -1;
}
+ if (axis < 0 || axis >= HAL_kMaxJoystickAxes) {
+ FRC_ReportError(warn::BadJoystickAxis, "axis {} out of range", axis);
+ return -1;
+ }
HAL_JoystickDescriptor descriptor;
HAL_GetJoystickDescriptor(stick, &descriptor);
- return static_cast<bool>(descriptor.axisTypes);
+ return descriptor.axisTypes[axis];
}
bool DriverStation::IsJoystickConnected(int stick) {
@@ -461,20 +466,12 @@
return controlWord.autonomous && controlWord.enabled;
}
-bool DriverStation::IsOperatorControl() {
- return IsTeleop();
-}
-
bool DriverStation::IsTeleop() {
HAL_ControlWord controlWord;
HAL_GetControlWord(&controlWord);
return !(controlWord.autonomous || controlWord.test);
}
-bool DriverStation::IsOperatorControlEnabled() {
- return IsTeleopEnabled();
-}
-
bool DriverStation::IsTeleopEnabled() {
HAL_ControlWord controlWord;
HAL_GetControlWord(&controlWord);
@@ -493,18 +490,6 @@
return controlWord.dsAttached;
}
-bool DriverStation::IsNewControlData() {
- auto& inst = ::GetInstance();
- std::unique_lock lock(inst.waitForDataMutex);
- int& lastCount = GetDSLastCount();
- int currentCount = inst.waitForDataCounter;
- if (lastCount == currentCount) {
- return false;
- }
- lastCount = currentCount;
- return true;
-}
-
bool DriverStation::IsFMSAttached() {
HAL_ControlWord controlWord;
HAL_GetControlWord(&controlWord);
@@ -577,36 +562,6 @@
}
}
-void DriverStation::WaitForData() {
- WaitForData(0_s);
-}
-
-bool DriverStation::WaitForData(units::second_t timeout) {
- auto& inst = ::GetInstance();
- auto timeoutTime = std::chrono::steady_clock::now() +
- std::chrono::steady_clock::duration{timeout};
-
- std::unique_lock lock(inst.waitForDataMutex);
- int& lastCount = GetDSLastCount();
- int currentCount = inst.waitForDataCounter;
- if (lastCount != currentCount) {
- lastCount = currentCount;
- return true;
- }
- while (inst.waitForDataCounter == currentCount) {
- if (timeout > 0_s) {
- auto timedOut = inst.waitForDataCond.wait_until(lock, timeoutTime);
- if (timedOut == std::cv_status::timeout) {
- return false;
- }
- } else {
- inst.waitForDataCond.wait(lock);
- }
- }
- lastCount = inst.waitForDataCounter;
- return true;
-}
-
double DriverStation::GetMatchTime() {
int32_t status = 0;
return HAL_GetMatchTime(&status);
@@ -615,46 +570,19 @@
double DriverStation::GetBatteryVoltage() {
int32_t status = 0;
double voltage = HAL_GetVinVoltage(&status);
- FRC_CheckErrorStatus(status, "{}", "getVinVoltage");
+ FRC_CheckErrorStatus(status, "getVinVoltage");
return voltage;
}
-void DriverStation::InDisabled(bool entering) {
- ::GetInstance().userInDisabled = entering;
-}
-
-void DriverStation::InAutonomous(bool entering) {
- ::GetInstance().userInAutonomous = entering;
-}
-
-void DriverStation::InOperatorControl(bool entering) {
- InTeleop(entering);
-}
-
-void DriverStation::InTeleop(bool entering) {
- ::GetInstance().userInTeleop = entering;
-}
-
-void DriverStation::InTest(bool entering) {
- ::GetInstance().userInTest = entering;
-}
-
-void DriverStation::WakeupWaitForData() {
- auto& inst = ::GetInstance();
- std::scoped_lock waitLock(inst.waitForDataMutex);
- // Nofify all threads
- inst.waitForDataCounter++;
- inst.waitForDataCond.notify_all();
-}
-
/**
* Copy data from the DS task for the user.
*
* If no new data exists, it will just be returned, otherwise
* the data will be copied from the DS polling loop.
*/
-void GetData() {
+void DriverStation::RefreshData() {
+ HAL_RefreshDSData();
auto& inst = ::GetInstance();
{
// Compute the pressed and released buttons
@@ -676,8 +604,22 @@
}
}
- DriverStation::WakeupWaitForData();
+ inst.refreshEvents.Wakeup();
+
SendMatchData();
+ if (auto sender = inst.dataLogSender.load()) {
+ sender->Send(wpi::Now());
+ }
+}
+
+void DriverStation::ProvideRefreshedDataEventHandle(WPI_EventHandle handle) {
+ auto& inst = ::GetInstance();
+ inst.refreshEvents.Add(handle);
+}
+
+void DriverStation::RemoveRefreshedDataEventHandle(WPI_EventHandle handle) {
+ auto& inst = ::GetInstance();
+ inst.refreshEvents.Remove(handle);
}
void DriverStation::SilenceJoystickConnectionWarning(bool silence) {
@@ -688,6 +630,24 @@
return !IsFMSAttached() && ::GetInstance().silenceJoystickWarning;
}
+void DriverStation::StartDataLog(wpi::log::DataLog& log, bool logJoysticks) {
+ auto& inst = ::GetInstance();
+ // Note: cannot safely replace, because we wouldn't know when to delete the
+ // "old" one. Instead do a compare and exchange with nullptr. We check first
+ // with a simple load to avoid the new in the common case.
+ if (inst.dataLogSender.load()) {
+ return;
+ }
+ DataLogSender* oldSender = nullptr;
+ DataLogSender* newSender = new DataLogSender;
+ inst.dataLogSender.compare_exchange_strong(oldSender, newSender);
+ if (oldSender) {
+ delete newSender; // already had a sender
+ } else {
+ newSender->Init(log, logJoysticks, wpi::Now());
+ }
+}
+
void ReportJoystickUnpluggedErrorV(fmt::string_view format,
fmt::format_args args) {
auto& inst = GetInstance();
@@ -710,37 +670,6 @@
}
}
-void Run() {
- auto& inst = GetInstance();
- inst.isRunning = true;
- int safetyCounter = 0;
- while (inst.isRunning) {
- HAL_WaitForDSData();
- GetData();
-
- if (DriverStation::IsDisabled()) {
- safetyCounter = 0;
- }
-
- if (++safetyCounter >= 4) {
- MotorSafety::CheckMotors();
- safetyCounter = 0;
- }
- if (inst.userInDisabled) {
- HAL_ObserveUserProgramDisabled();
- }
- if (inst.userInAutonomous) {
- HAL_ObserveUserProgramAutonomous();
- }
- if (inst.userInTeleop) {
- HAL_ObserveUserProgramTeleop();
- }
- if (inst.userInTest) {
- HAL_ObserveUserProgramTest();
- }
- }
-}
-
void SendMatchData() {
int32_t status = 0;
HAL_AllianceStationID alliance = HAL_GetAllianceStation(&status);
@@ -793,3 +722,131 @@
std::memcpy(&wordInt, &ctlWord, sizeof(wordInt));
inst.matchDataSender.controlWord.Set(wordInt);
}
+
+void JoystickLogSender::Init(wpi::log::DataLog& log, unsigned int stick,
+ int64_t timestamp) {
+ m_stick = stick;
+
+ m_logButtons = wpi::log::BooleanArrayLogEntry{
+ log, fmt::format("DS:joystick{}/buttons", stick), timestamp};
+ m_logAxes = wpi::log::FloatArrayLogEntry{
+ log, fmt::format("DS:joystick{}/axes", stick), timestamp};
+ m_logPOVs = wpi::log::IntegerArrayLogEntry{
+ log, fmt::format("DS:joystick{}/povs", stick), timestamp};
+
+ HAL_GetJoystickButtons(m_stick, &m_prevButtons);
+ HAL_GetJoystickAxes(m_stick, &m_prevAxes);
+ HAL_GetJoystickPOVs(m_stick, &m_prevPOVs);
+ AppendButtons(m_prevButtons, timestamp);
+ m_logAxes.Append(
+ std::span<const float>{m_prevAxes.axes,
+ static_cast<size_t>(m_prevAxes.count)},
+ timestamp);
+ AppendPOVs(m_prevPOVs, timestamp);
+}
+
+void JoystickLogSender::Send(uint64_t timestamp) {
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(m_stick, &buttons);
+ if (buttons.count != m_prevButtons.count ||
+ buttons.buttons != m_prevButtons.buttons) {
+ AppendButtons(buttons, timestamp);
+ }
+ m_prevButtons = buttons;
+
+ HAL_JoystickAxes axes;
+ HAL_GetJoystickAxes(m_stick, &axes);
+ if (axes.count != m_prevAxes.count ||
+ std::memcmp(axes.axes, m_prevAxes.axes,
+ sizeof(axes.axes[0]) * axes.count) != 0) {
+ m_logAxes.Append(
+ std::span<const float>{axes.axes, static_cast<size_t>(axes.count)},
+ timestamp);
+ }
+ m_prevAxes = axes;
+
+ HAL_JoystickPOVs povs;
+ HAL_GetJoystickPOVs(m_stick, &povs);
+ if (povs.count != m_prevPOVs.count ||
+ std::memcmp(povs.povs, m_prevPOVs.povs,
+ sizeof(povs.povs[0]) * povs.count) != 0) {
+ AppendPOVs(povs, timestamp);
+ }
+ m_prevPOVs = povs;
+}
+
+void JoystickLogSender::AppendButtons(HAL_JoystickButtons buttons,
+ uint64_t timestamp) {
+ uint8_t buttonsArr[32];
+ for (unsigned int i = 0; i < buttons.count; ++i) {
+ buttonsArr[i] = (buttons.buttons & (1u << i)) != 0;
+ }
+ m_logButtons.Append(std::span<const uint8_t>{buttonsArr, buttons.count},
+ timestamp);
+}
+
+void JoystickLogSender::AppendPOVs(const HAL_JoystickPOVs& povs,
+ uint64_t timestamp) {
+ int64_t povsArr[HAL_kMaxJoystickPOVs];
+ for (int i = 0; i < povs.count; ++i) {
+ povsArr[i] = povs.povs[i];
+ }
+ m_logPOVs.Append(
+ std::span<const int64_t>{povsArr, static_cast<size_t>(povs.count)},
+ timestamp);
+}
+
+void DataLogSender::Init(wpi::log::DataLog& log, bool logJoysticks,
+ int64_t timestamp) {
+ m_logEnabled = wpi::log::BooleanLogEntry{log, "DS:enabled", timestamp};
+ m_logAutonomous = wpi::log::BooleanLogEntry{log, "DS:autonomous", timestamp};
+ m_logTest = wpi::log::BooleanLogEntry{log, "DS:test", timestamp};
+ m_logEstop = wpi::log::BooleanLogEntry{log, "DS:estop", timestamp};
+
+ // append initial control word values
+ HAL_GetControlWord(&m_prevControlWord);
+ m_logEnabled.Append(m_prevControlWord.enabled, timestamp);
+ m_logAutonomous.Append(m_prevControlWord.autonomous, timestamp);
+ m_logTest.Append(m_prevControlWord.test, timestamp);
+ m_logEstop.Append(m_prevControlWord.eStop, timestamp);
+
+ m_logJoysticks = logJoysticks;
+ if (logJoysticks) {
+ unsigned int i = 0;
+ for (auto&& joystick : m_joysticks) {
+ joystick.Init(log, i++, timestamp);
+ }
+ }
+
+ m_initialized = true;
+}
+
+void DataLogSender::Send(uint64_t timestamp) {
+ if (!m_initialized) {
+ return;
+ }
+
+ // append control word value changes
+ HAL_ControlWord ctlWord;
+ HAL_GetControlWord(&ctlWord);
+ if (ctlWord.enabled != m_prevControlWord.enabled) {
+ m_logEnabled.Append(ctlWord.enabled, timestamp);
+ }
+ if (ctlWord.autonomous != m_prevControlWord.autonomous) {
+ m_logAutonomous.Append(ctlWord.autonomous, timestamp);
+ }
+ if (ctlWord.test != m_prevControlWord.test) {
+ m_logTest.Append(ctlWord.test, timestamp);
+ }
+ if (ctlWord.eStop != m_prevControlWord.eStop) {
+ m_logEstop.Append(ctlWord.eStop, timestamp);
+ }
+ m_prevControlWord = ctlWord;
+
+ if (m_logJoysticks) {
+ // append joystick value changes
+ for (auto&& joystick : m_joysticks) {
+ joystick.Send(timestamp);
+ }
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/DutyCycle.cpp b/wpilibc/src/main/native/cpp/DutyCycle.cpp
index a8375e0..88f6b56 100644
--- a/wpilibc/src/main/native/cpp/DutyCycle.cpp
+++ b/wpilibc/src/main/native/cpp/DutyCycle.cpp
@@ -17,7 +17,7 @@
DutyCycle::DutyCycle(DigitalSource* source)
: m_source{source, wpi::NullDeleter<DigitalSource>()} {
if (!m_source) {
- throw FRC_MakeError(err::NullParameter, "{}", "source");
+ throw FRC_MakeError(err::NullParameter, "source");
}
InitDutyCycle();
}
@@ -30,7 +30,7 @@
DutyCycle::DutyCycle(std::shared_ptr<DigitalSource> source)
: m_source{std::move(source)} {
if (!m_source) {
- throw FRC_MakeError(err::NullParameter, "{}", "source");
+ throw FRC_MakeError(err::NullParameter, "source");
}
InitDutyCycle();
}
@@ -73,11 +73,11 @@
return retVal;
}
-unsigned int DutyCycle::GetOutputRaw() const {
+units::second_t DutyCycle::GetHighTime() const {
int32_t status = 0;
- auto retVal = HAL_GetDutyCycleOutputRaw(m_handle, &status);
+ auto retVal = HAL_GetDutyCycleHighTime(m_handle, &status);
FRC_CheckErrorStatus(status, "Channel {}", GetSourceChannel());
- return retVal;
+ return units::nanosecond_t{static_cast<double>(retVal)};
}
unsigned int DutyCycle::GetOutputScaleFactor() const {
diff --git a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp
index 452f5cd..b1c943e 100644
--- a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp
+++ b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp
@@ -60,6 +60,8 @@
m_simDevice.CreateDouble("position", hal::SimDevice::kInput, 0.0);
m_simDistancePerRotation = m_simDevice.CreateDouble(
"distance_per_rot", hal::SimDevice::kOutput, 1.0);
+ m_simAbsolutePosition =
+ m_simDevice.CreateDouble("absPosition", hal::SimDevice::kInput, 0.0);
m_simIsConnected =
m_simDevice.CreateBoolean("connected", hal::SimDevice::kInput, true);
} else {
@@ -76,6 +78,11 @@
m_dutyCycle->GetSourceChannel());
}
+static bool DoubleEquals(double a, double b) {
+ constexpr double epsilon = 0.00001;
+ return std::abs(a - b) < epsilon;
+}
+
units::turn_t DutyCycleEncoder::Get() const {
if (m_simPosition) {
return units::turn_t{m_simPosition.Get()};
@@ -88,15 +95,9 @@
auto pos = m_dutyCycle->GetOutput();
auto counter2 = m_counter->Get();
auto pos2 = m_dutyCycle->GetOutput();
- if (counter == counter2 && pos == pos2) {
+ if (counter == counter2 && DoubleEquals(pos, pos2)) {
// map sensor range
- if (pos < m_sensorMin) {
- pos = m_sensorMin;
- }
- if (pos > m_sensorMax) {
- pos = m_sensorMax;
- }
- pos = (pos - m_sensorMin) / (m_sensorMax - m_sensorMin);
+ pos = MapSensorRange(pos);
units::turn_t turns{counter + pos - m_positionOffset};
m_lastPosition = turns;
return turns;
@@ -104,12 +105,39 @@
}
FRC_ReportError(
- warn::Warning, "{}",
+ warn::Warning,
"Failed to read DutyCycle Encoder. Potential Speed Overrun. Returning "
"last value");
return m_lastPosition;
}
+double DutyCycleEncoder::MapSensorRange(double pos) const {
+ if (pos < m_sensorMin) {
+ pos = m_sensorMin;
+ }
+ if (pos > m_sensorMax) {
+ pos = m_sensorMax;
+ }
+ pos = (pos - m_sensorMin) / (m_sensorMax - m_sensorMin);
+ return pos;
+}
+
+double DutyCycleEncoder::GetAbsolutePosition() const {
+ if (m_simAbsolutePosition) {
+ return m_simAbsolutePosition.Get();
+ }
+
+ return MapSensorRange(m_dutyCycle->GetOutput());
+}
+
+double DutyCycleEncoder::GetPositionOffset() const {
+ return m_positionOffset;
+}
+
+void DutyCycleEncoder::SetPositionOffset(double offset) {
+ m_positionOffset = std::clamp(offset, 0.0, 1.0);
+}
+
void DutyCycleEncoder::SetDutyCycleRange(double min, double max) {
m_sensorMin = std::clamp(min, 0.0, 1.0);
m_sensorMax = std::clamp(max, 0.0, 1.0);
diff --git a/wpilibc/src/main/native/cpp/Encoder.cpp b/wpilibc/src/main/native/cpp/Encoder.cpp
index bef6d76..c644070 100644
--- a/wpilibc/src/main/native/cpp/Encoder.cpp
+++ b/wpilibc/src/main/native/cpp/Encoder.cpp
@@ -31,10 +31,10 @@
: m_aSource(aSource, wpi::NullDeleter<DigitalSource>()),
m_bSource(bSource, wpi::NullDeleter<DigitalSource>()) {
if (!m_aSource) {
- throw FRC_MakeError(err::NullParameter, "{}", "aSource");
+ throw FRC_MakeError(err::NullParameter, "aSource");
}
if (!m_bSource) {
- throw FRC_MakeError(err::NullParameter, "{}", "bSource");
+ throw FRC_MakeError(err::NullParameter, "bSource");
}
InitEncoder(reverseDirection, encodingType);
}
@@ -51,10 +51,10 @@
EncodingType encodingType)
: m_aSource(std::move(aSource)), m_bSource(std::move(bSource)) {
if (!m_aSource) {
- throw FRC_MakeError(err::NullParameter, "{}", "aSource");
+ throw FRC_MakeError(err::NullParameter, "aSource");
}
if (!m_bSource) {
- throw FRC_MakeError(err::NullParameter, "{}", "bSource");
+ throw FRC_MakeError(err::NullParameter, "bSource");
}
InitEncoder(reverseDirection, encodingType);
}
@@ -62,100 +62,100 @@
Encoder::~Encoder() {
int32_t status = 0;
HAL_FreeEncoder(m_encoder, &status);
- FRC_ReportError(status, "{}", "FreeEncoder");
+ FRC_ReportError(status, "FreeEncoder");
}
int Encoder::Get() const {
int32_t status = 0;
int value = HAL_GetEncoder(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "Get");
+ FRC_CheckErrorStatus(status, "Get");
return value;
}
void Encoder::Reset() {
int32_t status = 0;
HAL_ResetEncoder(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "Reset");
+ FRC_CheckErrorStatus(status, "Reset");
}
units::second_t Encoder::GetPeriod() const {
int32_t status = 0;
double value = HAL_GetEncoderPeriod(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetPeriod");
+ FRC_CheckErrorStatus(status, "GetPeriod");
return units::second_t{value};
}
void Encoder::SetMaxPeriod(units::second_t maxPeriod) {
int32_t status = 0;
HAL_SetEncoderMaxPeriod(m_encoder, maxPeriod.value(), &status);
- FRC_CheckErrorStatus(status, "{}", "SetMaxPeriod");
+ FRC_CheckErrorStatus(status, "SetMaxPeriod");
}
bool Encoder::GetStopped() const {
int32_t status = 0;
bool value = HAL_GetEncoderStopped(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetStopped");
+ FRC_CheckErrorStatus(status, "GetStopped");
return value;
}
bool Encoder::GetDirection() const {
int32_t status = 0;
bool value = HAL_GetEncoderDirection(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetDirection");
+ FRC_CheckErrorStatus(status, "GetDirection");
return value;
}
int Encoder::GetRaw() const {
int32_t status = 0;
int value = HAL_GetEncoderRaw(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetRaw");
+ FRC_CheckErrorStatus(status, "GetRaw");
return value;
}
int Encoder::GetEncodingScale() const {
int32_t status = 0;
int val = HAL_GetEncoderEncodingScale(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetEncodingScale");
+ FRC_CheckErrorStatus(status, "GetEncodingScale");
return val;
}
double Encoder::GetDistance() const {
int32_t status = 0;
double value = HAL_GetEncoderDistance(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetDistance");
+ FRC_CheckErrorStatus(status, "GetDistance");
return value;
}
double Encoder::GetRate() const {
int32_t status = 0;
double value = HAL_GetEncoderRate(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetRate");
+ FRC_CheckErrorStatus(status, "GetRate");
return value;
}
void Encoder::SetMinRate(double minRate) {
int32_t status = 0;
HAL_SetEncoderMinRate(m_encoder, minRate, &status);
- FRC_CheckErrorStatus(status, "{}", "SetMinRate");
+ FRC_CheckErrorStatus(status, "SetMinRate");
}
void Encoder::SetDistancePerPulse(double distancePerPulse) {
int32_t status = 0;
HAL_SetEncoderDistancePerPulse(m_encoder, distancePerPulse, &status);
- FRC_CheckErrorStatus(status, "{}", "SetDistancePerPulse");
+ FRC_CheckErrorStatus(status, "SetDistancePerPulse");
}
double Encoder::GetDistancePerPulse() const {
int32_t status = 0;
double distancePerPulse = HAL_GetEncoderDistancePerPulse(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetDistancePerPulse");
+ FRC_CheckErrorStatus(status, "GetDistancePerPulse");
return distancePerPulse;
}
void Encoder::SetReverseDirection(bool reverseDirection) {
int32_t status = 0;
HAL_SetEncoderReverseDirection(m_encoder, reverseDirection, &status);
- FRC_CheckErrorStatus(status, "{}", "SetReverseDirection");
+ FRC_CheckErrorStatus(status, "SetReverseDirection");
}
void Encoder::SetSamplesToAverage(int samplesToAverage) {
@@ -167,13 +167,13 @@
}
int32_t status = 0;
HAL_SetEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
- FRC_CheckErrorStatus(status, "{}", "SetSamplesToAverage");
+ FRC_CheckErrorStatus(status, "SetSamplesToAverage");
}
int Encoder::GetSamplesToAverage() const {
int32_t status = 0;
int result = HAL_GetEncoderSamplesToAverage(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetSamplesToAverage");
+ FRC_CheckErrorStatus(status, "GetSamplesToAverage");
return result;
}
@@ -192,7 +192,7 @@
source.GetAnalogTriggerTypeForRouting()),
static_cast<HAL_EncoderIndexingType>(type),
&status);
- FRC_CheckErrorStatus(status, "{}", "SetIndexSource");
+ FRC_CheckErrorStatus(status, "SetIndexSource");
}
void Encoder::SetSimDevice(HAL_SimDeviceHandle device) {
@@ -202,14 +202,14 @@
int Encoder::GetFPGAIndex() const {
int32_t status = 0;
int val = HAL_GetEncoderFPGAIndex(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetFPGAIndex");
+ FRC_CheckErrorStatus(status, "GetFPGAIndex");
return val;
}
void Encoder::InitSendable(wpi::SendableBuilder& builder) {
int32_t status = 0;
HAL_EncoderEncodingType type = HAL_GetEncoderEncodingType(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "GetEncodingType");
+ FRC_CheckErrorStatus(status, "GetEncodingType");
if (type == HAL_EncoderEncodingType::HAL_Encoder_k4X) {
builder.SetSmartDashboardType("Quadrature Encoder");
} else {
@@ -217,11 +217,12 @@
}
builder.AddDoubleProperty(
- "Speed", [=] { return GetRate(); }, nullptr);
+ "Speed", [=, this] { return GetRate(); }, nullptr);
builder.AddDoubleProperty(
- "Distance", [=] { return GetDistance(); }, nullptr);
+ "Distance", [=, this] { return GetDistance(); }, nullptr);
builder.AddDoubleProperty(
- "Distance per Tick", [=] { return GetDistancePerPulse(); }, nullptr);
+ "Distance per Tick", [=, this] { return GetDistancePerPulse(); },
+ nullptr);
}
void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
@@ -235,7 +236,7 @@
m_bSource->GetAnalogTriggerTypeForRouting()),
reverseDirection, static_cast<HAL_EncoderEncodingType>(encodingType),
&status);
- FRC_CheckErrorStatus(status, "{}", "InitEncoder");
+ FRC_CheckErrorStatus(status, "InitEncoder");
HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex() + 1,
encodingType);
@@ -245,6 +246,6 @@
double Encoder::DecodingScaleFactor() const {
int32_t status = 0;
double val = HAL_GetEncoderDecodingScaleFactor(m_encoder, &status);
- FRC_CheckErrorStatus(status, "{}", "DecodingScaleFactor");
+ FRC_CheckErrorStatus(status, "DecodingScaleFactor");
return val;
}
diff --git a/wpilibc/src/main/native/cpp/GenericHID.cpp b/wpilibc/src/main/native/cpp/GenericHID.cpp
index 6c186eb..f4d26b6 100644
--- a/wpilibc/src/main/native/cpp/GenericHID.cpp
+++ b/wpilibc/src/main/native/cpp/GenericHID.cpp
@@ -8,6 +8,7 @@
#include "frc/DriverStation.h"
#include "frc/Errors.h"
+#include "frc/event/BooleanEvent.h"
using namespace frc;
@@ -30,6 +31,11 @@
return DriverStation::GetStickButtonReleased(m_port, button);
}
+BooleanEvent GenericHID::Button(int button, EventLoop* loop) const {
+ return BooleanEvent(loop,
+ [this, button]() { return this->GetRawButton(button); });
+}
+
double GenericHID::GetRawAxis(int axis) const {
return DriverStation::GetStickAxis(m_port, axis);
}
@@ -38,6 +44,65 @@
return DriverStation::GetStickPOV(m_port, pov);
}
+BooleanEvent GenericHID::POV(int angle, EventLoop* loop) const {
+ return POV(0, angle, loop);
+}
+
+BooleanEvent GenericHID::POV(int pov, int angle, EventLoop* loop) const {
+ return BooleanEvent(
+ loop, [this, pov, angle] { return this->GetPOV(pov) == angle; });
+}
+
+BooleanEvent GenericHID::POVUp(EventLoop* loop) const {
+ return POV(0, loop);
+}
+
+BooleanEvent GenericHID::POVUpRight(EventLoop* loop) const {
+ return POV(45, loop);
+}
+
+BooleanEvent GenericHID::POVRight(EventLoop* loop) const {
+ return POV(90, loop);
+}
+
+BooleanEvent GenericHID::POVDownRight(EventLoop* loop) const {
+ return POV(135, loop);
+}
+
+BooleanEvent GenericHID::POVDown(EventLoop* loop) const {
+ return POV(180, loop);
+}
+
+BooleanEvent GenericHID::POVDownLeft(EventLoop* loop) const {
+ return POV(225, loop);
+}
+
+BooleanEvent GenericHID::POVLeft(EventLoop* loop) const {
+ return POV(270, loop);
+}
+
+BooleanEvent GenericHID::POVUpLeft(EventLoop* loop) const {
+ return POV(315, loop);
+}
+
+BooleanEvent GenericHID::POVCenter(EventLoop* loop) const {
+ return POV(360, loop);
+}
+
+BooleanEvent GenericHID::AxisLessThan(int axis, double threshold,
+ EventLoop* loop) const {
+ return BooleanEvent(loop, [this, axis, threshold]() {
+ return this->GetRawAxis(axis) < threshold;
+ });
+}
+
+BooleanEvent GenericHID::AxisGreaterThan(int axis, double threshold,
+ EventLoop* loop) const {
+ return BooleanEvent(loop, [this, axis, threshold]() {
+ return this->GetRawAxis(axis) > threshold;
+ });
+}
+
int GenericHID::GetAxisCount() const {
return DriverStation::GetStickAxisCount(m_port);
}
@@ -83,15 +148,17 @@
}
void GenericHID::SetRumble(RumbleType type, double value) {
- if (value < 0) {
- value = 0;
- } else if (value > 1) {
- value = 1;
- }
+ value = std::clamp(value, 0.0, 1.0);
+ double rumbleValue = value * 65535;
+
if (type == kLeftRumble) {
- m_leftRumble = value * 65535;
+ m_leftRumble = rumbleValue;
+ } else if (type == kRightRumble) {
+ m_rightRumble = rumbleValue;
} else {
- m_rightRumble = value * 65535;
+ m_leftRumble = rumbleValue;
+ m_rightRumble = rumbleValue;
}
+
HAL_SetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
}
diff --git a/wpilibc/src/main/native/cpp/I2C.cpp b/wpilibc/src/main/native/cpp/I2C.cpp
index dcfb2b8..da26c0c 100644
--- a/wpilibc/src/main/native/cpp/I2C.cpp
+++ b/wpilibc/src/main/native/cpp/I2C.cpp
@@ -18,14 +18,14 @@
int32_t status = 0;
if (port == I2C::Port::kOnboard) {
- FRC_ReportError(warn::Warning, "{}",
+ FRC_ReportError(warn::Warning,
"Onboard I2C port is subject to system lockups. See Known "
"Issues page for "
"details");
}
HAL_InitializeI2C(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(port));
HAL_Report(HALUsageReporting::kResourceType_I2C, deviceAddress);
}
@@ -74,7 +74,7 @@
throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
}
if (!buffer) {
- throw FRC_MakeError(err::NullParameter, "{}", "buffer");
+ throw FRC_MakeError(err::NullParameter, "buffer");
}
uint8_t regAddr = registerAddress;
return Transaction(®Addr, sizeof(regAddr), buffer, count);
@@ -85,7 +85,7 @@
throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
}
if (!buffer) {
- throw FRC_MakeError(err::NullParameter, "{}", "buffer");
+ throw FRC_MakeError(err::NullParameter, "buffer");
}
return HAL_ReadI2C(m_port, m_deviceAddress, buffer, count) < 0;
}
diff --git a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp
index 47eb299..0bccb0b 100644
--- a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp
+++ b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp
@@ -4,6 +4,8 @@
#include "frc/IterativeRobotBase.h"
+#include <frc/DriverStation.h>
+
#include <fmt/format.h>
#include <hal/DriverStation.h>
#include <networktables/NetworkTableInstance.h>
@@ -16,9 +18,6 @@
using namespace frc;
-IterativeRobotBase::IterativeRobotBase(double period)
- : IterativeRobotBase(units::second_t(period)) {}
-
IterativeRobotBase::IterativeRobotBase(units::second_t period)
: m_period(period),
m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {}
@@ -95,11 +94,24 @@
m_ntFlushEnabled = enabled;
}
+void IterativeRobotBase::EnableLiveWindowInTest(bool testLW) {
+ if (IsTest()) {
+ throw FRC_MakeError(err::IncompatibleMode,
+ "Can't configure test mode while in test mode!");
+ }
+ m_lwEnabledInTest = testLW;
+}
+
+bool IterativeRobotBase::IsLiveWindowEnabledInTest() {
+ return m_lwEnabledInTest;
+}
+
units::second_t IterativeRobotBase::GetPeriod() const {
return m_period;
}
void IterativeRobotBase::LoopFunc() {
+ DriverStation::RefreshData();
m_watchdog.Reset();
// Get current mode
@@ -125,8 +137,10 @@
} else if (m_lastMode == Mode::kTeleop) {
TeleopExit();
} else if (m_lastMode == Mode::kTest) {
- LiveWindow::SetEnabled(false);
- Shuffleboard::DisableActuatorWidgets();
+ if (m_lwEnabledInTest) {
+ LiveWindow::SetEnabled(false);
+ Shuffleboard::DisableActuatorWidgets();
+ }
TestExit();
}
@@ -141,8 +155,10 @@
TeleopInit();
m_watchdog.AddEpoch("TeleopInit()");
} else if (mode == Mode::kTest) {
- LiveWindow::SetEnabled(true);
- Shuffleboard::EnableActuatorWidgets();
+ if (m_lwEnabledInTest) {
+ LiveWindow::SetEnabled(true);
+ Shuffleboard::EnableActuatorWidgets();
+ }
TestInit();
m_watchdog.AddEpoch("TestInit()");
}
@@ -190,7 +206,7 @@
// Flush NetworkTables
if (m_ntFlushEnabled) {
- nt::NetworkTableInstance::GetDefault().Flush();
+ nt::NetworkTableInstance::GetDefault().FlushLocal();
}
// Warn on loop time overruns
diff --git a/wpilibc/src/main/native/cpp/Joystick.cpp b/wpilibc/src/main/native/cpp/Joystick.cpp
index 48f0c77..0eff226 100644
--- a/wpilibc/src/main/native/cpp/Joystick.cpp
+++ b/wpilibc/src/main/native/cpp/Joystick.cpp
@@ -5,9 +5,11 @@
#include "frc/Joystick.h"
#include <cmath>
+#include <numbers>
#include <hal/FRCUsageReporting.h>
-#include <wpi/numbers>
+
+#include "frc/event/BooleanEvent.h"
using namespace frc;
@@ -93,6 +95,10 @@
return GetRawButtonReleased(Button::kTrigger);
}
+BooleanEvent Joystick::Trigger(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetTrigger(); });
+}
+
bool Joystick::GetTop() const {
return GetRawButton(Button::kTop);
}
@@ -105,8 +111,12 @@
return GetRawButtonReleased(Button::kTop);
}
+BooleanEvent Joystick::Top(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetTop(); });
+}
+
double Joystick::GetMagnitude() const {
- return std::sqrt(std::pow(GetX(), 2) + std::pow(GetY(), 2));
+ return std::hypot(GetX(), GetY());
}
double Joystick::GetDirectionRadians() const {
@@ -114,5 +124,5 @@
}
double Joystick::GetDirectionDegrees() const {
- return (180 / wpi::numbers::pi) * GetDirectionRadians();
+ return (180 / std::numbers::pi) * GetDirectionRadians();
}
diff --git a/wpilibc/src/main/native/cpp/MotorSafety.cpp b/wpilibc/src/main/native/cpp/MotorSafety.cpp
index 388a887..368092b 100644
--- a/wpilibc/src/main/native/cpp/MotorSafety.cpp
+++ b/wpilibc/src/main/native/cpp/MotorSafety.cpp
@@ -7,6 +7,8 @@
#include <algorithm>
#include <utility>
+#include <hal/DriverStation.h>
+#include <wpi/SafeThread.h>
#include <wpi/SmallPtrSet.h>
#include "frc/DriverStation.h"
@@ -14,26 +16,87 @@
using namespace frc;
-static wpi::SmallPtrSet<MotorSafety*, 32> instanceList;
-static wpi::mutex listMutex;
+namespace {
+class Thread : public wpi::SafeThread {
+ public:
+ Thread() {}
+ void Main() override;
+};
+
+void Thread::Main() {
+ wpi::Event event{false, false};
+ HAL_ProvideNewDataEventHandle(event.GetHandle());
+
+ int safetyCounter = 0;
+ while (m_active) {
+ bool timedOut = false;
+ bool signaled = wpi::WaitForObject(event.GetHandle(), 0.1, &timedOut);
+ if (signaled) {
+ HAL_ControlWord controlWord;
+ std::memset(&controlWord, 0, sizeof(controlWord));
+ HAL_GetControlWord(&controlWord);
+ if (!(controlWord.enabled && controlWord.dsAttached)) {
+ safetyCounter = 0;
+ }
+ if (++safetyCounter >= 4) {
+ MotorSafety::CheckMotors();
+ safetyCounter = 0;
+ }
+ } else {
+ safetyCounter = 0;
+ }
+ }
+
+ HAL_RemoveNewDataEventHandle(event.GetHandle());
+}
+} // namespace
+
+static std::atomic_bool gShutdown{false};
+
+namespace {
+struct MotorSafetyManager {
+ ~MotorSafetyManager() { gShutdown = true; }
+
+ wpi::SafeThreadOwner<Thread> thread;
+ wpi::SmallPtrSet<MotorSafety*, 32> instanceList;
+ wpi::mutex listMutex;
+ bool threadStarted = false;
+};
+} // namespace
+
+static MotorSafetyManager& GetManager() {
+ static MotorSafetyManager manager;
+ return manager;
+}
#ifndef __FRC_ROBORIO__
namespace frc::impl {
void ResetMotorSafety() {
- std::scoped_lock lock(listMutex);
- instanceList.clear();
+ auto& manager = GetManager();
+ std::scoped_lock lock(manager.listMutex);
+ manager.instanceList.clear();
+ manager.thread.Stop();
+ manager.thread.Join();
+ manager.thread = wpi::SafeThreadOwner<Thread>{};
+ manager.threadStarted = false;
}
} // namespace frc::impl
#endif
MotorSafety::MotorSafety() {
- std::scoped_lock lock(listMutex);
- instanceList.insert(this);
+ auto& manager = GetManager();
+ std::scoped_lock lock(manager.listMutex);
+ manager.instanceList.insert(this);
+ if (!manager.threadStarted) {
+ manager.threadStarted = true;
+ manager.thread.Start();
+ }
}
MotorSafety::~MotorSafety() {
- std::scoped_lock lock(listMutex);
- instanceList.erase(this);
+ auto& manager = GetManager();
+ std::scoped_lock lock(manager.listMutex);
+ manager.instanceList.erase(this);
}
MotorSafety::MotorSafety(MotorSafety&& rhs)
@@ -96,7 +159,9 @@
}
if (stopTime < Timer::GetFPGATimestamp()) {
- FRC_ReportError(err::Timeout, "{}... Output not updated often enough",
+ FRC_ReportError(err::Timeout,
+ "{}... Output not updated often enough. See "
+ "https://docs.wpilib.org/motorsafety for more information.",
GetDescription());
try {
@@ -111,8 +176,9 @@
}
void MotorSafety::CheckMotors() {
- std::scoped_lock lock(listMutex);
- for (auto elem : instanceList) {
+ auto& manager = GetManager();
+ std::scoped_lock lock(manager.listMutex);
+ for (auto elem : manager.instanceList) {
elem->Check();
}
}
diff --git a/wpilibc/src/main/native/cpp/Notifier.cpp b/wpilibc/src/main/native/cpp/Notifier.cpp
index 441f750..d837752 100644
--- a/wpilibc/src/main/native/cpp/Notifier.cpp
+++ b/wpilibc/src/main/native/cpp/Notifier.cpp
@@ -7,6 +7,7 @@
#include <utility>
#include <fmt/format.h>
+#include <hal/DriverStation.h>
#include <hal/FRCUsageReporting.h>
#include <hal/Notifier.h>
#include <hal/Threads.h>
@@ -18,14 +19,14 @@
Notifier::Notifier(std::function<void()> handler) {
if (!handler) {
- throw FRC_MakeError(err::NullParameter, "{}", "handler");
+ throw FRC_MakeError(err::NullParameter, "handler");
}
m_handler = handler;
int32_t status = 0;
m_notifier = HAL_InitializeNotifier(&status);
- FRC_CheckErrorStatus(status, "{}", "InitializeNotifier");
+ FRC_CheckErrorStatus(status, "InitializeNotifier");
- m_thread = std::thread([=] {
+ m_thread = std::thread([=, this] {
for (;;) {
int32_t status = 0;
HAL_NotifierHandle notifier = m_notifier.load();
@@ -60,14 +61,14 @@
Notifier::Notifier(int priority, std::function<void()> handler) {
if (!handler) {
- throw FRC_MakeError(err::NullParameter, "{}", "handler");
+ throw FRC_MakeError(err::NullParameter, "handler");
}
m_handler = handler;
int32_t status = 0;
m_notifier = HAL_InitializeNotifier(&status);
- FRC_CheckErrorStatus(status, "{}", "InitializeNotifier");
+ FRC_CheckErrorStatus(status, "InitializeNotifier");
- m_thread = std::thread([=] {
+ m_thread = std::thread([=, this] {
int32_t status = 0;
HAL_SetCurrentThreadPriority(true, priority, &status);
for (;;) {
@@ -95,7 +96,21 @@
// call callback
if (handler) {
- handler();
+ try {
+ handler();
+ } catch (const frc::RuntimeError& e) {
+ e.Report();
+ FRC_ReportError(
+ err::Error,
+ "Error in Notifier thread."
+ " The above stacktrace can help determine where the error "
+ "occurred.\n"
+ " See https://wpilib.org/stacktrace for more information.\n");
+ throw;
+ } catch (const std::exception& e) {
+ HAL_SendError(1, err::Error, 0, e.what(), "", "", 1);
+ throw;
+ }
}
}
});
@@ -106,7 +121,7 @@
// atomically set handle to 0, then clean
HAL_NotifierHandle handle = m_notifier.exchange(0);
HAL_StopNotifier(handle, &status);
- FRC_ReportError(status, "{}", "StopNotifier");
+ FRC_ReportError(status, "StopNotifier");
// Join the thread to ensure the handler has exited.
if (m_thread.joinable()) {
@@ -172,7 +187,7 @@
m_periodic = false;
int32_t status = 0;
HAL_CancelNotifierAlarm(m_notifier, &status);
- FRC_CheckErrorStatus(status, "{}", "CancelNotifierAlarm");
+ FRC_CheckErrorStatus(status, "CancelNotifierAlarm");
}
void Notifier::UpdateAlarm(uint64_t triggerTime) {
@@ -183,7 +198,7 @@
return;
}
HAL_UpdateNotifierAlarm(notifier, triggerTime, &status);
- FRC_CheckErrorStatus(status, "{}", "UpdateNotifierAlarm");
+ FRC_CheckErrorStatus(status, "UpdateNotifierAlarm");
}
void Notifier::UpdateAlarm() {
diff --git a/wpilibc/src/main/native/cpp/PS4Controller.cpp b/wpilibc/src/main/native/cpp/PS4Controller.cpp
index 91fd304..e59e18c 100644
--- a/wpilibc/src/main/native/cpp/PS4Controller.cpp
+++ b/wpilibc/src/main/native/cpp/PS4Controller.cpp
@@ -6,6 +6,8 @@
#include <hal/FRCUsageReporting.h>
+#include "frc/event/BooleanEvent.h"
+
using namespace frc;
PS4Controller::PS4Controller(int port) : GenericHID(port) {
@@ -48,6 +50,10 @@
return GetRawButtonReleased(Button::kSquare);
}
+BooleanEvent PS4Controller::Square(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetSquareButton(); });
+}
+
bool PS4Controller::GetCrossButton() const {
return GetRawButton(Button::kCross);
}
@@ -60,6 +66,10 @@
return GetRawButtonReleased(Button::kCross);
}
+BooleanEvent PS4Controller::Cross(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetCrossButton(); });
+}
+
bool PS4Controller::GetCircleButton() const {
return GetRawButton(Button::kCircle);
}
@@ -72,6 +82,10 @@
return GetRawButtonReleased(Button::kCircle);
}
+BooleanEvent PS4Controller::Circle(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetCircleButton(); });
+}
+
bool PS4Controller::GetTriangleButton() const {
return GetRawButton(Button::kTriangle);
}
@@ -84,6 +98,10 @@
return GetRawButtonReleased(Button::kTriangle);
}
+BooleanEvent PS4Controller::Triangle(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetTriangleButton(); });
+}
+
bool PS4Controller::GetL1Button() const {
return GetRawButton(Button::kL1);
}
@@ -96,6 +114,10 @@
return GetRawButtonReleased(Button::kL1);
}
+BooleanEvent PS4Controller::L1(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetL1Button(); });
+}
+
bool PS4Controller::GetR1Button() const {
return GetRawButton(Button::kR1);
}
@@ -108,6 +130,10 @@
return GetRawButtonReleased(Button::kR1);
}
+BooleanEvent PS4Controller::R1(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetR1Button(); });
+}
+
bool PS4Controller::GetL2Button() const {
return GetRawButton(Button::kL2);
}
@@ -120,6 +146,10 @@
return GetRawButtonReleased(Button::kL2);
}
+BooleanEvent PS4Controller::L2(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetL2Button(); });
+}
+
bool PS4Controller::GetR2Button() const {
return GetRawButton(Button::kR2);
}
@@ -132,6 +162,10 @@
return GetRawButtonReleased(Button::kR2);
}
+BooleanEvent PS4Controller::R2(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetR2Button(); });
+}
+
bool PS4Controller::GetShareButton() const {
return GetRawButton(Button::kShare);
}
@@ -144,6 +178,10 @@
return GetRawButtonReleased(Button::kShare);
}
+BooleanEvent PS4Controller::Share(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetShareButton(); });
+}
+
bool PS4Controller::GetOptionsButton() const {
return GetRawButton(Button::kOptions);
}
@@ -156,6 +194,10 @@
return GetRawButtonReleased(Button::kOptions);
}
+BooleanEvent PS4Controller::Options(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetOptionsButton(); });
+}
+
bool PS4Controller::GetL3Button() const {
return GetRawButton(Button::kL3);
}
@@ -168,6 +210,10 @@
return GetRawButtonReleased(Button::kL3);
}
+BooleanEvent PS4Controller::L3(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetL3Button(); });
+}
+
bool PS4Controller::GetR3Button() const {
return GetRawButton(Button::kR3);
}
@@ -180,6 +226,10 @@
return GetRawButtonReleased(Button::kR3);
}
+BooleanEvent PS4Controller::R3(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetR3Button(); });
+}
+
bool PS4Controller::GetPSButton() const {
return GetRawButton(Button::kPS);
}
@@ -192,6 +242,10 @@
return GetRawButtonReleased(Button::kPS);
}
+BooleanEvent PS4Controller::PS(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetPSButton(); });
+}
+
bool PS4Controller::GetTouchpad() const {
return GetRawButton(Button::kTouchpad);
}
@@ -203,3 +257,7 @@
bool PS4Controller::GetTouchpadReleased() {
return GetRawButtonReleased(Button::kTouchpad);
}
+
+BooleanEvent PS4Controller::Touchpad(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetTouchpad(); });
+}
diff --git a/wpilibc/src/main/native/cpp/PWM.cpp b/wpilibc/src/main/native/cpp/PWM.cpp
index 393accc..5c5e6f5 100644
--- a/wpilibc/src/main/native/cpp/PWM.cpp
+++ b/wpilibc/src/main/native/cpp/PWM.cpp
@@ -117,7 +117,7 @@
break;
default:
throw FRC_MakeError(err::InvalidParameter, "PeriodMultiplier value {}",
- mult);
+ static_cast<int>(mult));
}
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
@@ -166,7 +166,8 @@
void PWM::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("PWM");
builder.SetActuator(true);
- builder.SetSafeState([=] { SetDisabled(); });
+ builder.SetSafeState([=, this] { SetDisabled(); });
builder.AddDoubleProperty(
- "Value", [=] { return GetRaw(); }, [=](double value) { SetRaw(value); });
+ "Value", [=, this] { return GetRaw(); },
+ [=, this](double value) { SetRaw(value); });
}
diff --git a/wpilibc/src/main/native/cpp/PneumaticHub.cpp b/wpilibc/src/main/native/cpp/PneumaticHub.cpp
index 0f32e1e..ec008cf 100644
--- a/wpilibc/src/main/native/cpp/PneumaticHub.cpp
+++ b/wpilibc/src/main/native/cpp/PneumaticHub.cpp
@@ -4,6 +4,8 @@
#include "frc/PneumaticHub.h"
+#include <array>
+
#include <fmt/format.h>
#include <hal/REVPH.h>
#include <wpi/NullDeleter.h>
@@ -146,7 +148,7 @@
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) {
if (minPressure >= maxPressure) {
- throw FRC_MakeError(err::InvalidParameter, "{}",
+ throw FRC_MakeError(err::InvalidParameter,
"maxPressure must be greater than minPresure");
}
if (minPressure < 0_psi || minPressure > 120_psi) {
@@ -171,7 +173,7 @@
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) {
if (minPressure >= maxPressure) {
- throw FRC_MakeError(err::InvalidParameter, "{}",
+ throw FRC_MakeError(err::InvalidParameter,
"maxPressure must be greater than minPresure");
}
if (minPressure < 0_psi || minPressure > 120_psi) {
diff --git a/wpilibc/src/main/native/cpp/PowerDistribution.cpp b/wpilibc/src/main/native/cpp/PowerDistribution.cpp
index 21101f2..ba4cb38 100644
--- a/wpilibc/src/main/native/cpp/PowerDistribution.cpp
+++ b/wpilibc/src/main/native/cpp/PowerDistribution.cpp
@@ -195,7 +195,7 @@
for (int i = 0; i < numChannels; ++i) {
builder.AddDoubleProperty(
fmt::format("Chan{}", i),
- [=] {
+ [=, this] {
int32_t lStatus = 0;
return HAL_GetPowerDistributionChannelCurrent(m_handle, i, &lStatus);
},
@@ -203,25 +203,25 @@
}
builder.AddDoubleProperty(
"Voltage",
- [=] {
+ [=, this] {
int32_t lStatus = 0;
return HAL_GetPowerDistributionVoltage(m_handle, &lStatus);
},
nullptr);
builder.AddDoubleProperty(
"TotalCurrent",
- [=] {
+ [=, this] {
int32_t lStatus = 0;
return HAL_GetPowerDistributionTotalCurrent(m_handle, &lStatus);
},
nullptr);
builder.AddBooleanProperty(
"SwitchableChannel",
- [=] {
+ [=, this] {
int32_t lStatus = 0;
return HAL_GetPowerDistributionSwitchableChannel(m_handle, &lStatus);
},
- [=](bool value) {
+ [=, this](bool value) {
int32_t lStatus = 0;
HAL_SetPowerDistributionSwitchableChannel(m_handle, value, &lStatus);
});
diff --git a/wpilibc/src/main/native/cpp/Preferences.cpp b/wpilibc/src/main/native/cpp/Preferences.cpp
index 4663875..cfb5964 100644
--- a/wpilibc/src/main/native/cpp/Preferences.cpp
+++ b/wpilibc/src/main/native/cpp/Preferences.cpp
@@ -6,9 +6,13 @@
#include <algorithm>
+#include <fmt/format.h>
#include <hal/FRCUsageReporting.h>
+#include <networktables/MultiSubscriber.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
+#include <networktables/NetworkTableListener.h>
+#include <networktables/StringTopic.h>
using namespace frc;
@@ -21,7 +25,10 @@
std::shared_ptr<nt::NetworkTable> table{
nt::NetworkTableInstance::GetDefault().GetTable(kTableName)};
- NT_EntryListener listener;
+ nt::StringPublisher typePublisher{table->GetStringTopic(".type").Publish()};
+ nt::MultiSubscriber tableSubscriber{nt::NetworkTableInstance::GetDefault(),
+ {{fmt::format("{}/", table->GetPath())}}};
+ nt::NetworkTableListener listener;
};
} // namespace
@@ -38,40 +45,33 @@
} // namespace frc::impl
#endif
-Preferences* Preferences::GetInstance() {
- ::GetInstance();
- static Preferences instance;
- return &instance;
-}
-
std::vector<std::string> Preferences::GetKeys() {
return ::GetInstance().table->GetKeys();
}
std::string Preferences::GetString(std::string_view key,
std::string_view defaultValue) {
- return ::GetInstance().table->GetString(key, defaultValue);
+ return ::GetInstance().table->GetEntry(key).GetString(defaultValue);
}
int Preferences::GetInt(std::string_view key, int defaultValue) {
- return static_cast<int>(::GetInstance().table->GetNumber(key, defaultValue));
+ return ::GetInstance().table->GetEntry(key).GetInteger(defaultValue);
}
double Preferences::GetDouble(std::string_view key, double defaultValue) {
- return ::GetInstance().table->GetNumber(key, defaultValue);
+ return ::GetInstance().table->GetEntry(key).GetDouble(defaultValue);
}
float Preferences::GetFloat(std::string_view key, float defaultValue) {
- return ::GetInstance().table->GetNumber(key, defaultValue);
+ return ::GetInstance().table->GetEntry(key).GetFloat(defaultValue);
}
bool Preferences::GetBoolean(std::string_view key, bool defaultValue) {
- return ::GetInstance().table->GetBoolean(key, defaultValue);
+ return ::GetInstance().table->GetEntry(key).GetBoolean(defaultValue);
}
int64_t Preferences::GetLong(std::string_view key, int64_t defaultValue) {
- return static_cast<int64_t>(
- ::GetInstance().table->GetNumber(key, defaultValue));
+ return ::GetInstance().table->GetEntry(key).GetInteger(defaultValue);
}
void Preferences::SetString(std::string_view key, std::string_view value) {
@@ -80,10 +80,6 @@
entry.SetPersistent();
}
-void Preferences::PutString(std::string_view key, std::string_view value) {
- SetString(key, value);
-}
-
void Preferences::InitString(std::string_view key, std::string_view value) {
auto entry = ::GetInstance().table->GetEntry(key);
entry.SetDefaultString(value);
@@ -92,17 +88,13 @@
void Preferences::SetInt(std::string_view key, int value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDouble(value);
+ entry.SetInteger(value);
entry.SetPersistent();
}
-void Preferences::PutInt(std::string_view key, int value) {
- SetInt(key, value);
-}
-
void Preferences::InitInt(std::string_view key, int value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDefaultDouble(value);
+ entry.SetDefaultInteger(value);
entry.SetPersistent();
}
@@ -112,10 +104,6 @@
entry.SetPersistent();
}
-void Preferences::PutDouble(std::string_view key, double value) {
- SetDouble(key, value);
-}
-
void Preferences::InitDouble(std::string_view key, double value) {
auto entry = ::GetInstance().table->GetEntry(key);
entry.SetDefaultDouble(value);
@@ -124,17 +112,13 @@
void Preferences::SetFloat(std::string_view key, float value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDouble(value);
+ entry.SetFloat(value);
entry.SetPersistent();
}
-void Preferences::PutFloat(std::string_view key, float value) {
- SetFloat(key, value);
-}
-
void Preferences::InitFloat(std::string_view key, float value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDefaultDouble(value);
+ entry.SetDefaultFloat(value);
entry.SetPersistent();
}
@@ -144,10 +128,6 @@
entry.SetPersistent();
}
-void Preferences::PutBoolean(std::string_view key, bool value) {
- SetBoolean(key, value);
-}
-
void Preferences::InitBoolean(std::string_view key, bool value) {
auto entry = ::GetInstance().table->GetEntry(key);
entry.SetDefaultBoolean(value);
@@ -156,17 +136,13 @@
void Preferences::SetLong(std::string_view key, int64_t value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDouble(value);
+ entry.SetInteger(value);
entry.SetPersistent();
}
-void Preferences::PutLong(std::string_view key, int64_t value) {
- SetLong(key, value);
-}
-
void Preferences::InitLong(std::string_view key, int64_t value) {
auto entry = ::GetInstance().table->GetEntry(key);
- entry.SetDefaultDouble(value);
+ entry.SetDefaultInteger(value);
entry.SetPersistent();
}
@@ -175,7 +151,9 @@
}
void Preferences::Remove(std::string_view key) {
- ::GetInstance().table->Delete(key);
+ auto entry = ::GetInstance().table->GetEntry(key);
+ entry.ClearPersistent();
+ entry.Unpublish();
}
void Preferences::RemoveAll() {
@@ -187,11 +165,15 @@
}
Instance::Instance() {
- table->GetEntry(".type").SetString("RobotPreferences");
- listener = table->AddEntryListener(
- [=](nt::NetworkTable* table, std::string_view name,
- nt::NetworkTableEntry entry, std::shared_ptr<nt::Value> value,
- int flags) { entry.SetPersistent(); },
- NT_NOTIFY_NEW | NT_NOTIFY_IMMEDIATE);
+ typePublisher.Set("RobotPreferences");
+ listener = nt::NetworkTableListener::CreateListener(
+ tableSubscriber, NT_EVENT_PUBLISH | NT_EVENT_IMMEDIATE,
+ [typeTopic = typePublisher.GetTopic().GetHandle()](auto& event) {
+ if (auto topicInfo = event.GetTopicInfo()) {
+ if (topicInfo->topic != typeTopic) {
+ nt::SetTopicPersistent(topicInfo->topic, true);
+ }
+ }
+ });
HAL_Report(HALUsageReporting::kResourceType_Preferences, 0);
}
diff --git a/wpilibc/src/main/native/cpp/Relay.cpp b/wpilibc/src/main/native/cpp/Relay.cpp
index 9bec566..3dfbe64 100644
--- a/wpilibc/src/main/native/cpp/Relay.cpp
+++ b/wpilibc/src/main/native/cpp/Relay.cpp
@@ -175,10 +175,10 @@
void Relay::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Relay");
builder.SetActuator(true);
- builder.SetSafeState([=] { Set(kOff); });
+ builder.SetSafeState([=, this] { Set(kOff); });
builder.AddSmallStringProperty(
"Value",
- [=](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
+ [=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
switch (Get()) {
case kOn:
return "On";
@@ -190,7 +190,7 @@
return "Off";
}
},
- [=](std::string_view value) {
+ [=, this](std::string_view value) {
if (value == "Off") {
Set(kOff);
} else if (value == "Forward") {
diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp
index 8bc2d6b..da6e364 100644
--- a/wpilibc/src/main/native/cpp/RobotController.cpp
+++ b/wpilibc/src/main/native/cpp/RobotController.cpp
@@ -4,6 +4,8 @@
#include "frc/RobotController.h"
+#include <cstddef>
+
#include <hal/CAN.h>
#include <hal/HALBase.h>
#include <hal/Power.h>
@@ -15,161 +17,174 @@
int RobotController::GetFPGAVersion() {
int32_t status = 0;
int version = HAL_GetFPGAVersion(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFPGAVersion");
+ FRC_CheckErrorStatus(status, "GetFPGAVersion");
return version;
}
int64_t RobotController::GetFPGARevision() {
int32_t status = 0;
int64_t revision = HAL_GetFPGARevision(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFPGARevision");
+ FRC_CheckErrorStatus(status, "GetFPGARevision");
return revision;
}
+std::string RobotController::GetSerialNumber() {
+ // Serial number is 8 characters
+ char serialNum[9];
+ size_t len = HAL_GetSerialNumber(serialNum, sizeof(serialNum));
+ return std::string(serialNum, len);
+}
+
+std::string RobotController::GetComments() {
+ char comments[65];
+ size_t len = HAL_GetComments(comments, sizeof(comments));
+ return std::string(comments, len);
+}
+
uint64_t RobotController::GetFPGATime() {
int32_t status = 0;
uint64_t time = HAL_GetFPGATime(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFPGATime");
+ FRC_CheckErrorStatus(status, "GetFPGATime");
return time;
}
bool RobotController::GetUserButton() {
int32_t status = 0;
bool value = HAL_GetFPGAButton(&status);
- FRC_CheckErrorStatus(status, "{}", "GetUserButton");
+ FRC_CheckErrorStatus(status, "GetUserButton");
return value;
}
units::volt_t RobotController::GetBatteryVoltage() {
int32_t status = 0;
double retVal = HAL_GetVinVoltage(&status);
- FRC_CheckErrorStatus(status, "{}", "GetBatteryVoltage");
+ FRC_CheckErrorStatus(status, "GetBatteryVoltage");
return units::volt_t{retVal};
}
bool RobotController::IsSysActive() {
int32_t status = 0;
bool retVal = HAL_GetSystemActive(&status);
- FRC_CheckErrorStatus(status, "{}", "IsSysActive");
+ FRC_CheckErrorStatus(status, "IsSysActive");
return retVal;
}
bool RobotController::IsBrownedOut() {
int32_t status = 0;
bool retVal = HAL_GetBrownedOut(&status);
- FRC_CheckErrorStatus(status, "{}", "IsBrownedOut");
+ FRC_CheckErrorStatus(status, "IsBrownedOut");
return retVal;
}
double RobotController::GetInputVoltage() {
int32_t status = 0;
double retVal = HAL_GetVinVoltage(&status);
- FRC_CheckErrorStatus(status, "{}", "GetInputVoltage");
+ FRC_CheckErrorStatus(status, "GetInputVoltage");
return retVal;
}
double RobotController::GetInputCurrent() {
int32_t status = 0;
double retVal = HAL_GetVinCurrent(&status);
- FRC_CheckErrorStatus(status, "{}", "GetInputCurrent");
+ FRC_CheckErrorStatus(status, "GetInputCurrent");
return retVal;
}
double RobotController::GetVoltage3V3() {
int32_t status = 0;
double retVal = HAL_GetUserVoltage3V3(&status);
- FRC_CheckErrorStatus(status, "{}", "GetVoltage3V3");
+ FRC_CheckErrorStatus(status, "GetVoltage3V3");
return retVal;
}
double RobotController::GetCurrent3V3() {
int32_t status = 0;
double retVal = HAL_GetUserCurrent3V3(&status);
- FRC_CheckErrorStatus(status, "{}", "GetCurrent3V3");
+ FRC_CheckErrorStatus(status, "GetCurrent3V3");
return retVal;
}
bool RobotController::GetEnabled3V3() {
int32_t status = 0;
bool retVal = HAL_GetUserActive3V3(&status);
- FRC_CheckErrorStatus(status, "{}", "GetEnabled3V3");
+ FRC_CheckErrorStatus(status, "GetEnabled3V3");
return retVal;
}
int RobotController::GetFaultCount3V3() {
int32_t status = 0;
int retVal = HAL_GetUserCurrentFaults3V3(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFaultCount3V3");
+ FRC_CheckErrorStatus(status, "GetFaultCount3V3");
return retVal;
}
double RobotController::GetVoltage5V() {
int32_t status = 0;
double retVal = HAL_GetUserVoltage5V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetVoltage5V");
+ FRC_CheckErrorStatus(status, "GetVoltage5V");
return retVal;
}
double RobotController::GetCurrent5V() {
int32_t status = 0;
double retVal = HAL_GetUserCurrent5V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetCurrent5V");
+ FRC_CheckErrorStatus(status, "GetCurrent5V");
return retVal;
}
bool RobotController::GetEnabled5V() {
int32_t status = 0;
bool retVal = HAL_GetUserActive5V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetEnabled5V");
+ FRC_CheckErrorStatus(status, "GetEnabled5V");
return retVal;
}
int RobotController::GetFaultCount5V() {
int32_t status = 0;
int retVal = HAL_GetUserCurrentFaults5V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFaultCount5V");
+ FRC_CheckErrorStatus(status, "GetFaultCount5V");
return retVal;
}
double RobotController::GetVoltage6V() {
int32_t status = 0;
double retVal = HAL_GetUserVoltage6V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetVoltage6V");
+ FRC_CheckErrorStatus(status, "GetVoltage6V");
return retVal;
}
double RobotController::GetCurrent6V() {
int32_t status = 0;
double retVal = HAL_GetUserCurrent6V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetCurrent6V");
+ FRC_CheckErrorStatus(status, "GetCurrent6V");
return retVal;
}
bool RobotController::GetEnabled6V() {
int32_t status = 0;
bool retVal = HAL_GetUserActive6V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetEnabled6V");
+ FRC_CheckErrorStatus(status, "GetEnabled6V");
return retVal;
}
int RobotController::GetFaultCount6V() {
int32_t status = 0;
int retVal = HAL_GetUserCurrentFaults6V(&status);
- FRC_CheckErrorStatus(status, "{}", "GetFaultCount6V");
+ FRC_CheckErrorStatus(status, "GetFaultCount6V");
return retVal;
}
units::volt_t RobotController::GetBrownoutVoltage() {
int32_t status = 0;
double retVal = HAL_GetBrownoutVoltage(&status);
- FRC_CheckErrorStatus(status, "{}", "GetBrownoutVoltage");
- return units::volt_t(retVal);
+ FRC_CheckErrorStatus(status, "GetBrownoutVoltage");
+ return units::volt_t{retVal};
}
void RobotController::SetBrownoutVoltage(units::volt_t brownoutVoltage) {
int32_t status = 0;
HAL_SetBrownoutVoltage(brownoutVoltage.value(), &status);
- FRC_CheckErrorStatus(status, "{}", "SetBrownoutVoltage");
+ FRC_CheckErrorStatus(status, "SetBrownoutVoltage");
}
CANStatus RobotController::GetCANStatus() {
@@ -181,7 +196,7 @@
uint32_t transmitErrorCount = 0;
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
&receiveErrorCount, &transmitErrorCount, &status);
- FRC_CheckErrorStatus(status, "{}", "GetCANStatus");
+ FRC_CheckErrorStatus(status, "GetCANStatus");
return {percentBusUtilization, static_cast<int>(busOffCount),
static_cast<int>(txFullCount), static_cast<int>(receiveErrorCount),
static_cast<int>(transmitErrorCount)};
diff --git a/wpilibc/src/main/native/cpp/RobotState.cpp b/wpilibc/src/main/native/cpp/RobotState.cpp
index 651a644..ede314c 100644
--- a/wpilibc/src/main/native/cpp/RobotState.cpp
+++ b/wpilibc/src/main/native/cpp/RobotState.cpp
@@ -20,10 +20,6 @@
return DriverStation::IsEStopped();
}
-bool RobotState::IsOperatorControl() {
- return IsTeleop();
-}
-
bool RobotState::IsTeleop() {
return DriverStation::IsTeleop();
}
diff --git a/wpilibc/src/main/native/cpp/SPI.cpp b/wpilibc/src/main/native/cpp/SPI.cpp
index bdcee45..29cd006 100644
--- a/wpilibc/src/main/native/cpp/SPI.cpp
+++ b/wpilibc/src/main/native/cpp/SPI.cpp
@@ -25,7 +25,7 @@
public:
Accumulator(HAL_SPIPort port, int xferSize, int validMask, int validValue,
int dataShift, int dataSize, bool isSigned, bool bigEndian)
- : m_notifier([=] {
+ : m_notifier([=, this] {
std::scoped_lock lock(m_mutex);
Update();
}),
@@ -77,7 +77,7 @@
// get amount of data available
int32_t numToRead =
HAL_ReadSPIAutoReceivedData(m_port, m_buf, 0, 0, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
// only get whole responses; +1 is for timestamp
numToRead -= numToRead % m_xferSize;
@@ -91,7 +91,7 @@
// read buffered data
HAL_ReadSPIAutoReceivedData(m_port, m_buf, numToRead, 0, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
// loop over all responses
for (int32_t off = 0; off < numToRead; off += m_xferSize) {
@@ -158,7 +158,8 @@
SPI::SPI(Port port) : m_port(static_cast<HAL_SPIPort>(port)) {
int32_t status = 0;
HAL_InitializeSPI(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ HAL_SetSPIMode(m_port, m_mode);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
HAL_Report(HALUsageReporting::kResourceType_SPI,
static_cast<uint8_t>(port) + 1);
@@ -177,55 +178,58 @@
}
void SPI::SetMSBFirst() {
- m_msbFirst = true;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ FRC_ReportError(1, "SetMSBFirst not supported by roboRIO {}",
+ static_cast<int>(m_port));
}
void SPI::SetLSBFirst() {
- m_msbFirst = false;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ FRC_ReportError(1, "SetLSBFirst not supported by roboRIO {}",
+ static_cast<int>(m_port));
}
void SPI::SetSampleDataOnLeadingEdge() {
- m_sampleOnTrailing = false;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ int mode = m_mode;
+ mode &= 2;
+ m_mode = static_cast<HAL_SPIMode>(mode);
+ HAL_SetSPIMode(m_port, m_mode);
}
void SPI::SetSampleDataOnTrailingEdge() {
- m_sampleOnTrailing = true;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
-}
-
-void SPI::SetSampleDataOnFalling() {
- m_sampleOnTrailing = true;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
-}
-
-void SPI::SetSampleDataOnRising() {
- m_sampleOnTrailing = false;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ int mode = m_mode;
+ mode |= 2;
+ m_mode = static_cast<HAL_SPIMode>(mode);
+ HAL_SetSPIMode(m_port, m_mode);
}
void SPI::SetClockActiveLow() {
- m_clockIdleHigh = true;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ int mode = m_mode;
+ mode |= 1;
+ m_mode = static_cast<HAL_SPIMode>(mode);
+ HAL_SetSPIMode(m_port, m_mode);
}
void SPI::SetClockActiveHigh() {
- m_clockIdleHigh = false;
- HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+ int mode = m_mode;
+ mode &= 1;
+ m_mode = static_cast<HAL_SPIMode>(mode);
+ HAL_SetSPIMode(m_port, m_mode);
+}
+
+void SPI::SetMode(Mode mode) {
+ m_mode = static_cast<HAL_SPIMode>(mode & 0x3);
+ HAL_SetSPIMode(m_port, m_mode);
}
void SPI::SetChipSelectActiveHigh() {
int32_t status = 0;
HAL_SetSPIChipSelectActiveHigh(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::SetChipSelectActiveLow() {
int32_t status = 0;
HAL_SetSPIChipSelectActiveLow(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
int SPI::Write(uint8_t* data, int size) {
@@ -255,31 +259,27 @@
void SPI::InitAuto(int bufferSize) {
int32_t status = 0;
HAL_InitSPIAuto(m_port, bufferSize, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::FreeAuto() {
int32_t status = 0;
HAL_FreeSPIAuto(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
-void SPI::SetAutoTransmitData(wpi::span<const uint8_t> dataToSend,
+void SPI::SetAutoTransmitData(std::span<const uint8_t> dataToSend,
int zeroSize) {
int32_t status = 0;
HAL_SetSPIAutoTransmitData(m_port, dataToSend.data(), dataToSend.size(),
zeroSize, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::StartAutoRate(units::second_t period) {
int32_t status = 0;
HAL_StartSPIAutoRate(m_port, period.value(), &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
-}
-
-void SPI::StartAutoRate(double period) {
- StartAutoRate(units::second_t(period));
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::StartAutoTrigger(DigitalSource& source, bool rising, bool falling) {
@@ -288,19 +288,19 @@
static_cast<HAL_AnalogTriggerType>(
source.GetAnalogTriggerTypeForRouting()),
rising, falling, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::StopAuto() {
int32_t status = 0;
HAL_StopSPIAuto(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::ForceAutoRead() {
int32_t status = 0;
HAL_ForceSPIAutoRead(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
int SPI::ReadAutoReceivedData(uint32_t* buffer, int numToRead,
@@ -308,14 +308,14 @@
int32_t status = 0;
int32_t val = HAL_ReadSPIAutoReceivedData(m_port, buffer, numToRead,
timeout.value(), &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
return val;
}
int SPI::GetAutoDroppedCount() {
int32_t status = 0;
int32_t val = HAL_GetSPIAutoDroppedCount(m_port, &status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
return val;
}
@@ -324,7 +324,7 @@
int32_t status = 0;
HAL_ConfigureSPIAutoStall(m_port, csToSclkTicks, stallTicks, pow2BytesPerRead,
&status);
- FRC_CheckErrorStatus(status, "Port {}", m_port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(m_port));
}
void SPI::InitAccumulator(units::second_t period, int cmd, int xferSize,
@@ -355,13 +355,6 @@
m_accum->m_notifier.StartPeriodic(period * kAccumulateDepth / 2);
}
-void SPI::InitAccumulator(double period, int cmd, int xferSize, int validMask,
- int validValue, int dataShift, int dataSize,
- bool isSigned, bool bigEndian) {
- InitAccumulator(units::second_t(period), cmd, xferSize, validMask, validValue,
- dataShift, dataSize, isSigned, bigEndian);
-}
-
void SPI::FreeAccumulator() {
m_accum.reset(nullptr);
FreeAuto();
diff --git a/wpilibc/src/main/native/cpp/SerialPort.cpp b/wpilibc/src/main/native/cpp/SerialPort.cpp
index fb984f1..698a440 100644
--- a/wpilibc/src/main/native/cpp/SerialPort.cpp
+++ b/wpilibc/src/main/native/cpp/SerialPort.cpp
@@ -20,15 +20,16 @@
m_portHandle =
HAL_InitializeSerialPort(static_cast<HAL_SerialPort>(port), &status);
- FRC_CheckErrorStatus(status, "Port {}", port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(port));
HAL_SetSerialBaudRate(m_portHandle, baudRate, &status);
FRC_CheckErrorStatus(status, "SetSerialBaudRate {}", baudRate);
HAL_SetSerialDataBits(m_portHandle, dataBits, &status);
FRC_CheckErrorStatus(status, "SetSerialDataBits {}", dataBits);
HAL_SetSerialParity(m_portHandle, parity, &status);
- FRC_CheckErrorStatus(status, "SetSerialParity {}", parity);
+ FRC_CheckErrorStatus(status, "SetSerialParity {}", static_cast<int>(parity));
HAL_SetSerialStopBits(m_portHandle, stopBits, &status);
- FRC_CheckErrorStatus(status, "SetSerialStopBits {}", stopBits);
+ FRC_CheckErrorStatus(status, "SetSerialStopBits {}",
+ static_cast<int>(stopBits));
// Set the default timeout to 5 seconds.
SetTimeout(5_s);
@@ -50,15 +51,16 @@
m_portHandle =
HAL_InitializeSerialPortDirect(static_cast<HAL_SerialPort>(port),
std::string(portName).c_str(), &status);
- FRC_CheckErrorStatus(status, "Port {}", port);
+ FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(port));
HAL_SetSerialBaudRate(m_portHandle, baudRate, &status);
FRC_CheckErrorStatus(status, "SetSerialBaudRate {}", baudRate);
HAL_SetSerialDataBits(m_portHandle, dataBits, &status);
FRC_CheckErrorStatus(status, "SetSerialDataBits {}", dataBits);
HAL_SetSerialParity(m_portHandle, parity, &status);
- FRC_CheckErrorStatus(status, "SetSerialParity {}", parity);
+ FRC_CheckErrorStatus(status, "SetSerialParity {}", static_cast<int>(parity));
HAL_SetSerialStopBits(m_portHandle, stopBits, &status);
- FRC_CheckErrorStatus(status, "SetSerialStopBits {}", stopBits);
+ FRC_CheckErrorStatus(status, "SetSerialStopBits {}",
+ static_cast<int>(stopBits));
// Set the default timeout to 5 seconds.
SetTimeout(5_s);
@@ -75,13 +77,14 @@
SerialPort::~SerialPort() {
int32_t status = 0;
HAL_CloseSerial(m_portHandle, &status);
- FRC_ReportError(status, "{}", "CloseSerial");
+ FRC_ReportError(status, "CloseSerial");
}
void SerialPort::SetFlowControl(SerialPort::FlowControl flowControl) {
int32_t status = 0;
HAL_SetSerialFlowControl(m_portHandle, flowControl, &status);
- FRC_CheckErrorStatus(status, "SetFlowControl {}", flowControl);
+ FRC_CheckErrorStatus(status, "SetFlowControl {}",
+ static_cast<int>(flowControl));
}
void SerialPort::EnableTermination(char terminator) {
@@ -93,20 +96,20 @@
void SerialPort::DisableTermination() {
int32_t status = 0;
HAL_DisableSerialTermination(m_portHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "DisableTermination");
+ FRC_CheckErrorStatus(status, "DisableTermination");
}
int SerialPort::GetBytesReceived() {
int32_t status = 0;
int retVal = HAL_GetSerialBytesReceived(m_portHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "GetBytesReceived");
+ FRC_CheckErrorStatus(status, "GetBytesReceived");
return retVal;
}
int SerialPort::Read(char* buffer, int count) {
int32_t status = 0;
int retVal = HAL_ReadSerial(m_portHandle, buffer, count, &status);
- FRC_CheckErrorStatus(status, "{}", "Read");
+ FRC_CheckErrorStatus(status, "Read");
return retVal;
}
@@ -118,14 +121,14 @@
int32_t status = 0;
int retVal =
HAL_WriteSerial(m_portHandle, buffer.data(), buffer.size(), &status);
- FRC_CheckErrorStatus(status, "{}", "Write");
+ FRC_CheckErrorStatus(status, "Write");
return retVal;
}
void SerialPort::SetTimeout(units::second_t timeout) {
int32_t status = 0;
HAL_SetSerialTimeout(m_portHandle, timeout.value(), &status);
- FRC_CheckErrorStatus(status, "{}", "SetTimeout");
+ FRC_CheckErrorStatus(status, "SetTimeout");
}
void SerialPort::SetReadBufferSize(int size) {
@@ -143,17 +146,17 @@
void SerialPort::SetWriteBufferMode(SerialPort::WriteBufferMode mode) {
int32_t status = 0;
HAL_SetSerialWriteMode(m_portHandle, mode, &status);
- FRC_CheckErrorStatus(status, "SetWriteBufferMode {}", mode);
+ FRC_CheckErrorStatus(status, "SetWriteBufferMode {}", static_cast<int>(mode));
}
void SerialPort::Flush() {
int32_t status = 0;
HAL_FlushSerial(m_portHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "Flush");
+ FRC_CheckErrorStatus(status, "Flush");
}
void SerialPort::Reset() {
int32_t status = 0;
HAL_ClearSerial(m_portHandle, &status);
- FRC_CheckErrorStatus(status, "{}", "Reset");
+ FRC_CheckErrorStatus(status, "Reset");
}
diff --git a/wpilibc/src/main/native/cpp/Servo.cpp b/wpilibc/src/main/native/cpp/Servo.cpp
index c410bff..4a292b9 100644
--- a/wpilibc/src/main/native/cpp/Servo.cpp
+++ b/wpilibc/src/main/native/cpp/Servo.cpp
@@ -64,7 +64,8 @@
void Servo::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Servo");
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, [=](double value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](double value) { Set(value); });
}
double Servo::GetServoAngleRange() const {
diff --git a/wpilibc/src/main/native/cpp/Solenoid.cpp b/wpilibc/src/main/native/cpp/Solenoid.cpp
index 49000c2..819f79a 100644
--- a/wpilibc/src/main/native/cpp/Solenoid.cpp
+++ b/wpilibc/src/main/native/cpp/Solenoid.cpp
@@ -39,7 +39,9 @@
channel} {}
Solenoid::~Solenoid() {
- m_module->UnreserveSolenoids(m_mask);
+ if (m_module) {
+ m_module->UnreserveSolenoids(m_mask);
+ }
}
void Solenoid::Set(bool on) {
@@ -75,7 +77,8 @@
void Solenoid::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Solenoid");
builder.SetActuator(true);
- builder.SetSafeState([=] { Set(false); });
+ builder.SetSafeState([=, this] { Set(false); });
builder.AddBooleanProperty(
- "Value", [=] { return Get(); }, [=](bool value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](bool value) { Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp b/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp
deleted file mode 100644
index c3704df..0000000
--- a/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "frc/SpeedControllerGroup.h"
-
-#include <wpi/sendable/SendableBuilder.h>
-#include <wpi/sendable/SendableRegistry.h>
-
-using namespace frc;
-
-// Can't use a delegated constructor here because of an MSVC bug.
-// https://developercommunity.visualstudio.com/content/problem/583/compiler-bug-with-delegating-a-constructor.html
-
-SpeedControllerGroup::SpeedControllerGroup(
- std::vector<std::reference_wrapper<SpeedController>>&& speedControllers)
- : m_speedControllers(std::move(speedControllers)) {
- Initialize();
-}
-
-void SpeedControllerGroup::Initialize() {
- for (auto& speedController : m_speedControllers) {
- wpi::SendableRegistry::AddChild(this, &speedController.get());
- }
- static int instances = 0;
- ++instances;
- wpi::SendableRegistry::Add(this, "SpeedControllerGroup", instances);
-}
-
-void SpeedControllerGroup::Set(double speed) {
- for (auto speedController : m_speedControllers) {
- speedController.get().Set(m_isInverted ? -speed : speed);
- }
-}
-
-double SpeedControllerGroup::Get() const {
- if (!m_speedControllers.empty()) {
- return m_speedControllers.front().get().Get() * (m_isInverted ? -1 : 1);
- }
- return 0.0;
-}
-
-void SpeedControllerGroup::SetInverted(bool isInverted) {
- m_isInverted = isInverted;
-}
-
-bool SpeedControllerGroup::GetInverted() const {
- return m_isInverted;
-}
-
-void SpeedControllerGroup::Disable() {
- for (auto speedController : m_speedControllers) {
- speedController.get().Disable();
- }
-}
-
-void SpeedControllerGroup::StopMotor() {
- for (auto speedController : m_speedControllers) {
- speedController.get().StopMotor();
- }
-}
-
-void SpeedControllerGroup::InitSendable(wpi::SendableBuilder& builder) {
- builder.SetSmartDashboardType("Speed Controller");
- builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
- builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, [=](double value) { Set(value); });
-}
diff --git a/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp b/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp
index 49acd84..a6ab212 100644
--- a/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp
+++ b/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp
@@ -21,7 +21,7 @@
SynchronousInterrupt::SynchronousInterrupt(DigitalSource* source)
: m_source{source, wpi::NullDeleter<DigitalSource>()} {
if (m_source == nullptr) {
- FRC_CheckErrorStatus(frc::err::NullParameter, "{}", "Source is null");
+ FRC_CheckErrorStatus(frc::err::NullParameter, "Source is null");
} else {
InitSynchronousInterrupt();
}
@@ -30,7 +30,7 @@
std::shared_ptr<DigitalSource> source)
: m_source{std::move(source)} {
if (m_source == nullptr) {
- FRC_CheckErrorStatus(frc::err::NullParameter, "{}", "Source is null");
+ FRC_CheckErrorStatus(frc::err::NullParameter, "Source is null");
} else {
InitSynchronousInterrupt();
}
@@ -39,14 +39,14 @@
void SynchronousInterrupt::InitSynchronousInterrupt() {
int32_t status = 0;
m_handle = HAL_InitializeInterrupts(&status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt failed to initialize");
+ FRC_CheckErrorStatus(status, "Interrupt failed to initialize");
HAL_RequestInterrupts(m_handle, m_source->GetPortHandleForRouting(),
static_cast<HAL_AnalogTriggerType>(
m_source->GetAnalogTriggerTypeForRouting()),
&status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt request failed");
+ FRC_CheckErrorStatus(status, "Interrupt request failed");
HAL_SetInterruptUpSourceEdge(m_handle, true, false, &status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt setting up source edge failed");
+ FRC_CheckErrorStatus(status, "Interrupt setting up source edge failed");
}
SynchronousInterrupt::~SynchronousInterrupt() {
@@ -79,19 +79,19 @@
bool fallingEdge) {
int32_t status = 0;
HAL_SetInterruptUpSourceEdge(m_handle, risingEdge, fallingEdge, &status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt setting edges failed");
+ FRC_CheckErrorStatus(status, "Interrupt setting edges failed");
}
void SynchronousInterrupt::WakeupWaitingInterrupt() {
int32_t status = 0;
HAL_ReleaseWaitingInterrupt(m_handle, &status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt wakeup failed");
+ FRC_CheckErrorStatus(status, "Interrupt wakeup failed");
}
units::second_t SynchronousInterrupt::GetRisingTimestamp() {
int32_t status = 0;
auto ts = HAL_ReadInterruptRisingTimestamp(m_handle, &status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt rising timestamp failed");
+ FRC_CheckErrorStatus(status, "Interrupt rising timestamp failed");
units::microsecond_t ms{static_cast<double>(ts)};
return ms;
}
@@ -99,7 +99,7 @@
units::second_t SynchronousInterrupt::GetFallingTimestamp() {
int32_t status = 0;
auto ts = HAL_ReadInterruptFallingTimestamp(m_handle, &status);
- FRC_CheckErrorStatus(status, "{}", "Interrupt falling timestamp failed");
+ FRC_CheckErrorStatus(status, "Interrupt falling timestamp failed");
units::microsecond_t ms{static_cast<double>(ts)};
return ms;
}
diff --git a/wpilibc/src/main/native/cpp/Threads.cpp b/wpilibc/src/main/native/cpp/Threads.cpp
index 2b9c151..3ecab55 100644
--- a/wpilibc/src/main/native/cpp/Threads.cpp
+++ b/wpilibc/src/main/native/cpp/Threads.cpp
@@ -16,7 +16,7 @@
HAL_Bool rt = false;
auto native = thread.native_handle();
auto ret = HAL_GetThreadPriority(&native, &rt, &status);
- FRC_CheckErrorStatus(status, "{}", "GetThreadPriority");
+ FRC_CheckErrorStatus(status, "GetThreadPriority");
*isRealTime = rt;
return ret;
}
@@ -25,7 +25,7 @@
int32_t status = 0;
HAL_Bool rt = false;
auto ret = HAL_GetCurrentThreadPriority(&rt, &status);
- FRC_CheckErrorStatus(status, "{}", "GetCurrentThreadPriority");
+ FRC_CheckErrorStatus(status, "GetCurrentThreadPriority");
*isRealTime = rt;
return ret;
}
@@ -34,14 +34,14 @@
int32_t status = 0;
auto native = thread.native_handle();
auto ret = HAL_SetThreadPriority(&native, realTime, priority, &status);
- FRC_CheckErrorStatus(status, "{}", "SetThreadPriority");
+ FRC_CheckErrorStatus(status, "SetThreadPriority");
return ret;
}
bool SetCurrentThreadPriority(bool realTime, int priority) {
int32_t status = 0;
auto ret = HAL_SetCurrentThreadPriority(realTime, priority, &status);
- FRC_CheckErrorStatus(status, "{}", "SetCurrentThreadPriority");
+ FRC_CheckErrorStatus(status, "SetCurrentThreadPriority");
return ret;
}
diff --git a/wpilibc/src/main/native/cpp/TimedRobot.cpp b/wpilibc/src/main/native/cpp/TimedRobot.cpp
index 93e6698..0b7b9cb 100644
--- a/wpilibc/src/main/native/cpp/TimedRobot.cpp
+++ b/wpilibc/src/main/native/cpp/TimedRobot.cpp
@@ -40,7 +40,7 @@
HAL_UpdateNotifierAlarm(
m_notifier, static_cast<uint64_t>(callback.expirationTime * 1e6),
&status);
- FRC_CheckErrorStatus(status, "{}", "UpdateNotifierAlarm");
+ FRC_CheckErrorStatus(status, "UpdateNotifierAlarm");
uint64_t curTime = HAL_WaitForNotifierAlarm(m_notifier, &status);
if (curTime == 0 || status != 0) {
@@ -70,15 +70,13 @@
HAL_StopNotifier(m_notifier, &status);
}
-TimedRobot::TimedRobot(double period) : TimedRobot(units::second_t(period)) {}
-
TimedRobot::TimedRobot(units::second_t period) : IterativeRobotBase(period) {
m_startTime = Timer::GetFPGATimestamp();
- AddPeriodic([=] { LoopFunc(); }, period);
+ AddPeriodic([=, this] { LoopFunc(); }, period);
int32_t status = 0;
m_notifier = HAL_InitializeNotifier(&status);
- FRC_CheckErrorStatus(status, "{}", "InitializeNotifier");
+ FRC_CheckErrorStatus(status, "InitializeNotifier");
HAL_SetNotifierName(m_notifier, "TimedRobot", &status);
HAL_Report(HALUsageReporting::kResourceType_Framework,
@@ -89,7 +87,7 @@
int32_t status = 0;
HAL_StopNotifier(m_notifier, &status);
- FRC_ReportError(status, "{}", "StopNotifier");
+ FRC_ReportError(status, "StopNotifier");
HAL_CleanNotifier(m_notifier, &status);
}
diff --git a/wpilibc/src/main/native/cpp/Timer.cpp b/wpilibc/src/main/native/cpp/Timer.cpp
index bbd2262..3863de4 100644
--- a/wpilibc/src/main/native/cpp/Timer.cpp
+++ b/wpilibc/src/main/native/cpp/Timer.cpp
@@ -21,9 +21,9 @@
using std::chrono::duration_cast;
using std::chrono::system_clock;
- return units::second_t(
+ return units::second_t{
duration_cast<duration<double>>(system_clock::now().time_since_epoch())
- .count());
+ .count()};
}
} // namespace frc
@@ -65,10 +65,6 @@
return Get() >= period;
}
-bool Timer::HasPeriodPassed(units::second_t period) {
- return AdvanceIfElapsed(period);
-}
-
bool Timer::AdvanceIfElapsed(units::second_t period) {
if (Get() >= period) {
// Advance the start time by the period.
@@ -82,9 +78,9 @@
units::second_t Timer::GetFPGATimestamp() {
// FPGA returns the timestamp in microseconds
- return units::second_t(frc::RobotController::GetFPGATime() * 1.0e-6);
+ return units::second_t{frc::RobotController::GetFPGATime() * 1.0e-6};
}
units::second_t Timer::GetMatchTime() {
- return units::second_t(frc::DriverStation::GetMatchTime());
+ return units::second_t{frc::DriverStation::GetMatchTime()};
}
diff --git a/wpilibc/src/main/native/cpp/Ultrasonic.cpp b/wpilibc/src/main/native/cpp/Ultrasonic.cpp
index 02035dd..a034fc3 100644
--- a/wpilibc/src/main/native/cpp/Ultrasonic.cpp
+++ b/wpilibc/src/main/native/cpp/Ultrasonic.cpp
@@ -39,10 +39,10 @@
m_echoChannel(echoChannel, wpi::NullDeleter<DigitalInput>()),
m_counter(m_echoChannel) {
if (!pingChannel) {
- throw FRC_MakeError(err::NullParameter, "{}", "pingChannel");
+ throw FRC_MakeError(err::NullParameter, "pingChannel");
}
if (!echoChannel) {
- throw FRC_MakeError(err::NullParameter, "{}", "echoChannel");
+ throw FRC_MakeError(err::NullParameter, "echoChannel");
}
Initialize();
}
@@ -86,7 +86,7 @@
void Ultrasonic::Ping() {
if (m_automaticEnabled) {
- throw FRC_MakeError(err::IncompatibleMode, "{}",
+ throw FRC_MakeError(err::IncompatibleMode,
"cannot call Ping() in automatic mode");
}
@@ -120,11 +120,6 @@
}
m_thread = std::thread(&Ultrasonic::UltrasonicChecker);
-
- // TODO: Currently, lvuser does not have permissions to set task priorities.
- // Until that is the case, uncommenting this will break user code that calls
- // Ultrasonic::SetAutomicMode().
- // m_task.SetPriority(kPriority);
} else {
// Wait for background task to stop running
if (m_thread.joinable()) {
@@ -162,7 +157,8 @@
void Ultrasonic::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Ultrasonic");
builder.AddDoubleProperty(
- "Value", [=] { return units::inch_t{GetRange()}.value(); }, nullptr);
+ "Value", [=, this] { return units::inch_t{GetRange()}.value(); },
+ nullptr);
}
void Ultrasonic::Initialize() {
diff --git a/wpilibc/src/main/native/cpp/Watchdog.cpp b/wpilibc/src/main/native/cpp/Watchdog.cpp
index 854f9e9..37e2536 100644
--- a/wpilibc/src/main/native/cpp/Watchdog.cpp
+++ b/wpilibc/src/main/native/cpp/Watchdog.cpp
@@ -47,10 +47,10 @@
Watchdog::Impl::Impl() {
int32_t status = 0;
m_notifier = HAL_InitializeNotifier(&status);
- FRC_CheckErrorStatus(status, "{}", "starting watchdog notifier");
+ FRC_CheckErrorStatus(status, "starting watchdog notifier");
HAL_SetNotifierName(m_notifier, "Watchdog", &status);
- m_thread = std::thread([=] { Main(); });
+ m_thread = std::thread([=, this] { Main(); });
}
Watchdog::Impl::~Impl() {
@@ -58,7 +58,7 @@
// atomically set handle to 0, then clean
HAL_NotifierHandle handle = m_notifier.exchange(0);
HAL_StopNotifier(handle, &status);
- FRC_ReportError(status, "{}", "stopping watchdog notifier");
+ FRC_ReportError(status, "stopping watchdog notifier");
// Join the thread to ensure the handler has exited.
if (m_thread.joinable()) {
@@ -84,7 +84,7 @@
1e6),
&status);
}
- FRC_CheckErrorStatus(status, "{}", "updating watchdog notifier alarm");
+ FRC_CheckErrorStatus(status, "updating watchdog notifier alarm");
}
void Watchdog::Impl::Main() {
diff --git a/wpilibc/src/main/native/cpp/XboxController.cpp b/wpilibc/src/main/native/cpp/XboxController.cpp
index a08225b..f10419f 100644
--- a/wpilibc/src/main/native/cpp/XboxController.cpp
+++ b/wpilibc/src/main/native/cpp/XboxController.cpp
@@ -6,6 +6,8 @@
#include <hal/FRCUsageReporting.h>
+#include "frc/event/BooleanEvent.h"
+
using namespace frc;
XboxController::XboxController(int port) : GenericHID(port) {
@@ -60,6 +62,14 @@
return GetRawButtonReleased(Button::kRightBumper);
}
+BooleanEvent XboxController::LeftBumper(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetLeftBumper(); });
+}
+
+BooleanEvent XboxController::RightBumper(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetRightBumper(); });
+}
+
bool XboxController::GetLeftStickButton() const {
return GetRawButton(Button::kLeftStick);
}
@@ -84,6 +94,14 @@
return GetRawButtonReleased(Button::kRightStick);
}
+BooleanEvent XboxController::LeftStick(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetLeftStickButton(); });
+}
+
+BooleanEvent XboxController::RightStick(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetRightStickButton(); });
+}
+
bool XboxController::GetAButton() const {
return GetRawButton(Button::kA);
}
@@ -96,6 +114,10 @@
return GetRawButtonReleased(Button::kA);
}
+BooleanEvent XboxController::A(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetAButton(); });
+}
+
bool XboxController::GetBButton() const {
return GetRawButton(Button::kB);
}
@@ -108,6 +130,10 @@
return GetRawButtonReleased(Button::kB);
}
+BooleanEvent XboxController::B(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetBButton(); });
+}
+
bool XboxController::GetXButton() const {
return GetRawButton(Button::kX);
}
@@ -120,6 +146,10 @@
return GetRawButtonReleased(Button::kX);
}
+BooleanEvent XboxController::X(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetXButton(); });
+}
+
bool XboxController::GetYButton() const {
return GetRawButton(Button::kY);
}
@@ -132,6 +162,10 @@
return GetRawButtonReleased(Button::kY);
}
+BooleanEvent XboxController::Y(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetYButton(); });
+}
+
bool XboxController::GetBackButton() const {
return GetRawButton(Button::kBack);
}
@@ -144,6 +178,10 @@
return GetRawButtonReleased(Button::kBack);
}
+BooleanEvent XboxController::Back(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetBackButton(); });
+}
+
bool XboxController::GetStartButton() const {
return GetRawButton(Button::kStart);
}
@@ -155,3 +193,29 @@
bool XboxController::GetStartButtonReleased() {
return GetRawButtonReleased(Button::kStart);
}
+
+BooleanEvent XboxController::Start(EventLoop* loop) const {
+ return BooleanEvent(loop, [this]() { return this->GetStartButton(); });
+}
+
+BooleanEvent XboxController::LeftTrigger(double threshold,
+ EventLoop* loop) const {
+ return BooleanEvent(loop, [this, threshold]() {
+ return this->GetLeftTriggerAxis() > threshold;
+ });
+}
+
+BooleanEvent XboxController::LeftTrigger(EventLoop* loop) const {
+ return this->LeftTrigger(0.5, loop);
+}
+
+BooleanEvent XboxController::RightTrigger(double threshold,
+ EventLoop* loop) const {
+ return BooleanEvent(loop, [this, threshold]() {
+ return this->GetRightTriggerAxis() > threshold;
+ });
+}
+
+BooleanEvent XboxController::RightTrigger(EventLoop* loop) const {
+ return this->RightTrigger(0.5, loop);
+}
diff --git a/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp b/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp
index 8c7bb58..24709aa 100644
--- a/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp
+++ b/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp
@@ -24,10 +24,10 @@
std::shared_ptr<DigitalSource> countSource,
std::shared_ptr<DigitalSource> directionSource) {
if (countSource == nullptr) {
- throw FRC_MakeError(err::NullParameter, "{}", "countSource");
+ throw FRC_MakeError(err::NullParameter, "countSource");
}
if (directionSource == nullptr) {
- throw FRC_MakeError(err::NullParameter, "{}", "directionSource");
+ throw FRC_MakeError(err::NullParameter, "directionSource");
}
m_countSource = countSource;
diff --git a/wpilibc/src/main/native/cpp/counter/Tachometer.cpp b/wpilibc/src/main/native/cpp/counter/Tachometer.cpp
index a52bea5..90324f5 100644
--- a/wpilibc/src/main/native/cpp/counter/Tachometer.cpp
+++ b/wpilibc/src/main/native/cpp/counter/Tachometer.cpp
@@ -19,7 +19,7 @@
: Tachometer({&source, wpi::NullDeleter<DigitalSource>()}) {}
Tachometer::Tachometer(std::shared_ptr<DigitalSource> source) {
if (source == nullptr) {
- throw FRC_MakeError(err::NullParameter, "{}", "source");
+ throw FRC_MakeError(err::NullParameter, "source");
}
m_source = source;
diff --git a/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp
index eed9495..8cce62e 100644
--- a/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp
+++ b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp
@@ -12,20 +12,12 @@
#include <wpi/sendable/SendableRegistry.h>
#include "frc/MathUtil.h"
-#include "frc/SpeedController.h"
+#include "frc/motorcontrol/MotorController.h"
using namespace frc;
-#if defined(_MSC_VER)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-DifferentialDrive::DifferentialDrive(SpeedController& leftMotor,
- SpeedController& rightMotor)
+DifferentialDrive::DifferentialDrive(MotorController& leftMotor,
+ MotorController& rightMotor)
: m_leftMotor(&leftMotor), m_rightMotor(&rightMotor) {
wpi::SendableRegistry::AddChild(this, m_leftMotor);
wpi::SendableRegistry::AddChild(this, m_rightMotor);
@@ -106,39 +98,19 @@
zRotation = std::copysign(zRotation * zRotation, zRotation);
}
- double leftSpeed;
- double rightSpeed;
+ double leftSpeed = xSpeed - zRotation;
+ double rightSpeed = xSpeed + zRotation;
- double maxInput =
- std::copysign(std::max(std::abs(xSpeed), std::abs(zRotation)), xSpeed);
-
- // Sign is used because `xSpeed >= 0.0` succeeds for -0.0
- if (!std::signbit(xSpeed)) {
- // First quadrant, else second quadrant
- if (!std::signbit(zRotation)) {
- leftSpeed = maxInput;
- rightSpeed = xSpeed - zRotation;
- } else {
- leftSpeed = xSpeed + zRotation;
- rightSpeed = maxInput;
- }
- } else {
- // Third quadrant, else fourth quadrant
- if (!std::signbit(zRotation)) {
- leftSpeed = xSpeed + zRotation;
- rightSpeed = maxInput;
- } else {
- leftSpeed = maxInput;
- rightSpeed = xSpeed - zRotation;
- }
+ // Find the maximum possible value of (throttle + turn) along the vector that
+ // the joystick is pointing, then desaturate the wheel speeds
+ double greaterInput = (std::max)(std::abs(xSpeed), std::abs(zRotation));
+ double lesserInput = (std::min)(std::abs(xSpeed), std::abs(zRotation));
+ if (greaterInput == 0.0) {
+ return {0.0, 0.0};
}
-
- // Normalize the wheel speeds
- double maxMagnitude = std::max(std::abs(leftSpeed), std::abs(rightSpeed));
- if (maxMagnitude > 1.0) {
- leftSpeed /= maxMagnitude;
- rightSpeed /= maxMagnitude;
- }
+ double saturatedInput = (greaterInput + lesserInput) / greaterInput;
+ leftSpeed /= saturatedInput;
+ rightSpeed /= saturatedInput;
return {leftSpeed, rightSpeed};
}
@@ -152,14 +124,14 @@
double rightSpeed = 0.0;
if (allowTurnInPlace) {
- leftSpeed = xSpeed + zRotation;
- rightSpeed = xSpeed - zRotation;
+ leftSpeed = xSpeed - zRotation;
+ rightSpeed = xSpeed + zRotation;
} else {
- leftSpeed = xSpeed + std::abs(xSpeed) * zRotation;
- rightSpeed = xSpeed - std::abs(xSpeed) * zRotation;
+ leftSpeed = xSpeed - std::abs(xSpeed) * zRotation;
+ rightSpeed = xSpeed + std::abs(xSpeed) * zRotation;
}
- // Normalize wheel speeds
+ // Desaturate wheel speeds
double maxMagnitude = std::max(std::abs(leftSpeed), std::abs(rightSpeed));
if (maxMagnitude > 1.0) {
leftSpeed /= maxMagnitude;
@@ -197,11 +169,11 @@
void DifferentialDrive::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("DifferentialDrive");
builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
+ builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
- "Left Motor Speed", [=] { return m_leftMotor->Get(); },
- [=](double value) { m_leftMotor->Set(value); });
+ "Left Motor Speed", [=, this] { return m_leftMotor->Get(); },
+ [=, this](double value) { m_leftMotor->Set(value); });
builder.AddDoubleProperty(
- "Right Motor Speed", [=] { return m_rightMotor->Get(); },
- [=](double value) { m_rightMotor->Set(value); });
+ "Right Motor Speed", [=, this] { return m_rightMotor->Get(); },
+ [=, this](double value) { m_rightMotor->Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp b/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp
deleted file mode 100644
index 268ae64..0000000
--- a/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "frc/drive/KilloughDrive.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include <hal/FRCUsageReporting.h>
-#include <wpi/numbers>
-#include <wpi/sendable/SendableBuilder.h>
-#include <wpi/sendable/SendableRegistry.h>
-
-#include "frc/MathUtil.h"
-#include "frc/SpeedController.h"
-
-using namespace frc;
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-KilloughDrive::KilloughDrive(SpeedController& leftMotor,
- SpeedController& rightMotor,
- SpeedController& backMotor)
- : KilloughDrive(leftMotor, rightMotor, backMotor, kDefaultLeftMotorAngle,
- kDefaultRightMotorAngle, kDefaultBackMotorAngle) {}
-
-KilloughDrive::KilloughDrive(SpeedController& leftMotor,
- SpeedController& rightMotor,
- SpeedController& backMotor, double leftMotorAngle,
- double rightMotorAngle, double backMotorAngle)
- : m_leftMotor(&leftMotor),
- m_rightMotor(&rightMotor),
- m_backMotor(&backMotor) {
- m_leftVec = {std::cos(leftMotorAngle * (wpi::numbers::pi / 180.0)),
- std::sin(leftMotorAngle * (wpi::numbers::pi / 180.0))};
- m_rightVec = {std::cos(rightMotorAngle * (wpi::numbers::pi / 180.0)),
- std::sin(rightMotorAngle * (wpi::numbers::pi / 180.0))};
- m_backVec = {std::cos(backMotorAngle * (wpi::numbers::pi / 180.0)),
- std::sin(backMotorAngle * (wpi::numbers::pi / 180.0))};
- wpi::SendableRegistry::AddChild(this, m_leftMotor);
- wpi::SendableRegistry::AddChild(this, m_rightMotor);
- wpi::SendableRegistry::AddChild(this, m_backMotor);
- static int instances = 0;
- ++instances;
- wpi::SendableRegistry::AddLW(this, "KilloughDrive", instances);
-}
-
-void KilloughDrive::DriveCartesian(double ySpeed, double xSpeed,
- double zRotation, double gyroAngle) {
- if (!reported) {
- HAL_Report(HALUsageReporting::kResourceType_RobotDrive,
- HALUsageReporting::kRobotDrive2_KilloughCartesian, 3);
- reported = true;
- }
-
- ySpeed = ApplyDeadband(ySpeed, m_deadband);
- xSpeed = ApplyDeadband(xSpeed, m_deadband);
-
- auto [left, right, back] =
- DriveCartesianIK(ySpeed, xSpeed, zRotation, gyroAngle);
-
- m_leftMotor->Set(left * m_maxOutput);
- m_rightMotor->Set(right * m_maxOutput);
- m_backMotor->Set(back * m_maxOutput);
-
- Feed();
-}
-
-void KilloughDrive::DrivePolar(double magnitude, double angle,
- double zRotation) {
- if (!reported) {
- HAL_Report(HALUsageReporting::kResourceType_RobotDrive,
- HALUsageReporting::kRobotDrive2_KilloughPolar, 3);
- reported = true;
- }
-
- DriveCartesian(magnitude * std::sin(angle * (wpi::numbers::pi / 180.0)),
- magnitude * std::cos(angle * (wpi::numbers::pi / 180.0)),
- zRotation, 0.0);
-}
-
-KilloughDrive::WheelSpeeds KilloughDrive::DriveCartesianIK(double ySpeed,
- double xSpeed,
- double zRotation,
- double gyroAngle) {
- ySpeed = std::clamp(ySpeed, -1.0, 1.0);
- xSpeed = std::clamp(xSpeed, -1.0, 1.0);
-
- // Compensate for gyro angle.
- Vector2d input{ySpeed, xSpeed};
- input.Rotate(-gyroAngle);
-
- double wheelSpeeds[3];
- wheelSpeeds[kLeft] = input.ScalarProject(m_leftVec) + zRotation;
- wheelSpeeds[kRight] = input.ScalarProject(m_rightVec) + zRotation;
- wheelSpeeds[kBack] = input.ScalarProject(m_backVec) + zRotation;
-
- Desaturate(wheelSpeeds);
-
- return {wheelSpeeds[kLeft], wheelSpeeds[kRight], wheelSpeeds[kBack]};
-}
-
-void KilloughDrive::StopMotor() {
- m_leftMotor->StopMotor();
- m_rightMotor->StopMotor();
- m_backMotor->StopMotor();
- Feed();
-}
-
-std::string KilloughDrive::GetDescription() const {
- return "KilloughDrive";
-}
-
-void KilloughDrive::InitSendable(wpi::SendableBuilder& builder) {
- builder.SetSmartDashboardType("KilloughDrive");
- builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
- builder.AddDoubleProperty(
- "Left Motor Speed", [=] { return m_leftMotor->Get(); },
- [=](double value) { m_leftMotor->Set(value); });
- builder.AddDoubleProperty(
- "Right Motor Speed", [=] { return m_rightMotor->Get(); },
- [=](double value) { m_rightMotor->Set(value); });
- builder.AddDoubleProperty(
- "Back Motor Speed", [=] { return m_backMotor->Get(); },
- [=](double value) { m_backMotor->Set(value); });
-}
diff --git a/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp
index 70e90d4..2bf6a3f 100644
--- a/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp
+++ b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp
@@ -5,31 +5,21 @@
#include "frc/drive/MecanumDrive.h"
#include <algorithm>
-#include <cmath>
#include <hal/FRCUsageReporting.h>
-#include <wpi/numbers>
#include <wpi/sendable/SendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/MathUtil.h"
-#include "frc/SpeedController.h"
-#include "frc/drive/Vector2d.h"
+#include "frc/geometry/Translation2d.h"
+#include "frc/motorcontrol/MotorController.h"
using namespace frc;
-#if defined(_MSC_VER)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-MecanumDrive::MecanumDrive(SpeedController& frontLeftMotor,
- SpeedController& rearLeftMotor,
- SpeedController& frontRightMotor,
- SpeedController& rearRightMotor)
+MecanumDrive::MecanumDrive(MotorController& frontLeftMotor,
+ MotorController& rearLeftMotor,
+ MotorController& frontRightMotor,
+ MotorController& rearRightMotor)
: m_frontLeftMotor(&frontLeftMotor),
m_rearLeftMotor(&rearLeftMotor),
m_frontRightMotor(&frontRightMotor),
@@ -43,19 +33,19 @@
wpi::SendableRegistry::AddLW(this, "MecanumDrive", instances);
}
-void MecanumDrive::DriveCartesian(double ySpeed, double xSpeed,
- double zRotation, double gyroAngle) {
+void MecanumDrive::DriveCartesian(double xSpeed, double ySpeed,
+ double zRotation, Rotation2d gyroAngle) {
if (!reported) {
HAL_Report(HALUsageReporting::kResourceType_RobotDrive,
HALUsageReporting::kRobotDrive2_MecanumCartesian, 4);
reported = true;
}
- ySpeed = ApplyDeadband(ySpeed, m_deadband);
xSpeed = ApplyDeadband(xSpeed, m_deadband);
+ ySpeed = ApplyDeadband(ySpeed, m_deadband);
auto [frontLeft, frontRight, rearLeft, rearRight] =
- DriveCartesianIK(ySpeed, xSpeed, zRotation, gyroAngle);
+ DriveCartesianIK(xSpeed, ySpeed, zRotation, gyroAngle);
m_frontLeftMotor->Set(frontLeft * m_maxOutput);
m_frontRightMotor->Set(frontRight * m_maxOutput);
@@ -65,7 +55,7 @@
Feed();
}
-void MecanumDrive::DrivePolar(double magnitude, double angle,
+void MecanumDrive::DrivePolar(double magnitude, Rotation2d angle,
double zRotation) {
if (!reported) {
HAL_Report(HALUsageReporting::kResourceType_RobotDrive,
@@ -73,9 +63,8 @@
reported = true;
}
- DriveCartesian(magnitude * std::cos(angle * (wpi::numbers::pi / 180.0)),
- magnitude * std::sin(angle * (wpi::numbers::pi / 180.0)),
- zRotation, 0.0);
+ DriveCartesian(magnitude * angle.Cos(), magnitude * angle.Sin(), zRotation,
+ 0_rad);
}
void MecanumDrive::StopMotor() {
@@ -86,22 +75,23 @@
Feed();
}
-MecanumDrive::WheelSpeeds MecanumDrive::DriveCartesianIK(double ySpeed,
- double xSpeed,
+MecanumDrive::WheelSpeeds MecanumDrive::DriveCartesianIK(double xSpeed,
+ double ySpeed,
double zRotation,
- double gyroAngle) {
- ySpeed = std::clamp(ySpeed, -1.0, 1.0);
+ Rotation2d gyroAngle) {
xSpeed = std::clamp(xSpeed, -1.0, 1.0);
+ ySpeed = std::clamp(ySpeed, -1.0, 1.0);
// Compensate for gyro angle.
- Vector2d input{ySpeed, xSpeed};
- input.Rotate(-gyroAngle);
+ auto input =
+ Translation2d{units::meter_t{xSpeed}, units::meter_t{ySpeed}}.RotateBy(
+ -gyroAngle);
double wheelSpeeds[4];
- wheelSpeeds[kFrontLeft] = input.x + input.y + zRotation;
- wheelSpeeds[kFrontRight] = input.x - input.y - zRotation;
- wheelSpeeds[kRearLeft] = input.x - input.y + zRotation;
- wheelSpeeds[kRearRight] = input.x + input.y - zRotation;
+ wheelSpeeds[kFrontLeft] = input.X().value() + input.Y().value() + zRotation;
+ wheelSpeeds[kFrontRight] = input.X().value() - input.Y().value() - zRotation;
+ wheelSpeeds[kRearLeft] = input.X().value() - input.Y().value() + zRotation;
+ wheelSpeeds[kRearRight] = input.X().value() + input.Y().value() - zRotation;
Desaturate(wheelSpeeds);
@@ -116,17 +106,17 @@
void MecanumDrive::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("MecanumDrive");
builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
+ builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
- "Front Left Motor Speed", [=] { return m_frontLeftMotor->Get(); },
- [=](double value) { m_frontLeftMotor->Set(value); });
+ "Front Left Motor Speed", [=, this] { return m_frontLeftMotor->Get(); },
+ [=, this](double value) { m_frontLeftMotor->Set(value); });
builder.AddDoubleProperty(
- "Front Right Motor Speed", [=] { return m_frontRightMotor->Get(); },
- [=](double value) { m_frontRightMotor->Set(value); });
+ "Front Right Motor Speed", [=, this] { return m_frontRightMotor->Get(); },
+ [=, this](double value) { m_frontRightMotor->Set(value); });
builder.AddDoubleProperty(
- "Rear Left Motor Speed", [=] { return m_rearLeftMotor->Get(); },
- [=](double value) { m_rearLeftMotor->Set(value); });
+ "Rear Left Motor Speed", [=, this] { return m_rearLeftMotor->Get(); },
+ [=, this](double value) { m_rearLeftMotor->Set(value); });
builder.AddDoubleProperty(
- "Rear Right Motor Speed", [=] { return m_rearRightMotor->Get(); },
- [=](double value) { m_rearRightMotor->Set(value); });
+ "Rear Right Motor Speed", [=, this] { return m_rearRightMotor->Get(); },
+ [=, this](double value) { m_rearRightMotor->Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp b/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp
index 97ea0ee..fbd0c6e 100644
--- a/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp
+++ b/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp
@@ -10,7 +10,6 @@
#include <hal/FRCUsageReporting.h>
-#include "frc/MathUtil.h"
#include "frc/motorcontrol/MotorController.h"
using namespace frc;
@@ -31,11 +30,7 @@
Feed();
}
-double RobotDriveBase::ApplyDeadband(double value, double deadband) {
- return frc::ApplyDeadband(value, deadband);
-}
-
-void RobotDriveBase::Desaturate(wpi::span<double> wheelSpeeds) {
+void RobotDriveBase::Desaturate(std::span<double> wheelSpeeds) {
double maxMagnitude = std::abs(wheelSpeeds[0]);
for (size_t i = 1; i < wheelSpeeds.size(); i++) {
double temp = std::abs(wheelSpeeds[i]);
diff --git a/wpilibc/src/main/native/cpp/drive/Vector2d.cpp b/wpilibc/src/main/native/cpp/drive/Vector2d.cpp
deleted file mode 100644
index a342dc2..0000000
--- a/wpilibc/src/main/native/cpp/drive/Vector2d.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "frc/drive/Vector2d.h"
-
-#include <cmath>
-
-#include <wpi/numbers>
-
-using namespace frc;
-
-Vector2d::Vector2d(double x, double y) {
- this->x = x;
- this->y = y;
-}
-
-void Vector2d::Rotate(double angle) {
- double cosA = std::cos(angle * (wpi::numbers::pi / 180.0));
- double sinA = std::sin(angle * (wpi::numbers::pi / 180.0));
- double out[2];
- out[0] = x * cosA - y * sinA;
- out[1] = x * sinA + y * cosA;
- x = out[0];
- y = out[1];
-}
-
-double Vector2d::Dot(const Vector2d& vec) const {
- return x * vec.x + y * vec.y;
-}
-
-double Vector2d::Magnitude() const {
- return std::sqrt(x * x + y * y);
-}
-
-double Vector2d::ScalarProject(const Vector2d& vec) const {
- return Dot(vec) / vec.Magnitude();
-}
diff --git a/wpilibc/src/main/native/cpp/event/BooleanEvent.cpp b/wpilibc/src/main/native/cpp/event/BooleanEvent.cpp
new file mode 100644
index 0000000..5b8ce63
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/event/BooleanEvent.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/event/BooleanEvent.h"
+
+using namespace frc;
+
+BooleanEvent::BooleanEvent(EventLoop* loop, std::function<bool()> condition)
+ : m_loop(loop), m_condition(std::move(condition)) {}
+
+BooleanEvent::operator std::function<bool()>() {
+ return m_condition;
+}
+
+bool BooleanEvent::GetAsBoolean() const {
+ return m_condition();
+}
+
+void BooleanEvent::IfHigh(std::function<void()> action) {
+ m_loop->Bind([condition = m_condition, action = std::move(action)] {
+ if (condition()) {
+ action();
+ }
+ });
+}
+
+BooleanEvent BooleanEvent::operator!() {
+ return BooleanEvent(this->m_loop, [lhs = m_condition] { return !lhs(); });
+}
+
+BooleanEvent BooleanEvent::operator&&(std::function<bool()> rhs) {
+ return BooleanEvent(this->m_loop,
+ [lhs = m_condition, rhs] { return lhs() && rhs(); });
+}
+
+BooleanEvent BooleanEvent::operator||(std::function<bool()> rhs) {
+ return BooleanEvent(this->m_loop,
+ [lhs = m_condition, rhs] { return lhs() || rhs(); });
+}
+
+BooleanEvent BooleanEvent::Rising() {
+ return BooleanEvent(
+ this->m_loop, [lhs = m_condition, m_previous = m_condition()]() mutable {
+ bool present = lhs();
+ bool past = m_previous;
+ m_previous = present;
+ return !past && present;
+ });
+}
+
+BooleanEvent BooleanEvent::Falling() {
+ return BooleanEvent(
+ this->m_loop, [lhs = m_condition, m_previous = m_condition()]() mutable {
+ bool present = lhs();
+ bool past = m_previous;
+ m_previous = present;
+ return past && !present;
+ });
+}
+
+BooleanEvent BooleanEvent::Debounce(units::second_t debounceTime,
+ frc::Debouncer::DebounceType type) {
+ return BooleanEvent(
+ this->m_loop,
+ [debouncer = frc::Debouncer(debounceTime, type),
+ lhs = m_condition]() mutable { return debouncer.Calculate(lhs()); });
+}
diff --git a/wpilibc/src/main/native/cpp/event/EventLoop.cpp b/wpilibc/src/main/native/cpp/event/EventLoop.cpp
new file mode 100644
index 0000000..5af79c9
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/event/EventLoop.cpp
@@ -0,0 +1,23 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/event/EventLoop.h"
+
+using namespace frc;
+
+EventLoop::EventLoop() {}
+
+void EventLoop::Bind(wpi::unique_function<void()> action) {
+ m_bindings.emplace_back(std::move(action));
+}
+
+void EventLoop::Poll() {
+ for (wpi::unique_function<void()>& action : m_bindings) {
+ action();
+ }
+}
+
+void EventLoop::Clear() {
+ m_bindings.clear();
+}
diff --git a/wpilibc/src/main/native/cpp/event/NetworkBooleanEvent.cpp b/wpilibc/src/main/native/cpp/event/NetworkBooleanEvent.cpp
new file mode 100644
index 0000000..d910361
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/event/NetworkBooleanEvent.cpp
@@ -0,0 +1,40 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/event/NetworkBooleanEvent.h"
+
+#include <networktables/BooleanTopic.h>
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableInstance.h>
+
+using namespace frc;
+
+NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
+ nt::BooleanTopic topic)
+ : NetworkBooleanEvent{loop, topic.Subscribe(false)} {}
+
+NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
+ nt::BooleanSubscriber sub)
+ : BooleanEvent{
+ loop,
+ [sub = std::make_shared<nt::BooleanSubscriber>(std::move(sub))] {
+ return sub->GetTopic().GetInstance().IsConnected() && sub->Get();
+ }} {}
+
+NetworkBooleanEvent::NetworkBooleanEvent(
+ EventLoop* loop, std::shared_ptr<nt::NetworkTable> table,
+ std::string_view topicName)
+ : NetworkBooleanEvent{loop, table->GetBooleanTopic(topicName)} {}
+
+NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
+ std::string_view tableName,
+ std::string_view topicName)
+ : NetworkBooleanEvent{loop, nt::NetworkTableInstance::GetDefault(),
+ tableName, topicName} {}
+
+NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
+ nt::NetworkTableInstance inst,
+ std::string_view tableName,
+ std::string_view topicName)
+ : NetworkBooleanEvent{loop, inst.GetTable(tableName), topicName} {}
diff --git a/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp b/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp
new file mode 100644
index 0000000..4085658
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/internal/DriverStationModeThread.h"
+
+#include <hal/DriverStation.h>
+#include <wpi/Synchronization.h>
+
+#include "frc/DriverStation.h"
+
+using namespace frc::internal;
+
+DriverStationModeThread::DriverStationModeThread() {
+ m_keepAlive = true;
+ m_thread = std::thread{[&] { Run(); }};
+}
+
+DriverStationModeThread::~DriverStationModeThread() {
+ m_keepAlive = false;
+ if (m_thread.joinable()) {
+ m_thread.join();
+ }
+}
+
+void DriverStationModeThread::InAutonomous(bool entering) {
+ m_userInAutonomous = entering;
+}
+void DriverStationModeThread::InDisabled(bool entering) {
+ m_userInDisabled = entering;
+}
+
+void DriverStationModeThread::InTeleop(bool entering) {
+ m_userInTeleop = entering;
+}
+
+void DriverStationModeThread::InTest(bool entering) {
+ m_userInTest = entering;
+}
+
+void DriverStationModeThread::Run() {
+ wpi::Event event{false, false};
+ HAL_ProvideNewDataEventHandle(event.GetHandle());
+
+ while (m_keepAlive.load()) {
+ bool timedOut = false;
+ wpi::WaitForObject(event.GetHandle(), 0.1, &timedOut);
+ frc::DriverStation::RefreshData();
+ if (m_userInDisabled) {
+ HAL_ObserveUserProgramDisabled();
+ }
+ if (m_userInAutonomous) {
+ HAL_ObserveUserProgramAutonomous();
+ }
+ if (m_userInTeleop) {
+ HAL_ObserveUserProgramTeleop();
+ }
+ if (m_userInTest) {
+ HAL_ObserveUserProgramTest();
+ }
+ }
+
+ HAL_RemoveNewDataEventHandle(event.GetHandle());
+}
diff --git a/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp b/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp
index ac1c8ad..0a4e1b8 100644
--- a/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp
+++ b/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp
@@ -4,9 +4,10 @@
#include "frc/livewindow/LiveWindow.h"
+#include <networktables/BooleanTopic.h>
#include <networktables/NetworkTable.h>
-#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableInstance.h>
+#include <networktables/StringTopic.h>
#include <wpi/mutex.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableRegistry.h>
@@ -18,13 +19,16 @@
namespace {
struct Component {
bool firstTime = true;
- bool telemetryEnabled = true;
+ bool telemetryEnabled = false;
+ nt::StringPublisher namePub;
+ nt::StringPublisher typePub;
};
struct Instance {
Instance() {
wpi::SendableRegistry::SetLiveWindowBuilderFactory(
[] { return std::make_unique<SendableBuilderImpl>(); });
+ enabledPub.Set(false);
}
wpi::mutex mutex;
@@ -35,11 +39,12 @@
nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow");
std::shared_ptr<nt::NetworkTable> statusTable =
liveWindowTable->GetSubTable(".status");
- nt::NetworkTableEntry enabledEntry = statusTable->GetEntry("LW Enabled");
+ nt::BooleanPublisher enabledPub =
+ statusTable->GetBooleanTopic("LW Enabled").Publish();
bool startLiveWindow = false;
bool liveWindowEnabled = false;
- bool telemetryEnabled = true;
+ bool telemetryEnabled = false;
std::function<void()> enabled;
std::function<void()> disabled;
@@ -75,12 +80,6 @@
return data;
}
-LiveWindow* LiveWindow::GetInstance() {
- ::GetInstance();
- static LiveWindow instance;
- return &instance;
-}
-
void LiveWindow::SetEnabledCallback(std::function<void()> func) {
::GetInstance().enabled = func;
}
@@ -115,6 +114,18 @@
});
}
+void LiveWindow::EnableAllTelemetry() {
+ auto& inst = ::GetInstance();
+ std::scoped_lock lock(inst.mutex);
+ inst.telemetryEnabled = true;
+ wpi::SendableRegistry::ForeachLiveWindow(inst.dataHandle, [&](auto& cbdata) {
+ if (!cbdata.data) {
+ cbdata.data = std::make_shared<Component>();
+ }
+ std::static_pointer_cast<Component>(cbdata.data)->telemetryEnabled = true;
+ });
+}
+
bool LiveWindow::IsEnabled() {
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.mutex);
@@ -145,7 +156,7 @@
inst.disabled();
}
}
- inst.enabledEntry.SetBoolean(enabled);
+ inst.enabledPub.Set(enabled);
}
void LiveWindow::UpdateValues() {
@@ -192,10 +203,12 @@
} else {
table = ssTable->GetSubTable(cbdata.name);
}
- table->GetEntry(".name").SetString(cbdata.name);
+ comp.namePub = nt::StringTopic{table->GetTopic(".name")}.Publish();
+ comp.namePub.Set(cbdata.name);
static_cast<SendableBuilderImpl&>(cbdata.builder).SetTable(table);
cbdata.sendable->InitSendable(cbdata.builder);
- ssTable->GetEntry(".type").SetString("LW Subsystem");
+ comp.typePub = nt::StringTopic{ssTable->GetTopic(".type")}.Publish();
+ comp.typePub.Set("LW Subsystem");
comp.firstTime = false;
}
diff --git a/wpilibc/src/main/native/cpp/SpeedController.cpp b/wpilibc/src/main/native/cpp/motorcontrol/MotorController.cpp
similarity index 62%
rename from wpilibc/src/main/native/cpp/SpeedController.cpp
rename to wpilibc/src/main/native/cpp/motorcontrol/MotorController.cpp
index e0b0cb2..9d20144 100644
--- a/wpilibc/src/main/native/cpp/SpeedController.cpp
+++ b/wpilibc/src/main/native/cpp/motorcontrol/MotorController.cpp
@@ -2,12 +2,12 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
-#include "frc/SpeedController.h"
+#include "frc/motorcontrol/MotorController.h"
#include <frc/RobotController.h>
using namespace frc;
-void SpeedController::SetVoltage(units::volt_t output) {
- Set(output / units::volt_t(RobotController::GetInputVoltage()));
+void MotorController::SetVoltage(units::volt_t output) {
+ Set(output / RobotController::GetBatteryVoltage());
}
diff --git a/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp b/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp
index b7f26d1..f855d14 100644
--- a/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp
+++ b/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp
@@ -33,6 +33,12 @@
}
}
+void MotorControllerGroup::SetVoltage(units::volt_t output) {
+ for (auto motorController : m_motorControllers) {
+ motorController.get().SetVoltage(m_isInverted ? -output : output);
+ }
+}
+
double MotorControllerGroup::Get() const {
if (!m_motorControllers.empty()) {
return m_motorControllers.front().get().Get() * (m_isInverted ? -1 : 1);
@@ -63,7 +69,8 @@
void MotorControllerGroup::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Motor Controller");
builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
+ builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, [=](double value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](double value) { Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp b/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp
index 21164eb..01c70d0 100644
--- a/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp
+++ b/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp
@@ -73,7 +73,8 @@
void NidecBrushless::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Nidec Brushless");
builder.SetActuator(true);
- builder.SetSafeState([=] { StopMotor(); });
+ builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, [=](double value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](double value) { Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp b/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp
index f9ff4b8..3692f75 100644
--- a/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp
+++ b/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp
@@ -12,6 +12,7 @@
void PWMMotorController::Set(double speed) {
m_pwm.SetSpeed(m_isInverted ? -speed : speed);
+ Feed();
}
double PWMMotorController::Get() const {
@@ -31,7 +32,8 @@
}
void PWMMotorController::StopMotor() {
- Disable();
+ // Don't use Set(0) as that will feed the watch kitty
+ m_pwm.SetSpeed(0);
}
std::string PWMMotorController::GetDescription() const {
@@ -54,7 +56,8 @@
void PWMMotorController::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Motor Controller");
builder.SetActuator(true);
- builder.SetSafeState([=] { Disable(); });
+ builder.SetSafeState([=, this] { Disable(); });
builder.AddDoubleProperty(
- "Value", [=] { return Get(); }, [=](double value) { Set(value); });
+ "Value", [=, this] { return Get(); },
+ [=, this](double value) { Set(value); });
}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp b/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp
index 834c4be..fb1ef9c 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp
@@ -9,40 +9,40 @@
using namespace frc;
using namespace frc::detail;
-RecordingController::RecordingController(nt::NetworkTableInstance ntInstance)
- : m_recordingControlEntry(), m_recordingFileNameFormatEntry() {
+RecordingController::RecordingController(nt::NetworkTableInstance ntInstance) {
m_recordingControlEntry =
- ntInstance.GetEntry("/Shuffleboard/.recording/RecordData");
+ ntInstance.GetBooleanTopic("/Shuffleboard/.recording/RecordData")
+ .Publish();
m_recordingFileNameFormatEntry =
- ntInstance.GetEntry("/Shuffleboard/.recording/FileNameFormat");
+ ntInstance.GetStringTopic("/Shuffleboard/.recording/FileNameFormat")
+ .Publish();
m_eventsTable = ntInstance.GetTable("/Shuffleboard/.recording/events");
}
void RecordingController::StartRecording() {
- m_recordingControlEntry.SetBoolean(true);
+ m_recordingControlEntry.Set(true);
}
void RecordingController::StopRecording() {
- m_recordingControlEntry.SetBoolean(false);
+ m_recordingControlEntry.Set(false);
}
void RecordingController::SetRecordingFileNameFormat(std::string_view format) {
- m_recordingFileNameFormatEntry.SetString(format);
+ m_recordingFileNameFormatEntry.Set(format);
}
void RecordingController::ClearRecordingFileNameFormat() {
- m_recordingFileNameFormatEntry.Delete();
+ m_recordingFileNameFormatEntry.Set("");
}
void RecordingController::AddEventMarker(
std::string_view name, std::string_view description,
ShuffleboardEventImportance importance) {
if (name.empty()) {
- FRC_ReportError(err::Error, "{}",
- "Shuffleboard event name was not specified");
+ FRC_ReportError(err::Error, "Shuffleboard event name was not specified");
return;
}
m_eventsTable->GetSubTable(name)->GetEntry("Info").SetStringArray(
- {std::string{description},
- std::string{ShuffleboardEventImportanceName(importance)}});
+ {{std::string{description},
+ std::string{ShuffleboardEventImportanceName(importance)}}});
}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp b/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp
index 16b404c..9135012 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp
@@ -63,10 +63,24 @@
AddEventMarker(name, "", importance);
}
-detail::ShuffleboardInstance& Shuffleboard::GetInstance() {
- static detail::ShuffleboardInstance inst(
+static std::unique_ptr<detail::ShuffleboardInstance>& GetInstanceHolder() {
+ static std::unique_ptr<detail::ShuffleboardInstance> instance =
+ std::make_unique<detail::ShuffleboardInstance>(
+ nt::NetworkTableInstance::GetDefault());
+ return instance;
+}
+
+#ifndef __FRC_ROBORIO__
+namespace frc::impl {
+void ResetShuffleboardInstance() {
+ GetInstanceHolder() = std::make_unique<detail::ShuffleboardInstance>(
nt::NetworkTableInstance::GetDefault());
- return inst;
+}
+} // namespace frc::impl
+#endif
+
+detail::ShuffleboardInstance& Shuffleboard::GetInstance() {
+ return *GetInstanceHolder();
}
detail::RecordingController& Shuffleboard::GetRecordingController() {
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp
index 940f6ab..c43fc90 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp
@@ -22,27 +22,21 @@
return;
}
// Component type
- if (GetType() == "") {
- metaTable->GetEntry("PreferredComponent").Delete();
- } else {
- metaTable->GetEntry("PreferredComponent").ForceSetString(GetType());
+ if (!GetType().empty()) {
+ metaTable->GetEntry("PreferredComponent").SetString(GetType());
}
// Tile size
- if (m_width <= 0 || m_height <= 0) {
- metaTable->GetEntry("Size").Delete();
- } else {
+ if (m_width > 0 && m_height > 0) {
metaTable->GetEntry("Size").SetDoubleArray(
- {static_cast<double>(m_width), static_cast<double>(m_height)});
+ {{static_cast<double>(m_width), static_cast<double>(m_height)}});
}
// Tile position
- if (m_column < 0 || m_row < 0) {
- metaTable->GetEntry("Position").Delete();
- } else {
+ if (m_column >= 0 && m_row >= 0) {
metaTable->GetEntry("Position")
.SetDoubleArray(
- {static_cast<double>(m_column), static_cast<double>(m_row)});
+ {{static_cast<double>(m_column), static_cast<double>(m_row)}});
}
// Custom properties
@@ -63,7 +57,7 @@
return m_type;
}
-const wpi::StringMap<std::shared_ptr<nt::Value>>&
-ShuffleboardComponentBase::GetProperties() const {
+const wpi::StringMap<nt::Value>& ShuffleboardComponentBase::GetProperties()
+ const {
return m_properties;
}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp
index 004f7c5..ca3c6d6 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp
@@ -4,6 +4,7 @@
#include "frc/shuffleboard/ShuffleboardContainer.h"
+#include <ntcore_cpp.h>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/Errors.h"
@@ -69,19 +70,20 @@
ComplexWidget& ShuffleboardContainer::Add(wpi::Sendable& sendable) {
auto name = wpi::SendableRegistry::GetName(&sendable);
if (name.empty()) {
- FRC_ReportError(err::Error, "{}", "Sendable must have a name");
+ FRC_ReportError(err::Error, "Sendable must have a name");
}
return Add(name, sendable);
}
-SimpleWidget& ShuffleboardContainer::Add(
- std::string_view title, std::shared_ptr<nt::Value> defaultValue) {
+SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
+ const nt::Value& defaultValue) {
CheckTitle(title);
auto widget = std::make_unique<SimpleWidget>(*this, title);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
- ptr->GetEntry().SetDefaultValue(defaultValue);
+ ptr->GetEntry(nt::GetStringFromType(defaultValue.type()))
+ ->SetDefault(defaultValue);
return *ptr;
}
@@ -96,8 +98,13 @@
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
+ float defaultValue) {
+ return Add(title, nt::Value::MakeFloat(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
int defaultValue) {
- return Add(title, nt::Value::MakeDouble(defaultValue));
+ return Add(title, nt::Value::MakeInteger(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
@@ -111,29 +118,39 @@
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
- wpi::span<const bool> defaultValue) {
+ std::span<const bool> defaultValue) {
return Add(title, nt::Value::MakeBooleanArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
- wpi::span<const double> defaultValue) {
+ std::span<const double> defaultValue) {
return Add(title, nt::Value::MakeDoubleArray(defaultValue));
}
+SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
+ std::span<const float> defaultValue) {
+ return Add(title, nt::Value::MakeFloatArray(defaultValue));
+}
+
SimpleWidget& ShuffleboardContainer::Add(
- std::string_view title, wpi::span<const std::string> defaultValue) {
+ std::string_view title, std::span<const int64_t> defaultValue) {
+ return Add(title, nt::Value::MakeIntegerArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(
+ std::string_view title, std::span<const std::string> defaultValue) {
return Add(title, nt::Value::MakeStringArray(defaultValue));
}
SuppliedValueWidget<std::string>& ShuffleboardContainer::AddString(
std::string_view title, std::function<std::string()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry, std::string value) {
+ static auto setter = [](nt::GenericPublisher& entry, std::string value) {
entry.SetString(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::string>>(
- *this, title, supplier, setter);
+ *this, title, "string", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
@@ -141,13 +158,46 @@
SuppliedValueWidget<double>& ShuffleboardContainer::AddNumber(
std::string_view title, std::function<double()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry, double value) {
+ return AddDouble(title, std::move(supplier));
+}
+
+SuppliedValueWidget<double>& ShuffleboardContainer::AddDouble(
+ std::string_view title, std::function<double()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry, double value) {
entry.SetDouble(value);
};
CheckTitle(title);
- auto widget = std::make_unique<SuppliedValueWidget<double>>(*this, title,
- supplier, setter);
+ auto widget = std::make_unique<SuppliedValueWidget<double>>(
+ *this, title, "double", supplier, setter);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ return *ptr;
+}
+
+SuppliedValueWidget<float>& ShuffleboardContainer::AddFloat(
+ std::string_view title, std::function<float()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry, float value) {
+ entry.SetFloat(value);
+ };
+
+ CheckTitle(title);
+ auto widget = std::make_unique<SuppliedValueWidget<float>>(
+ *this, title, "float", supplier, setter);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ return *ptr;
+}
+
+SuppliedValueWidget<int64_t>& ShuffleboardContainer::AddInteger(
+ std::string_view title, std::function<int64_t()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry, int64_t value) {
+ entry.SetInteger(value);
+ };
+
+ CheckTitle(title);
+ auto widget = std::make_unique<SuppliedValueWidget<int64_t>>(
+ *this, title, "int", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
@@ -155,13 +205,13 @@
SuppliedValueWidget<bool>& ShuffleboardContainer::AddBoolean(
std::string_view title, std::function<bool()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry, bool value) {
+ static auto setter = [](nt::GenericPublisher& entry, bool value) {
entry.SetBoolean(value);
};
CheckTitle(title);
- auto widget = std::make_unique<SuppliedValueWidget<bool>>(*this, title,
- supplier, setter);
+ auto widget = std::make_unique<SuppliedValueWidget<bool>>(
+ *this, title, "boolean", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
@@ -171,14 +221,14 @@
ShuffleboardContainer::AddStringArray(
std::string_view title,
std::function<std::vector<std::string>()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry,
+ static auto setter = [](nt::GenericPublisher& entry,
std::vector<std::string> value) {
entry.SetStringArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<std::string>>>(
- *this, title, supplier, setter);
+ *this, title, "string[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
@@ -186,14 +236,50 @@
SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddNumberArray(
std::string_view title, std::function<std::vector<double>()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry,
+ return AddDoubleArray(title, std::move(supplier));
+}
+
+SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddDoubleArray(
+ std::string_view title, std::function<std::vector<double>()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry,
std::vector<double> value) {
entry.SetDoubleArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<double>>>(
- *this, title, supplier, setter);
+ *this, title, "double[]", supplier, setter);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ return *ptr;
+}
+
+SuppliedValueWidget<std::vector<float>>& ShuffleboardContainer::AddFloatArray(
+ std::string_view title, std::function<std::vector<float>()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry,
+ std::vector<float> value) {
+ entry.SetFloatArray(value);
+ };
+
+ CheckTitle(title);
+ auto widget = std::make_unique<SuppliedValueWidget<std::vector<float>>>(
+ *this, title, "float[]", supplier, setter);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ return *ptr;
+}
+
+SuppliedValueWidget<std::vector<int64_t>>&
+ShuffleboardContainer::AddIntegerArray(
+ std::string_view title, std::function<std::vector<int64_t>()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry,
+ std::vector<int64_t> value) {
+ entry.SetIntegerArray(value);
+ };
+
+ CheckTitle(title);
+ auto widget = std::make_unique<SuppliedValueWidget<std::vector<int64_t>>>(
+ *this, title, "int[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
@@ -201,36 +287,43 @@
SuppliedValueWidget<std::vector<int>>& ShuffleboardContainer::AddBooleanArray(
std::string_view title, std::function<std::vector<int>()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry, std::vector<int> value) {
+ static auto setter = [](nt::GenericPublisher& entry, std::vector<int> value) {
entry.SetBooleanArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<int>>>(
- *this, title, supplier, setter);
+ *this, title, "boolean[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
-SuppliedValueWidget<std::string_view>& ShuffleboardContainer::AddRaw(
- std::string_view title, std::function<std::string_view()> supplier) {
- static auto setter = [](nt::NetworkTableEntry entry, std::string_view value) {
- entry.SetRaw(value);
- };
+SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
+ std::string_view title, std::function<std::vector<uint8_t>()> supplier) {
+ return AddRaw(title, "raw", std::move(supplier));
+}
+
+SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
+ std::string_view title, std::string_view typeString,
+ std::function<std::vector<uint8_t>()> supplier) {
+ static auto setter = [](nt::GenericPublisher& entry,
+ std::vector<uint8_t> value) { entry.SetRaw(value); };
CheckTitle(title);
- auto widget = std::make_unique<SuppliedValueWidget<std::string_view>>(
- *this, title, supplier, setter);
+ auto widget = std::make_unique<SuppliedValueWidget<std::vector<uint8_t>>>(
+ *this, title, typeString, supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
- std::string_view title, std::shared_ptr<nt::Value> defaultValue) {
+ std::string_view title, const nt::Value& defaultValue) {
auto& widget = Add(title, defaultValue);
- widget.GetEntry().SetPersistent();
+ widget.GetEntry(nt::GetStringFromType(defaultValue.type()))
+ ->GetTopic()
+ .SetPersistent(true);
return widget;
}
@@ -245,8 +338,13 @@
}
SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
+ float defaultValue) {
+ return AddPersistent(title, nt::Value::MakeFloat(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
int defaultValue) {
- return AddPersistent(title, nt::Value::MakeDouble(defaultValue));
+ return AddPersistent(title, nt::Value::MakeInteger(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
@@ -255,17 +353,27 @@
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
- std::string_view title, wpi::span<const bool> defaultValue) {
+ std::string_view title, std::span<const bool> defaultValue) {
return AddPersistent(title, nt::Value::MakeBooleanArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
- std::string_view title, wpi::span<const double> defaultValue) {
+ std::string_view title, std::span<const double> defaultValue) {
return AddPersistent(title, nt::Value::MakeDoubleArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
- std::string_view title, wpi::span<const std::string> defaultValue) {
+ std::string_view title, std::span<const float> defaultValue) {
+ return AddPersistent(title, nt::Value::MakeFloatArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ std::string_view title, std::span<const int64_t> defaultValue) {
+ return AddPersistent(title, nt::Value::MakeIntegerArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ std::string_view title, std::span<const std::string> defaultValue) {
return AddPersistent(title, nt::Value::MakeStringArray(defaultValue));
}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp
index 083b4a2..a315b90 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp
@@ -46,7 +46,7 @@
for (auto& entry : m_impl->tabs) {
tabTitles.emplace_back(entry.second->GetTitle());
}
- m_impl->rootMetaTable->GetEntry("Tabs").ForceSetStringArray(tabTitles);
+ m_impl->rootMetaTable->GetEntry("Tabs").SetStringArray(tabTitles);
m_impl->tabsChanged = false;
}
for (auto& entry : m_impl->tabs) {
@@ -75,9 +75,9 @@
}
void ShuffleboardInstance::SelectTab(int index) {
- m_impl->rootMetaTable->GetEntry("Selected").ForceSetDouble(index);
+ m_impl->rootMetaTable->GetEntry("Selected").SetDouble(index);
}
void ShuffleboardInstance::SelectTab(std::string_view title) {
- m_impl->rootMetaTable->GetEntry("Selected").ForceSetString(title);
+ m_impl->rootMetaTable->GetEntry("Selected").SetString(title);
}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp
index 31e4b11..bb475fd 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp
@@ -20,7 +20,7 @@
"ComboBox Chooser",
"Split Button Chooser",
"Encoder",
- "Speed Controller",
+ "Motor Controller",
"Command",
"PID Command",
"PID Controller",
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp
index 390c9c4..c62b76d 100644
--- a/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp
+++ b/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp
@@ -14,18 +14,26 @@
std::string_view title)
: ShuffleboardValue(title), ShuffleboardWidget(parent, title), m_entry() {}
-nt::NetworkTableEntry SimpleWidget::GetEntry() {
+nt::GenericEntry* SimpleWidget::GetEntry() {
if (!m_entry) {
ForceGenerate();
}
- return m_entry;
+ return &m_entry;
+}
+
+nt::GenericEntry* SimpleWidget::GetEntry(std::string_view typeString) {
+ if (!m_entry) {
+ m_typeString = typeString;
+ ForceGenerate();
+ }
+ return &m_entry;
}
void SimpleWidget::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) {
BuildMetadata(metaTable);
if (!m_entry) {
- m_entry = parentTable->GetEntry(GetTitle());
+ m_entry = parentTable->GetTopic(GetTitle()).GetGenericEntry(m_typeString);
}
}
diff --git a/wpilibc/src/main/native/cpp/simulation/AnalogEncoderSim.cpp b/wpilibc/src/main/native/cpp/simulation/AnalogEncoderSim.cpp
index 049241e..435e29e 100644
--- a/wpilibc/src/main/native/cpp/simulation/AnalogEncoderSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/AnalogEncoderSim.cpp
@@ -27,6 +27,5 @@
}
frc::Rotation2d AnalogEncoderSim::GetPosition() {
- units::radian_t rads = GetTurns();
- return frc::Rotation2d{rads};
+ return units::radian_t{GetTurns()};
}
diff --git a/wpilibc/src/main/native/cpp/simulation/CTREPCMSim.cpp b/wpilibc/src/main/native/cpp/simulation/CTREPCMSim.cpp
index 9c7450b..0081928 100644
--- a/wpilibc/src/main/native/cpp/simulation/CTREPCMSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/CTREPCMSim.cpp
@@ -14,12 +14,13 @@
using namespace frc;
using namespace frc::sim;
-CTREPCMSim::CTREPCMSim() : m_index{SensorUtil::GetDefaultCTREPCMModule()} {}
+CTREPCMSim::CTREPCMSim()
+ : PneumaticsBaseSim{SensorUtil::GetDefaultCTREPCMModule()} {}
-CTREPCMSim::CTREPCMSim(int module) : m_index{module} {}
+CTREPCMSim::CTREPCMSim(int module) : PneumaticsBaseSim{module} {}
CTREPCMSim::CTREPCMSim(const PneumaticsBase& pneumatics)
- : m_index{pneumatics.GetModuleNumber()} {}
+ : PneumaticsBaseSim{pneumatics.GetModuleNumber()} {}
std::unique_ptr<CallbackStore> CTREPCMSim::RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify) {
diff --git a/wpilibc/src/main/native/cpp/simulation/DCMotorSim.cpp b/wpilibc/src/main/native/cpp/simulation/DCMotorSim.cpp
index 7860e32..bda2020 100644
--- a/wpilibc/src/main/native/cpp/simulation/DCMotorSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/DCMotorSim.cpp
@@ -42,5 +42,5 @@
}
void DCMotorSim::SetInputVoltage(units::volt_t voltage) {
- SetInput(Eigen::Vector<double, 1>{voltage.value()});
+ SetInput(Vectord<1>{voltage.value()});
}
diff --git a/wpilibc/src/main/native/cpp/simulation/DifferentialDrivetrainSim.cpp b/wpilibc/src/main/native/cpp/simulation/DifferentialDrivetrainSim.cpp
index 78b9dc7..b6c95dc 100644
--- a/wpilibc/src/main/native/cpp/simulation/DifferentialDrivetrainSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/DifferentialDrivetrainSim.cpp
@@ -41,8 +41,7 @@
driveMotor, mass, wheelRadius, trackWidth / 2.0, J, gearing),
trackWidth, driveMotor, gearing, wheelRadius, measurementStdDevs) {}
-Eigen::Vector<double, 2> DifferentialDrivetrainSim::ClampInput(
- const Eigen::Vector<double, 2>& u) {
+Vectord<2> DifferentialDrivetrainSim::ClampInput(const Vectord<2>& u) {
return frc::DesaturateInputVector<2>(u,
frc::RobotController::GetInputVoltage());
}
@@ -66,11 +65,11 @@
return m_currentGearing;
}
-Eigen::Vector<double, 7> DifferentialDrivetrainSim::GetOutput() const {
+Vectord<7> DifferentialDrivetrainSim::GetOutput() const {
return m_y;
}
-Eigen::Vector<double, 7> DifferentialDrivetrainSim::GetState() const {
+Vectord<7> DifferentialDrivetrainSim::GetState() const {
return m_x;
}
@@ -83,20 +82,20 @@
}
Rotation2d DifferentialDrivetrainSim::GetHeading() const {
- return Rotation2d(units::radian_t(GetOutput(State::kHeading)));
+ return units::radian_t{GetOutput(State::kHeading)};
}
Pose2d DifferentialDrivetrainSim::GetPose() const {
- return Pose2d(units::meter_t(GetOutput(State::kX)),
- units::meter_t(GetOutput(State::kY)), GetHeading());
+ return Pose2d{units::meter_t{GetOutput(State::kX)},
+ units::meter_t{GetOutput(State::kY)}, GetHeading()};
}
units::ampere_t DifferentialDrivetrainSim::GetLeftCurrentDraw() const {
auto loadIleft =
m_motor.Current(
- units::radians_per_second_t(m_x(State::kLeftVelocity) *
- m_currentGearing / m_wheelRadius.value()),
- units::volt_t(m_u(0))) *
+ units::radians_per_second_t{m_x(State::kLeftVelocity) *
+ m_currentGearing / m_wheelRadius.value()},
+ units::volt_t{m_u(0)}) *
wpi::sgn(m_u(0));
return loadIleft;
@@ -105,9 +104,9 @@
units::ampere_t DifferentialDrivetrainSim::GetRightCurrentDraw() const {
auto loadIRight =
m_motor.Current(
- units::radians_per_second_t(m_x(State::kRightVelocity) *
- m_currentGearing / m_wheelRadius.value()),
- units::volt_t(m_u(1))) *
+ units::radians_per_second_t{m_x(State::kRightVelocity) *
+ m_currentGearing / m_wheelRadius.value()},
+ units::volt_t{m_u(1)}) *
wpi::sgn(m_u(1));
return loadIRight;
@@ -116,8 +115,7 @@
return GetLeftCurrentDraw() + GetRightCurrentDraw();
}
-void DifferentialDrivetrainSim::SetState(
- const Eigen::Vector<double, 7>& state) {
+void DifferentialDrivetrainSim::SetState(const Vectord<7>& state) {
m_x = state;
}
@@ -129,19 +127,19 @@
m_x(State::kRightPosition) = 0;
}
-Eigen::Vector<double, 7> DifferentialDrivetrainSim::Dynamics(
- const Eigen::Vector<double, 7>& x, const Eigen::Vector<double, 2>& u) {
- // Because G^2 can be factored out of A, we can divide by the old ratio
+Vectord<7> DifferentialDrivetrainSim::Dynamics(const Vectord<7>& x,
+ const Vectord<2>& u) {
+ // Because G² can be factored out of A, we can divide by the old ratio
// squared and multiply by the new ratio squared to get a new drivetrain
// model.
- Eigen::Matrix<double, 4, 2> B;
+ Matrixd<4, 2> B;
B.block<2, 2>(0, 0) = m_plant.B() * m_currentGearing * m_currentGearing /
m_originalGearing / m_originalGearing;
B.block<2, 2>(2, 0).setZero();
// Because G can be factored out of B, we can divide by the old ratio and
// multiply by the new ratio to get a new drivetrain model.
- Eigen::Matrix<double, 4, 4> A;
+ Matrixd<4, 4> A;
A.block<2, 2>(0, 0) = m_plant.A() * m_currentGearing / m_originalGearing;
A.block<2, 2>(2, 0).setIdentity();
@@ -149,7 +147,7 @@
double v = (x(State::kLeftVelocity) + x(State::kRightVelocity)) / 2.0;
- Eigen::Vector<double, 7> xdot;
+ Vectord<7> xdot;
xdot(0) = v * std::cos(x(State::kHeading));
xdot(1) = v * std::sin(x(State::kHeading));
xdot(2) =
diff --git a/wpilibc/src/main/native/cpp/simulation/DoubleSolenoidSim.cpp b/wpilibc/src/main/native/cpp/simulation/DoubleSolenoidSim.cpp
new file mode 100644
index 0000000..da99867
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/simulation/DoubleSolenoidSim.cpp
@@ -0,0 +1,48 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/simulation/DoubleSolenoidSim.h"
+
+#include "frc/PneumaticsBase.h"
+
+using namespace frc;
+using namespace frc::sim;
+
+DoubleSolenoidSim::DoubleSolenoidSim(
+ std::shared_ptr<PneumaticsBaseSim> moduleSim, int fwd, int rev)
+ : m_module{std::move(moduleSim)}, m_fwd{fwd}, m_rev{rev} {}
+
+DoubleSolenoidSim::DoubleSolenoidSim(int module, PneumaticsModuleType type,
+ int fwd, int rev)
+ : m_module{PneumaticsBaseSim::GetForType(module, type)},
+ m_fwd{fwd},
+ m_rev{rev} {}
+
+DoubleSolenoidSim::DoubleSolenoidSim(PneumaticsModuleType type, int fwd,
+ int rev)
+ : m_module{PneumaticsBaseSim::GetForType(
+ PneumaticsBase::GetDefaultForType(type), type)},
+ m_fwd{fwd},
+ m_rev{rev} {}
+
+DoubleSolenoid::Value DoubleSolenoidSim::Get() const {
+ bool fwdState = m_module->GetSolenoidOutput(m_fwd);
+ bool revState = m_module->GetSolenoidOutput(m_rev);
+ if (fwdState && !revState) {
+ return DoubleSolenoid::Value::kForward;
+ } else if (!fwdState && revState) {
+ return DoubleSolenoid::Value::kReverse;
+ } else {
+ return DoubleSolenoid::Value::kOff;
+ }
+}
+
+void DoubleSolenoidSim::Set(DoubleSolenoid::Value output) {
+ m_module->SetSolenoidOutput(m_fwd, output == DoubleSolenoid::Value::kForward);
+ m_module->SetSolenoidOutput(m_rev, output == DoubleSolenoid::Value::kReverse);
+}
+
+std::shared_ptr<PneumaticsBaseSim> DoubleSolenoidSim::GetModuleSim() const {
+ return m_module;
+}
diff --git a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp
index 5f2c645..345204a 100644
--- a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include <hal/DriverStation.h>
#include <hal/simulation/DriverStationData.h>
#include <hal/simulation/MockHooks.h>
@@ -154,8 +155,12 @@
}
void DriverStationSim::NotifyNewData() {
+ wpi::Event waitEvent{true};
+ HAL_ProvideNewDataEventHandle(waitEvent.GetHandle());
HALSIM_NotifyDriverStationNewData();
- DriverStation::WaitForData();
+ wpi::WaitForObject(waitEvent.GetHandle());
+ HAL_RemoveNewDataEventHandle(waitEvent.GetHandle());
+ frc::DriverStation::RefreshData();
}
void DriverStationSim::SetSendError(bool shouldSend) {
@@ -229,20 +234,20 @@
HALSIM_SetJoystickType(stick, type);
}
-void DriverStationSim::SetJoystickName(int stick, const char* name) {
- HALSIM_SetJoystickName(stick, name);
+void DriverStationSim::SetJoystickName(int stick, std::string_view name) {
+ HALSIM_SetJoystickName(stick, name.data(), name.size());
}
void DriverStationSim::SetJoystickAxisType(int stick, int axis, int type) {
HALSIM_SetJoystickAxisType(stick, axis, type);
}
-void DriverStationSim::SetGameSpecificMessage(const char* message) {
- HALSIM_SetGameSpecificMessage(message);
+void DriverStationSim::SetGameSpecificMessage(std::string_view message) {
+ HALSIM_SetGameSpecificMessage(message.data(), message.size());
}
-void DriverStationSim::SetEventName(const char* name) {
- HALSIM_SetEventName(name);
+void DriverStationSim::SetEventName(std::string_view name) {
+ HALSIM_SetEventName(name.data(), name.size());
}
void DriverStationSim::SetMatchType(DriverStation::MatchType type) {
diff --git a/wpilibc/src/main/native/cpp/simulation/ElevatorSim.cpp b/wpilibc/src/main/native/cpp/simulation/ElevatorSim.cpp
index a2d5c66..529fb1a 100644
--- a/wpilibc/src/main/native/cpp/simulation/ElevatorSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/ElevatorSim.cpp
@@ -15,19 +15,20 @@
ElevatorSim::ElevatorSim(const LinearSystem<2, 1, 1>& plant,
const DCMotor& gearbox, double gearing,
units::meter_t drumRadius, units::meter_t minHeight,
- units::meter_t maxHeight,
+ units::meter_t maxHeight, bool simulateGravity,
const std::array<double, 1>& measurementStdDevs)
: LinearSystemSim(plant, measurementStdDevs),
m_gearbox(gearbox),
m_drumRadius(drumRadius),
m_minHeight(minHeight),
m_maxHeight(maxHeight),
- m_gearing(gearing) {}
+ m_gearing(gearing),
+ m_simulateGravity(simulateGravity) {}
ElevatorSim::ElevatorSim(const DCMotor& gearbox, double gearing,
units::kilogram_t carriageMass,
units::meter_t drumRadius, units::meter_t minHeight,
- units::meter_t maxHeight,
+ units::meter_t maxHeight, bool simulateGravity,
const std::array<double, 1>& measurementStdDevs)
: LinearSystemSim(LinearSystemId::ElevatorSystem(gearbox, carriageMass,
drumRadius, gearing),
@@ -36,7 +37,8 @@
m_drumRadius(drumRadius),
m_minHeight(minHeight),
m_maxHeight(maxHeight),
- m_gearing(gearing) {}
+ m_gearing(gearing),
+ m_simulateGravity(simulateGravity) {}
bool ElevatorSim::WouldHitLowerLimit(units::meter_t elevatorHeight) const {
return elevatorHeight < m_minHeight;
@@ -47,11 +49,11 @@
}
bool ElevatorSim::HasHitLowerLimit() const {
- return WouldHitLowerLimit(units::meter_t(m_y(0)));
+ return WouldHitLowerLimit(units::meter_t{m_y(0)});
}
bool ElevatorSim::HasHitUpperLimit() const {
- return WouldHitUpperLimit(units::meter_t(m_y(0)));
+ return WouldHitUpperLimit(units::meter_t{m_y(0)});
}
units::meter_t ElevatorSim::GetPosition() const {
@@ -78,25 +80,27 @@
}
void ElevatorSim::SetInputVoltage(units::volt_t voltage) {
- SetInput(Eigen::Vector<double, 1>{voltage.value()});
+ SetInput(Vectord<1>{voltage.value()});
}
-Eigen::Vector<double, 2> ElevatorSim::UpdateX(
- const Eigen::Vector<double, 2>& currentXhat,
- const Eigen::Vector<double, 1>& u, units::second_t dt) {
+Vectord<2> ElevatorSim::UpdateX(const Vectord<2>& currentXhat,
+ const Vectord<1>& u, units::second_t dt) {
auto updatedXhat = RKDP(
- [&](const Eigen::Vector<double, 2>& x,
- const Eigen::Vector<double, 1>& u_) -> Eigen::Vector<double, 2> {
- return m_plant.A() * x + m_plant.B() * u_ +
- Eigen::Vector<double, 2>{0.0, -9.8};
+ [&](const Vectord<2>& x, const Vectord<1>& u_) -> Vectord<2> {
+ Vectord<2> xdot = m_plant.A() * x + m_plant.B() * u;
+
+ if (m_simulateGravity) {
+ xdot += Vectord<2>{0.0, -9.8};
+ }
+ return xdot;
},
currentXhat, u, dt);
// Check for collision after updating x-hat.
- if (WouldHitLowerLimit(units::meter_t(updatedXhat(0)))) {
- return Eigen::Vector<double, 2>{m_minHeight.value(), 0.0};
+ if (WouldHitLowerLimit(units::meter_t{updatedXhat(0)})) {
+ return Vectord<2>{m_minHeight.value(), 0.0};
}
- if (WouldHitUpperLimit(units::meter_t(updatedXhat(0)))) {
- return Eigen::Vector<double, 2>{m_maxHeight.value(), 0.0};
+ if (WouldHitUpperLimit(units::meter_t{updatedXhat(0)})) {
+ return Vectord<2>{m_maxHeight.value(), 0.0};
}
return updatedXhat;
}
diff --git a/wpilibc/src/main/native/cpp/simulation/FlywheelSim.cpp b/wpilibc/src/main/native/cpp/simulation/FlywheelSim.cpp
index f4371b1..95dcb9e 100644
--- a/wpilibc/src/main/native/cpp/simulation/FlywheelSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/FlywheelSim.cpp
@@ -38,5 +38,5 @@
}
void FlywheelSim::SetInputVoltage(units::volt_t voltage) {
- SetInput(Eigen::Vector<double, 1>{voltage.value()});
+ SetInput(Vectord<1>{voltage.value()});
}
diff --git a/wpilibc/src/main/native/cpp/simulation/PS4ControllerSim.cpp b/wpilibc/src/main/native/cpp/simulation/PS4ControllerSim.cpp
index 3403755..fecac9d 100644
--- a/wpilibc/src/main/native/cpp/simulation/PS4ControllerSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/PS4ControllerSim.cpp
@@ -13,11 +13,13 @@
: GenericHIDSim{joystick} {
SetAxisCount(6);
SetButtonCount(14);
+ SetPOVCount(1);
}
PS4ControllerSim::PS4ControllerSim(int port) : GenericHIDSim{port} {
SetAxisCount(6);
SetButtonCount(14);
+ SetPOVCount(1);
}
void PS4ControllerSim::SetLeftX(double value) {
diff --git a/wpilibc/src/main/native/cpp/simulation/PWMSim.cpp b/wpilibc/src/main/native/cpp/simulation/PWMSim.cpp
index f5d69db..3fafa8e 100644
--- a/wpilibc/src/main/native/cpp/simulation/PWMSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/PWMSim.cpp
@@ -10,12 +10,16 @@
#include <hal/simulation/PWMData.h>
#include "frc/PWM.h"
+#include "frc/motorcontrol/PWMMotorController.h"
using namespace frc;
using namespace frc::sim;
PWMSim::PWMSim(const PWM& pwm) : m_index{pwm.GetChannel()} {}
+PWMSim::PWMSim(const PWMMotorController& motorctrl)
+ : m_index{motorctrl.GetChannel()} {}
+
PWMSim::PWMSim(int channel) : m_index{channel} {}
std::unique_ptr<CallbackStore> PWMSim::RegisterInitializedCallback(
diff --git a/wpilibc/src/main/native/cpp/simulation/PneumaticsBaseSim.cpp b/wpilibc/src/main/native/cpp/simulation/PneumaticsBaseSim.cpp
new file mode 100644
index 0000000..476d07a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/simulation/PneumaticsBaseSim.cpp
@@ -0,0 +1,33 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/simulation/PneumaticsBaseSim.h"
+
+#include "frc/Errors.h"
+#include "frc/PneumaticsModuleType.h"
+#include "frc/simulation/CTREPCMSim.h"
+#include "frc/simulation/REVPHSim.h"
+
+using namespace frc;
+using namespace frc::sim;
+
+PneumaticsBaseSim::PneumaticsBaseSim(int module) : m_index{module} {}
+
+PneumaticsBaseSim::PneumaticsBaseSim(const PneumaticsBase& module)
+ : m_index{module.GetModuleNumber()} {}
+
+std::shared_ptr<PneumaticsBaseSim> PneumaticsBaseSim::GetForType(
+ int module, PneumaticsModuleType type) {
+ switch (type) {
+ case PneumaticsModuleType::REVPH:
+ return std::make_shared<REVPHSim>(module);
+
+ case PneumaticsModuleType::CTREPCM:
+ return std::make_shared<CTREPCMSim>(module);
+
+ default:
+ throw FRC_MakeError(err::InvalidParameter, "{}",
+ static_cast<int>(module));
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/simulation/REVPHSim.cpp b/wpilibc/src/main/native/cpp/simulation/REVPHSim.cpp
index ca7384a..df7bc02 100644
--- a/wpilibc/src/main/native/cpp/simulation/REVPHSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/REVPHSim.cpp
@@ -14,12 +14,12 @@
using namespace frc;
using namespace frc::sim;
-REVPHSim::REVPHSim() : m_index{SensorUtil::GetDefaultREVPHModule()} {}
+REVPHSim::REVPHSim() : PneumaticsBaseSim{SensorUtil::GetDefaultREVPHModule()} {}
-REVPHSim::REVPHSim(int module) : m_index{module} {}
+REVPHSim::REVPHSim(int module) : PneumaticsBaseSim{module} {}
REVPHSim::REVPHSim(const PneumaticsBase& pneumatics)
- : m_index{pneumatics.GetModuleNumber()} {}
+ : PneumaticsBaseSim{pneumatics} {}
std::unique_ptr<CallbackStore> REVPHSim::RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify) {
diff --git a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp
index dc2b557..6d0f809 100644
--- a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp
@@ -39,7 +39,7 @@
}
units::volt_t RoboRioSim::GetVInVoltage() {
- return units::volt_t(HALSIM_GetRoboRioVInVoltage());
+ return units::volt_t{HALSIM_GetRoboRioVInVoltage()};
}
void RoboRioSim::SetVInVoltage(units::volt_t vInVoltage) {
@@ -56,7 +56,7 @@
}
units::ampere_t RoboRioSim::GetVInCurrent() {
- return units::ampere_t(HALSIM_GetRoboRioVInCurrent());
+ return units::ampere_t{HALSIM_GetRoboRioVInCurrent()};
}
void RoboRioSim::SetVInCurrent(units::ampere_t vInCurrent) {
@@ -73,7 +73,7 @@
}
units::volt_t RoboRioSim::GetUserVoltage6V() {
- return units::volt_t(HALSIM_GetRoboRioUserVoltage6V());
+ return units::volt_t{HALSIM_GetRoboRioUserVoltage6V()};
}
void RoboRioSim::SetUserVoltage6V(units::volt_t userVoltage6V) {
@@ -90,7 +90,7 @@
}
units::ampere_t RoboRioSim::GetUserCurrent6V() {
- return units::ampere_t(HALSIM_GetRoboRioUserCurrent6V());
+ return units::ampere_t{HALSIM_GetRoboRioUserCurrent6V()};
}
void RoboRioSim::SetUserCurrent6V(units::ampere_t userCurrent6V) {
@@ -124,7 +124,7 @@
}
units::volt_t RoboRioSim::GetUserVoltage5V() {
- return units::volt_t(HALSIM_GetRoboRioUserVoltage5V());
+ return units::volt_t{HALSIM_GetRoboRioUserVoltage5V()};
}
void RoboRioSim::SetUserVoltage5V(units::volt_t userVoltage5V) {
@@ -141,7 +141,7 @@
}
units::ampere_t RoboRioSim::GetUserCurrent5V() {
- return units::ampere_t(HALSIM_GetRoboRioUserCurrent5V());
+ return units::ampere_t{HALSIM_GetRoboRioUserCurrent5V()};
}
void RoboRioSim::SetUserCurrent5V(units::ampere_t userCurrent5V) {
@@ -175,7 +175,7 @@
}
units::volt_t RoboRioSim::GetUserVoltage3V3() {
- return units::volt_t(HALSIM_GetRoboRioUserVoltage3V3());
+ return units::volt_t{HALSIM_GetRoboRioUserVoltage3V3()};
}
void RoboRioSim::SetUserVoltage3V3(units::volt_t userVoltage3V3) {
@@ -192,7 +192,7 @@
}
units::ampere_t RoboRioSim::GetUserCurrent3V3() {
- return units::ampere_t(HALSIM_GetRoboRioUserCurrent3V3());
+ return units::ampere_t{HALSIM_GetRoboRioUserCurrent3V3()};
}
void RoboRioSim::SetUserCurrent3V3(units::ampere_t userCurrent3V3) {
@@ -277,13 +277,33 @@
}
units::volt_t RoboRioSim::GetBrownoutVoltage() {
- return units::volt_t(HALSIM_GetRoboRioBrownoutVoltage());
+ return units::volt_t{HALSIM_GetRoboRioBrownoutVoltage()};
}
void RoboRioSim::SetBrownoutVoltage(units::volt_t vInVoltage) {
HALSIM_SetRoboRioBrownoutVoltage(vInVoltage.value());
}
+std::string RoboRioSim::GetSerialNumber() {
+ char serialNum[9];
+ size_t len = HALSIM_GetRoboRioSerialNumber(serialNum, sizeof(serialNum));
+ return std::string(serialNum, len);
+}
+
+void RoboRioSim::SetSerialNumber(std::string_view serialNumber) {
+ HALSIM_SetRoboRioSerialNumber(serialNumber.data(), serialNumber.size());
+}
+
+std::string RoboRioSim::GetComments() {
+ char comments[65];
+ size_t len = HALSIM_GetRoboRioComments(comments, sizeof(comments));
+ return std::string(comments, len);
+}
+
+void RoboRioSim::SetComments(std::string_view comments) {
+ HALSIM_SetRoboRioComments(comments.data(), comments.size());
+}
+
void RoboRioSim::ResetData() {
HALSIM_ResetRoboRioData();
}
diff --git a/wpilibc/src/main/native/cpp/simulation/SingleJointedArmSim.cpp b/wpilibc/src/main/native/cpp/simulation/SingleJointedArmSim.cpp
index db56434..88e45c6 100644
--- a/wpilibc/src/main/native/cpp/simulation/SingleJointedArmSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/SingleJointedArmSim.cpp
@@ -18,13 +18,13 @@
SingleJointedArmSim::SingleJointedArmSim(
const LinearSystem<2, 1, 1>& system, const DCMotor& gearbox, double gearing,
units::meter_t armLength, units::radian_t minAngle,
- units::radian_t maxAngle, units::kilogram_t mass, bool simulateGravity,
+ units::radian_t maxAngle, units::kilogram_t armMass, bool simulateGravity,
const std::array<double, 1>& measurementStdDevs)
: LinearSystemSim<2, 1, 1>(system, measurementStdDevs),
m_r(armLength),
m_minAngle(minAngle),
m_maxAngle(maxAngle),
- m_mass(mass),
+ m_armMass(armMass),
m_gearbox(gearbox),
m_gearing(gearing),
m_simulateGravity(simulateGravity) {}
@@ -32,27 +32,27 @@
SingleJointedArmSim::SingleJointedArmSim(
const DCMotor& gearbox, double gearing, units::kilogram_square_meter_t moi,
units::meter_t armLength, units::radian_t minAngle,
- units::radian_t maxAngle, units::kilogram_t mass, bool simulateGravity,
+ units::radian_t maxAngle, units::kilogram_t armMass, bool simulateGravity,
const std::array<double, 1>& measurementStdDevs)
: SingleJointedArmSim(
LinearSystemId::SingleJointedArmSystem(gearbox, moi, gearing),
- gearbox, gearing, armLength, minAngle, maxAngle, mass,
+ gearbox, gearing, armLength, minAngle, maxAngle, armMass,
simulateGravity, measurementStdDevs) {}
bool SingleJointedArmSim::WouldHitLowerLimit(units::radian_t armAngle) const {
- return armAngle < m_minAngle;
+ return armAngle <= m_minAngle;
}
bool SingleJointedArmSim::WouldHitUpperLimit(units::radian_t armAngle) const {
- return armAngle > m_maxAngle;
+ return armAngle >= m_maxAngle;
}
bool SingleJointedArmSim::HasHitLowerLimit() const {
- return WouldHitLowerLimit(units::radian_t(m_y(0)));
+ return WouldHitLowerLimit(units::radian_t{m_y(0)});
}
bool SingleJointedArmSim::HasHitUpperLimit() const {
- return WouldHitUpperLimit(units::radian_t(m_y(0)));
+ return WouldHitUpperLimit(units::radian_t{m_y(0)});
}
units::radian_t SingleJointedArmSim::GetAngle() const {
@@ -72,12 +72,12 @@
}
void SingleJointedArmSim::SetInputVoltage(units::volt_t voltage) {
- SetInput(Eigen::Vector<double, 1>{voltage.value()});
+ SetInput(Vectord<1>{voltage.value()});
}
-Eigen::Vector<double, 2> SingleJointedArmSim::UpdateX(
- const Eigen::Vector<double, 2>& currentXhat,
- const Eigen::Vector<double, 1>& u, units::second_t dt) {
+Vectord<2> SingleJointedArmSim::UpdateX(const Vectord<2>& currentXhat,
+ const Vectord<1>& u,
+ units::second_t dt) {
// Horizontal case:
// Torque = F * r = I * alpha
// alpha = F * r / I
@@ -88,25 +88,24 @@
// We therefore find that f(x, u) = Ax + Bu + [[0] [m * g * r / I *
// std::cos(theta)]]
- Eigen::Vector<double, 2> updatedXhat = RKDP(
- [&](const auto& x, const auto& u) -> Eigen::Vector<double, 2> {
- Eigen::Vector<double, 2> xdot = m_plant.A() * x + m_plant.B() * u;
+ Vectord<2> updatedXhat = RKDP(
+ [&](const auto& x, const auto& u) -> Vectord<2> {
+ Vectord<2> xdot = m_plant.A() * x + m_plant.B() * u;
if (m_simulateGravity) {
- xdot += Eigen::Vector<double, 2>{
- 0.0, (m_mass * m_r * -9.8 * 3.0 / (m_mass * m_r * m_r) *
- std::cos(x(0)))
- .value()};
+ xdot += Vectord<2>{0.0, (m_armMass * m_r * -9.8 * 3.0 /
+ (m_armMass * m_r * m_r) * std::cos(x(0)))
+ .value()};
}
return xdot;
},
currentXhat, u, dt);
// Check for collisions.
- if (WouldHitLowerLimit(units::radian_t(updatedXhat(0)))) {
- return Eigen::Vector<double, 2>{m_minAngle.value(), 0.0};
- } else if (WouldHitUpperLimit(units::radian_t(updatedXhat(0)))) {
- return Eigen::Vector<double, 2>{m_maxAngle.value(), 0.0};
+ if (WouldHitLowerLimit(units::radian_t{updatedXhat(0)})) {
+ return Vectord<2>{m_minAngle.value(), 0.0};
+ } else if (WouldHitUpperLimit(units::radian_t{updatedXhat(0)})) {
+ return Vectord<2>{m_maxAngle.value(), 0.0};
}
return updatedXhat;
}
diff --git a/wpilibc/src/main/native/cpp/simulation/SolenoidSim.cpp b/wpilibc/src/main/native/cpp/simulation/SolenoidSim.cpp
new file mode 100644
index 0000000..29d8207
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/simulation/SolenoidSim.cpp
@@ -0,0 +1,41 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/simulation/SolenoidSim.h"
+
+#include "frc/PneumaticsBase.h"
+
+using namespace frc;
+using namespace frc::sim;
+
+SolenoidSim::SolenoidSim(std::shared_ptr<PneumaticsBaseSim> moduleSim,
+ int channel)
+ : m_module{std::move(moduleSim)}, m_channel{channel} {}
+
+SolenoidSim::SolenoidSim(int module, PneumaticsModuleType type, int channel)
+ : m_module{PneumaticsBaseSim::GetForType(module, type)},
+ m_channel{channel} {}
+
+SolenoidSim::SolenoidSim(PneumaticsModuleType type, int channel)
+ : m_module{PneumaticsBaseSim::GetForType(
+ PneumaticsBase::GetDefaultForType(type), type)},
+ m_channel{channel} {}
+
+bool SolenoidSim::GetOutput() const {
+ return m_module->GetSolenoidOutput(m_channel);
+}
+
+void SolenoidSim::SetOutput(bool output) {
+ m_module->SetSolenoidOutput(m_channel, output);
+}
+
+std::unique_ptr<CallbackStore> SolenoidSim::RegisterOutputCallback(
+ NotifyCallback callback, bool initialNotify) {
+ return m_module->RegisterSolenoidOutputCallback(m_channel, callback,
+ initialNotify);
+}
+
+std::shared_ptr<PneumaticsBaseSim> SolenoidSim::GetModuleSim() const {
+ return m_module;
+}
diff --git a/wpilibc/src/main/native/cpp/simulation/XboxControllerSim.cpp b/wpilibc/src/main/native/cpp/simulation/XboxControllerSim.cpp
index 393c41a..daf48b7 100644
--- a/wpilibc/src/main/native/cpp/simulation/XboxControllerSim.cpp
+++ b/wpilibc/src/main/native/cpp/simulation/XboxControllerSim.cpp
@@ -13,11 +13,13 @@
: GenericHIDSim{joystick} {
SetAxisCount(6);
SetButtonCount(10);
+ SetPOVCount(1);
}
XboxControllerSim::XboxControllerSim(int port) : GenericHIDSim{port} {
SetAxisCount(6);
SetButtonCount(10);
+ SetPOVCount(1);
}
void XboxControllerSim::SetLeftX(double value) {
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/Field2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/Field2d.cpp
index 2915a12..ec52e9c 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/Field2d.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/Field2d.cpp
@@ -4,6 +4,7 @@
#include "frc/smartdashboard/Field2d.h"
+#include <networktables/DoubleArrayTopic.h>
#include <networktables/NTSendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
@@ -57,7 +58,7 @@
std::make_unique<FieldObject2d>(name, FieldObject2d::private_init{}));
auto obj = m_objects.back().get();
if (m_table) {
- obj->m_entry = m_table->GetEntry(obj->m_name);
+ obj->m_entry = m_table->GetDoubleArrayTopic(obj->m_name).GetEntry({});
}
return obj;
}
@@ -74,7 +75,7 @@
m_table = builder.GetTable();
for (auto&& obj : m_objects) {
std::scoped_lock lock2(obj->m_mutex);
- obj->m_entry = m_table->GetEntry(obj->m_name);
+ obj->m_entry = m_table->GetDoubleArrayTopic(obj->m_name).GetEntry({});
obj->UpdateEntry(true);
}
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/FieldObject2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/FieldObject2d.cpp
index 93d6d7e..3895e87 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/FieldObject2d.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/FieldObject2d.cpp
@@ -6,9 +6,6 @@
#include <vector>
-#include <wpi/Endian.h>
-#include <wpi/MathExtras.h>
-
#include "frc/trajectory/Trajectory.h"
using namespace frc;
@@ -45,7 +42,7 @@
return m_poses[0];
}
-void FieldObject2d::SetPoses(wpi::span<const Pose2d> poses) {
+void FieldObject2d::SetPoses(std::span<const Pose2d> poses) {
std::scoped_lock lock(m_mutex);
m_poses.assign(poses.begin(), poses.end());
UpdateEntry();
@@ -71,7 +68,7 @@
return std::vector<Pose2d>(m_poses.begin(), m_poses.end());
}
-wpi::span<const Pose2d> FieldObject2d::GetPoses(
+std::span<const Pose2d> FieldObject2d::GetPoses(
wpi::SmallVectorImpl<Pose2d>& out) const {
std::scoped_lock lock(m_mutex);
UpdateFromEntry();
@@ -83,41 +80,17 @@
if (!m_entry) {
return;
}
- if (m_poses.size() < (255 / 3)) {
- wpi::SmallVector<double, 9> arr;
- for (auto&& pose : m_poses) {
- auto& translation = pose.Translation();
- arr.push_back(translation.X().value());
- arr.push_back(translation.Y().value());
- arr.push_back(pose.Rotation().Degrees().value());
- }
- if (setDefault) {
- m_entry.SetDefaultDoubleArray(arr);
- } else {
- m_entry.ForceSetDoubleArray(arr);
- }
+ wpi::SmallVector<double, 9> arr;
+ for (auto&& pose : m_poses) {
+ auto& translation = pose.Translation();
+ arr.push_back(translation.X().value());
+ arr.push_back(translation.Y().value());
+ arr.push_back(pose.Rotation().Degrees().value());
+ }
+ if (setDefault) {
+ m_entry.SetDefault(arr);
} else {
- // send as raw array of doubles if too big for NT array
- std::vector<char> arr;
- arr.resize(m_poses.size() * 3 * 8);
- char* p = arr.data();
- for (auto&& pose : m_poses) {
- auto& translation = pose.Translation();
- wpi::support::endian::write64be(
- p, wpi::DoubleToBits(translation.X().value()));
- p += 8;
- wpi::support::endian::write64be(
- p, wpi::DoubleToBits(translation.Y().value()));
- p += 8;
- wpi::support::endian::write64be(
- p, wpi::DoubleToBits(pose.Rotation().Degrees().value()));
- p += 8;
- }
- if (setDefault) {
- m_entry.SetDefaultRaw({arr.data(), arr.size()});
- } else {
- m_entry.ForceSetRaw({arr.data(), arr.size()});
- }
+ m_entry.Set(arr);
}
}
@@ -125,46 +98,15 @@
if (!m_entry) {
return;
}
- auto val = m_entry.GetValue();
- if (!val) {
+ auto arr = m_entry.Get();
+ auto size = arr.size();
+ if ((size % 3) != 0) {
return;
}
-
- if (val->IsDoubleArray()) {
- auto arr = val->GetDoubleArray();
- auto size = arr.size();
- if ((size % 3) != 0) {
- return;
- }
- m_poses.resize(size / 3);
- for (size_t i = 0; i < size / 3; ++i) {
- m_poses[i] =
- Pose2d{units::meter_t{arr[i * 3 + 0]}, units::meter_t{arr[i * 3 + 1]},
- Rotation2d{units::degree_t{arr[i * 3 + 2]}}};
- }
- } else if (val->IsRaw()) {
- // treat it simply as an array of doubles
- std::string_view data = val->GetRaw();
-
- // must be triples of doubles
- auto size = data.size();
- if ((size % (3 * 8)) != 0) {
- return;
- }
- m_poses.resize(size / (3 * 8));
- const char* p = data.data();
- for (size_t i = 0; i < size / (3 * 8); ++i) {
- double x = wpi::BitsToDouble(
- wpi::support::endian::readNext<uint64_t, wpi::support::big,
- wpi::support::unaligned>(p));
- double y = wpi::BitsToDouble(
- wpi::support::endian::readNext<uint64_t, wpi::support::big,
- wpi::support::unaligned>(p));
- double rot = wpi::BitsToDouble(
- wpi::support::endian::readNext<uint64_t, wpi::support::big,
- wpi::support::unaligned>(p));
- m_poses[i] = Pose2d{units::meter_t{x}, units::meter_t{y},
- Rotation2d{units::degree_t{rot}}};
- }
+ m_poses.resize(size / 3);
+ for (size_t i = 0; i < size / 3; ++i) {
+ m_poses[i] =
+ Pose2d{units::meter_t{arr[i * 3 + 0]}, units::meter_t{arr[i * 3 + 1]},
+ units::degree_t{arr[i * 3 + 2]}};
}
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp
index bfa827a..355cbc6 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp
@@ -5,13 +5,14 @@
#include "frc/smartdashboard/Mechanism2d.h"
#include <cstdio>
+#include <string_view>
#include <networktables/NTSendableBuilder.h>
using namespace frc;
-static constexpr char kBackgroundColor[] = "backgroundColor";
-static constexpr char kDims[] = "dims";
+static constexpr std::string_view kBackgroundColor = "backgroundColor";
+static constexpr std::string_view kDims = "dims";
Mechanism2d::Mechanism2d(double width, double height,
const Color8Bit& backgroundColor)
@@ -34,10 +35,9 @@
}
void Mechanism2d::SetBackgroundColor(const Color8Bit& color) {
- std::snprintf(m_color, sizeof(m_color), "#%02X%02X%02X", color.red,
- color.green, color.blue);
- if (m_table) {
- m_table->GetEntry(kBackgroundColor).SetString(m_color);
+ m_color = color.HexString();
+ if (m_colorPub) {
+ m_colorPub.Set(m_color);
}
}
@@ -46,8 +46,10 @@
std::scoped_lock lock(m_mutex);
m_table = builder.GetTable();
- m_table->GetEntry(kDims).SetDoubleArray({m_width, m_height});
- m_table->GetEntry(kBackgroundColor).SetString(m_color);
+ m_dimsPub = m_table->GetDoubleArrayTopic(kDims).Publish();
+ m_dimsPub.Set({{m_width, m_height}});
+ m_colorPub = m_table->GetStringTopic(kBackgroundColor).Publish();
+ m_colorPub.Set(m_color);
for (const auto& entry : m_roots) {
const auto& root = entry.getValue().get();
root->Update(m_table->GetSubTable(entry.getKey()));
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/MechanismLigament2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/MechanismLigament2d.cpp
index b49bc99..a43aa16 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/MechanismLigament2d.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/MechanismLigament2d.cpp
@@ -12,7 +12,7 @@
units::degree_t angle,
double lineWeight,
const frc::Color8Bit& color)
- : MechanismObject2d(name),
+ : MechanismObject2d{name},
m_length{length},
m_angle{angle.value()},
m_weight{lineWeight} {
@@ -21,38 +21,48 @@
void MechanismLigament2d::UpdateEntries(
std::shared_ptr<nt::NetworkTable> table) {
- table->GetEntry(".type").SetString("line");
+ m_typePub = table->GetStringTopic(".type").Publish();
+ m_typePub.Set("line");
- m_colorEntry = table->GetEntry("color");
- m_angleEntry = table->GetEntry("angle");
- m_weightEntry = table->GetEntry("weight");
- m_lengthEntry = table->GetEntry("length");
- Flush();
+ m_colorEntry = table->GetStringTopic("color").GetEntry("");
+ m_colorEntry.Set(m_color);
+ m_angleEntry = table->GetDoubleTopic("angle").GetEntry(0.0);
+ m_angleEntry.Set(m_angle);
+ m_weightEntry = table->GetDoubleTopic("weight").GetEntry(0.0);
+ m_weightEntry.Set(m_weight);
+ m_lengthEntry = table->GetDoubleTopic("length").GetEntry(0.0);
+ m_lengthEntry.Set(m_length);
}
void MechanismLigament2d::SetColor(const Color8Bit& color) {
std::scoped_lock lock(m_mutex);
std::snprintf(m_color, sizeof(m_color), "#%02X%02X%02X", color.red,
color.green, color.blue);
- Flush();
+ if (m_colorEntry) {
+ m_colorEntry.Set(m_color);
+ }
}
void MechanismLigament2d::SetAngle(units::degree_t angle) {
std::scoped_lock lock(m_mutex);
m_angle = angle.value();
- Flush();
+ if (m_angleEntry) {
+ m_angleEntry.Set(m_angle);
+ }
}
void MechanismLigament2d::SetLineWeight(double lineWidth) {
std::scoped_lock lock(m_mutex);
m_weight = lineWidth;
- Flush();
+ if (m_weightEntry) {
+ m_weightEntry.Set(m_weight);
+ }
}
Color8Bit MechanismLigament2d::GetColor() {
std::scoped_lock lock(m_mutex);
if (m_colorEntry) {
- auto color = m_colorEntry.GetString("");
+ auto color = m_colorEntry.Get();
std::strncpy(m_color, color.c_str(), sizeof(m_color));
m_color[sizeof(m_color) - 1] = '\0';
}
@@ -64,7 +74,7 @@
double MechanismLigament2d::GetAngle() {
std::scoped_lock lock(m_mutex);
if (m_angleEntry) {
- m_angle = m_angleEntry.GetDouble(0.0);
+ m_angle = m_angleEntry.Get();
}
return m_angle;
}
@@ -72,7 +82,7 @@
double MechanismLigament2d::GetLength() {
std::scoped_lock lock(m_mutex);
if (m_lengthEntry) {
- m_length = m_lengthEntry.GetDouble(0.0);
+ m_length = m_lengthEntry.Get();
}
return m_length;
}
@@ -80,7 +90,7 @@
double MechanismLigament2d::GetLineWeight() {
std::scoped_lock lock(m_mutex);
if (m_weightEntry) {
- m_weight = m_weightEntry.GetDouble(0.0);
+ m_weight = m_weightEntry.Get();
}
return m_weight;
}
@@ -88,16 +98,7 @@
void MechanismLigament2d::SetLength(double length) {
std::scoped_lock lock(m_mutex);
m_length = length;
- Flush();
-}
-
-#define SAFE_WRITE(data, Type) \
- if (m_##data##Entry) { \
- m_##data##Entry.Set##Type(m_##data); \
+ if (m_lengthEntry) {
+ m_lengthEntry.Set(length);
}
-void MechanismLigament2d::Flush() {
- SAFE_WRITE(color, String)
- SAFE_WRITE(angle, Double)
- SAFE_WRITE(length, Double)
- SAFE_WRITE(weight, Double)
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/MechanismRoot2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/MechanismRoot2d.cpp
index 637b24b..a40f5ee 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/MechanismRoot2d.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/MechanismRoot2d.cpp
@@ -10,7 +10,7 @@
MechanismRoot2d::MechanismRoot2d(std::string_view name, double x, double y,
const private_init&)
- : MechanismObject2d(name), m_x{x}, m_y{y} {}
+ : MechanismObject2d{name}, m_x{x}, m_y{y} {}
void MechanismRoot2d::SetPosition(double x, double y) {
std::scoped_lock lock(m_mutex);
@@ -20,16 +20,16 @@
}
void MechanismRoot2d::UpdateEntries(std::shared_ptr<nt::NetworkTable> table) {
- m_xEntry = table->GetEntry("x");
- m_yEntry = table->GetEntry("y");
+ m_xPub = table->GetDoubleTopic("x").Publish();
+ m_yPub = table->GetDoubleTopic("y").Publish();
Flush();
}
inline void MechanismRoot2d::Flush() {
- if (m_xEntry) {
- m_xEntry.SetDouble(m_x);
+ if (m_xPub) {
+ m_xPub.Set(m_x);
}
- if (m_yEntry) {
- m_yEntry.SetDouble(m_y);
+ if (m_yPub) {
+ m_yPub.Set(m_y);
}
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp
index 48af198..79b0e6e 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp
@@ -4,16 +4,38 @@
#include "frc/smartdashboard/SendableBuilderImpl.h"
+#include <networktables/BooleanArrayTopic.h>
+#include <networktables/BooleanTopic.h>
+#include <networktables/DoubleArrayTopic.h>
+#include <networktables/DoubleTopic.h>
+#include <networktables/FloatArrayTopic.h>
+#include <networktables/FloatTopic.h>
+#include <networktables/IntegerArrayTopic.h>
+#include <networktables/IntegerTopic.h>
+#include <networktables/RawTopic.h>
+#include <networktables/StringArrayTopic.h>
#include <ntcore_cpp.h>
-#include <wpi/SmallString.h>
+#include <wpi/SmallVector.h>
#include "frc/smartdashboard/SmartDashboard.h"
using namespace frc;
+template <typename Topic>
+void SendableBuilderImpl::PropertyImpl<Topic>::Update(bool controllable,
+ int64_t time) {
+ if (controllable && sub && updateLocal) {
+ updateLocal(sub);
+ }
+ if (pub && updateNetwork) {
+ updateNetwork(pub, time);
+ }
+}
+
void SendableBuilderImpl::SetTable(std::shared_ptr<nt::NetworkTable> table) {
m_table = table;
- m_controllableEntry = table->GetEntry(".controllable");
+ m_controllablePublisher = table->GetBooleanTopic(".controllable").Publish();
+ m_controllablePublisher.SetDefault(false);
}
std::shared_ptr<nt::NetworkTable> SendableBuilderImpl::GetTable() {
@@ -31,9 +53,7 @@
void SendableBuilderImpl::Update() {
uint64_t time = nt::Now();
for (auto& property : m_properties) {
- if (property.update) {
- property.update(property.entry, time);
- }
+ property->Update(m_controllable, time);
}
for (auto& updateTable : m_updateTables) {
updateTable();
@@ -41,20 +61,16 @@
}
void SendableBuilderImpl::StartListeners() {
- for (auto& property : m_properties) {
- property.StartListener();
- }
- if (m_controllableEntry) {
- m_controllableEntry.SetBoolean(true);
+ m_controllable = true;
+ if (m_controllablePublisher) {
+ m_controllablePublisher.Set(true);
}
}
void SendableBuilderImpl::StopListeners() {
- for (auto& property : m_properties) {
- property.StopListener();
- }
- if (m_controllableEntry) {
- m_controllableEntry.SetBoolean(false);
+ m_controllable = false;
+ if (m_controllablePublisher) {
+ m_controllablePublisher.Set(false);
}
}
@@ -77,11 +93,17 @@
}
void SendableBuilderImpl::SetSmartDashboardType(std::string_view type) {
- m_table->GetEntry(".type").SetString(type);
+ if (!m_typePublisher) {
+ m_typePublisher = m_table->GetStringTopic(".type").Publish();
+ }
+ m_typePublisher.Set(type);
}
void SendableBuilderImpl::SetActuator(bool value) {
- m_table->GetEntry(".actuator").SetBoolean(value);
+ if (!m_actuatorPublisher) {
+ m_actuatorPublisher = m_table->GetBooleanTopic(".actuator").Publish();
+ }
+ m_actuatorPublisher.Set(value);
m_actuator = value;
}
@@ -89,357 +111,229 @@
m_safeState = func;
}
-void SendableBuilderImpl::SetUpdateTable(std::function<void()> func) {
+void SendableBuilderImpl::SetUpdateTable(wpi::unique_function<void()> func) {
m_updateTables.emplace_back(std::move(func));
}
-nt::NetworkTableEntry SendableBuilderImpl::GetEntry(std::string_view key) {
- return m_table->GetEntry(key);
+nt::Topic SendableBuilderImpl::GetTopic(std::string_view key) {
+ return m_table->GetTopic(key);
+}
+
+template <typename Topic, typename Getter, typename Setter>
+void SendableBuilderImpl::AddPropertyImpl(Topic topic, Getter getter,
+ Setter setter) {
+ auto prop = std::make_unique<PropertyImpl<Topic>>();
+ if (getter) {
+ prop->pub = topic.Publish();
+ prop->updateNetwork = [=](auto& pub, int64_t time) {
+ pub.Set(getter(), time);
+ };
+ }
+ if (setter) {
+ prop->sub =
+ topic.Subscribe({}, {.excludePublisher = prop->pub.GetHandle()});
+ prop->updateLocal = [=](auto& sub) {
+ for (auto&& val : sub.ReadQueue()) {
+ setter(val.value);
+ }
+ };
+ }
+ m_properties.emplace_back(std::move(prop));
}
void SendableBuilderImpl::AddBooleanProperty(std::string_view key,
std::function<bool()> getter,
std::function<void(bool)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeBoolean(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsBoolean()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetBoolean()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ AddPropertyImpl(m_table->GetBooleanTopic(key), std::move(getter),
+ std::move(setter));
+}
+
+void SendableBuilderImpl::AddIntegerProperty(
+ std::string_view key, std::function<int64_t()> getter,
+ std::function<void(int64_t)> setter) {
+ AddPropertyImpl(m_table->GetIntegerTopic(key), std::move(getter),
+ std::move(setter));
+}
+
+void SendableBuilderImpl::AddFloatProperty(std::string_view key,
+ std::function<float()> getter,
+ std::function<void(float)> setter) {
+ AddPropertyImpl(m_table->GetFloatTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddDoubleProperty(
std::string_view key, std::function<double()> getter,
std::function<void(double)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeDouble(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsDouble()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetDouble()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ AddPropertyImpl(m_table->GetDoubleTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddStringProperty(
std::string_view key, std::function<std::string()> getter,
std::function<void(std::string_view)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeString(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsString()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetString()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ AddPropertyImpl(m_table->GetStringTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddBooleanArrayProperty(
std::string_view key, std::function<std::vector<int>()> getter,
- std::function<void(wpi::span<const int>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeBooleanArray(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsBooleanArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetBooleanArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<void(std::span<const int>)> setter) {
+ AddPropertyImpl(m_table->GetBooleanArrayTopic(key), std::move(getter),
+ std::move(setter));
+}
+
+void SendableBuilderImpl::AddIntegerArrayProperty(
+ std::string_view key, std::function<std::vector<int64_t>()> getter,
+ std::function<void(std::span<const int64_t>)> setter) {
+ AddPropertyImpl(m_table->GetIntegerArrayTopic(key), std::move(getter),
+ std::move(setter));
+}
+
+void SendableBuilderImpl::AddFloatArrayProperty(
+ std::string_view key, std::function<std::vector<float>()> getter,
+ std::function<void(std::span<const float>)> setter) {
+ AddPropertyImpl(m_table->GetFloatArrayTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddDoubleArrayProperty(
std::string_view key, std::function<std::vector<double>()> getter,
- std::function<void(wpi::span<const double>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeDoubleArray(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsDoubleArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetDoubleArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<void(std::span<const double>)> setter) {
+ AddPropertyImpl(m_table->GetDoubleArrayTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddStringArrayProperty(
std::string_view key, std::function<std::vector<std::string>()> getter,
- std::function<void(wpi::span<const std::string>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeStringArray(getter(), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsStringArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetStringArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<void(std::span<const std::string>)> setter) {
+ AddPropertyImpl(m_table->GetStringArrayTopic(key), std::move(getter),
+ std::move(setter));
}
void SendableBuilderImpl::AddRawProperty(
- std::string_view key, std::function<std::string()> getter,
- std::function<void(std::string_view)> setter) {
- m_properties.emplace_back(*m_table, key);
+ std::string_view key, std::string_view typeString,
+ std::function<std::vector<uint8_t>()> getter,
+ std::function<void(std::span<const uint8_t>)> setter) {
+ auto topic = m_table->GetRawTopic(key);
+ auto prop = std::make_unique<PropertyImpl<nt::RawTopic>>();
if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(nt::Value::MakeRaw(getter(), time));
+ prop->pub = topic.Publish(typeString);
+ prop->updateNetwork = [=](auto& pub, int64_t time) {
+ pub.Set(getter(), time);
};
}
if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsRaw()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetRaw()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ prop->sub = topic.Subscribe(typeString, {},
+ {.excludePublisher = prop->pub.GetHandle()});
+ prop->updateLocal = [=](auto& sub) {
+ for (auto&& val : sub.ReadQueue()) {
+ setter(val.value);
+ }
};
}
+ m_properties.emplace_back(std::move(prop));
}
-void SendableBuilderImpl::AddValueProperty(
- std::string_view key, std::function<std::shared_ptr<nt::Value>()> getter,
- std::function<void(std::shared_ptr<nt::Value>)> setter) {
- m_properties.emplace_back(*m_table, key);
+template <typename T, size_t Size, typename Topic, typename Getter,
+ typename Setter>
+void SendableBuilderImpl::AddSmallPropertyImpl(Topic topic, Getter getter,
+ Setter setter) {
+ auto prop = std::make_unique<PropertyImpl<Topic>>();
if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- entry.SetValue(getter());
+ prop->pub = topic.Publish();
+ prop->updateNetwork = [=](auto& pub, int64_t time) {
+ wpi::SmallVector<T, Size> buf;
+ pub.Set(getter(buf), time);
};
}
if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- SmartDashboard::PostListenerTask([=] { setter(event.value); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ prop->sub =
+ topic.Subscribe({}, {.excludePublisher = prop->pub.GetHandle()});
+ prop->updateLocal = [=](auto& sub) {
+ for (auto&& val : sub.ReadQueue()) {
+ setter(val.value);
+ }
};
}
+ m_properties.emplace_back(std::move(prop));
}
void SendableBuilderImpl::AddSmallStringProperty(
std::string_view key,
std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
std::function<void(std::string_view)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- wpi::SmallString<128> buf;
- entry.SetValue(nt::Value::MakeString(getter(buf), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsString()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetString()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ AddSmallPropertyImpl<char, 128>(m_table->GetStringTopic(key),
+ std::move(getter), std::move(setter));
}
void SendableBuilderImpl::AddSmallBooleanArrayProperty(
std::string_view key,
- std::function<wpi::span<const int>(wpi::SmallVectorImpl<int>& buf)> getter,
- std::function<void(wpi::span<const int>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- wpi::SmallVector<int, 16> buf;
- entry.SetValue(nt::Value::MakeBooleanArray(getter(buf), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsBooleanArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetBooleanArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<std::span<const int>(wpi::SmallVectorImpl<int>& buf)> getter,
+ std::function<void(std::span<const int>)> setter) {
+ AddSmallPropertyImpl<int, 16>(m_table->GetBooleanArrayTopic(key),
+ std::move(getter), std::move(setter));
+}
+
+void SendableBuilderImpl::AddSmallIntegerArrayProperty(
+ std::string_view key,
+ std::function<std::span<const int64_t>(wpi::SmallVectorImpl<int64_t>& buf)>
+ getter,
+ std::function<void(std::span<const int64_t>)> setter) {
+ AddSmallPropertyImpl<int64_t, 16>(m_table->GetIntegerArrayTopic(key),
+ std::move(getter), std::move(setter));
+}
+
+void SendableBuilderImpl::AddSmallFloatArrayProperty(
+ std::string_view key,
+ std::function<std::span<const float>(wpi::SmallVectorImpl<float>& buf)>
+ getter,
+ std::function<void(std::span<const float>)> setter) {
+ AddSmallPropertyImpl<float, 16>(m_table->GetFloatArrayTopic(key),
+ std::move(getter), std::move(setter));
}
void SendableBuilderImpl::AddSmallDoubleArrayProperty(
std::string_view key,
- std::function<wpi::span<const double>(wpi::SmallVectorImpl<double>& buf)>
+ std::function<std::span<const double>(wpi::SmallVectorImpl<double>& buf)>
getter,
- std::function<void(wpi::span<const double>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- wpi::SmallVector<double, 16> buf;
- entry.SetValue(nt::Value::MakeDoubleArray(getter(buf), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsDoubleArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetDoubleArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<void(std::span<const double>)> setter) {
+ AddSmallPropertyImpl<double, 16>(m_table->GetDoubleArrayTopic(key),
+ std::move(getter), std::move(setter));
}
void SendableBuilderImpl::AddSmallStringArrayProperty(
std::string_view key,
std::function<
- wpi::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+ std::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
getter,
- std::function<void(wpi::span<const std::string>)> setter) {
- m_properties.emplace_back(*m_table, key);
- if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- wpi::SmallVector<std::string, 16> buf;
- entry.SetValue(nt::Value::MakeStringArray(getter(buf), time));
- };
- }
- if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsStringArray()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetStringArray()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
- };
- }
+ std::function<void(std::span<const std::string>)> setter) {
+ AddSmallPropertyImpl<std::string, 16>(m_table->GetStringArrayTopic(key),
+ std::move(getter), std::move(setter));
}
void SendableBuilderImpl::AddSmallRawProperty(
- std::string_view key,
- std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
- std::function<void(std::string_view)> setter) {
- m_properties.emplace_back(*m_table, key);
+ std::string_view key, std::string_view typeString,
+ std::function<std::span<uint8_t>(wpi::SmallVectorImpl<uint8_t>& buf)>
+ getter,
+ std::function<void(std::span<const uint8_t>)> setter) {
+ auto topic = m_table->GetRawTopic(key);
+ auto prop = std::make_unique<PropertyImpl<nt::RawTopic>>();
if (getter) {
- m_properties.back().update = [=](nt::NetworkTableEntry entry,
- uint64_t time) {
- wpi::SmallVector<char, 128> buf;
- entry.SetValue(nt::Value::MakeRaw(getter(buf), time));
+ prop->pub = topic.Publish(typeString);
+ prop->updateNetwork = [=](auto& pub, int64_t time) {
+ wpi::SmallVector<uint8_t, 128> buf;
+ pub.Set(getter(buf), time);
};
}
if (setter) {
- m_properties.back().createListener =
- [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
- return entry.AddListener(
- [=](const nt::EntryNotification& event) {
- if (!event.value->IsRaw()) {
- return;
- }
- SmartDashboard::PostListenerTask(
- [=] { setter(event.value->GetRaw()); });
- },
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ prop->sub = topic.Subscribe(typeString, {},
+ {.excludePublisher = prop->pub.GetHandle()});
+ prop->updateLocal = [=](auto& sub) {
+ for (auto&& val : sub.ReadQueue()) {
+ setter(val.value);
+ }
};
}
+ m_properties.emplace_back(std::move(prop));
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp
index 550d40c..9fa5b69 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp
@@ -19,7 +19,8 @@
m_defaultChoice(std::move(oth.m_defaultChoice)),
m_selected(std::move(oth.m_selected)),
m_haveSelected(std::move(oth.m_haveSelected)),
- m_activeEntries(std::move(oth.m_activeEntries)),
+ m_instancePubs(std::move(oth.m_instancePubs)),
+ m_activePubs(std::move(oth.m_activePubs)),
m_instance(std::move(oth.m_instance)) {}
SendableChooserBase& SendableChooserBase::operator=(SendableChooserBase&& oth) {
@@ -28,7 +29,8 @@
m_defaultChoice = std::move(oth.m_defaultChoice);
m_selected = std::move(oth.m_selected);
m_haveSelected = std::move(oth.m_haveSelected);
- m_activeEntries = std::move(oth.m_activeEntries);
+ m_instancePubs = std::move(oth.m_instancePubs);
+ m_activePubs = std::move(oth.m_activePubs);
m_instance = std::move(oth.m_instance);
return *this;
}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp
index 5088394..e6991d4 100644
--- a/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp
@@ -70,29 +70,13 @@
return GetInstance().table->GetEntry(key).IsPersistent();
}
-void SmartDashboard::SetFlags(std::string_view key, unsigned int flags) {
- GetInstance().table->GetEntry(key).SetFlags(flags);
-}
-
-void SmartDashboard::ClearFlags(std::string_view key, unsigned int flags) {
- GetInstance().table->GetEntry(key).ClearFlags(flags);
-}
-
-unsigned int SmartDashboard::GetFlags(std::string_view key) {
- return GetInstance().table->GetEntry(key).GetFlags();
-}
-
-void SmartDashboard::Delete(std::string_view key) {
- GetInstance().table->Delete(key);
-}
-
nt::NetworkTableEntry SmartDashboard::GetEntry(std::string_view key) {
return GetInstance().table->GetEntry(key);
}
void SmartDashboard::PutData(std::string_view key, wpi::Sendable* data) {
if (!data) {
- throw FRC_MakeError(err::NullParameter, "{}", "value");
+ throw FRC_MakeError(err::NullParameter, "value");
}
auto& inst = GetInstance();
std::scoped_lock lock(inst.tablesToDataMutex);
@@ -112,7 +96,7 @@
void SmartDashboard::PutData(wpi::Sendable* value) {
if (!value) {
- throw FRC_MakeError(err::NullParameter, "{}", "value");
+ throw FRC_MakeError(err::NullParameter, "value");
}
auto name = wpi::SendableRegistry::GetName(value);
if (!name.empty()) {
@@ -173,76 +157,77 @@
}
bool SmartDashboard::PutBooleanArray(std::string_view key,
- wpi::span<const int> value) {
+ std::span<const int> value) {
return GetInstance().table->GetEntry(key).SetBooleanArray(value);
}
bool SmartDashboard::SetDefaultBooleanArray(std::string_view key,
- wpi::span<const int> defaultValue) {
+ std::span<const int> defaultValue) {
return GetInstance().table->GetEntry(key).SetDefaultBooleanArray(
defaultValue);
}
std::vector<int> SmartDashboard::GetBooleanArray(
- std::string_view key, wpi::span<const int> defaultValue) {
+ std::string_view key, std::span<const int> defaultValue) {
return GetInstance().table->GetEntry(key).GetBooleanArray(defaultValue);
}
bool SmartDashboard::PutNumberArray(std::string_view key,
- wpi::span<const double> value) {
+ std::span<const double> value) {
return GetInstance().table->GetEntry(key).SetDoubleArray(value);
}
bool SmartDashboard::SetDefaultNumberArray(
- std::string_view key, wpi::span<const double> defaultValue) {
+ std::string_view key, std::span<const double> defaultValue) {
return GetInstance().table->GetEntry(key).SetDefaultDoubleArray(defaultValue);
}
std::vector<double> SmartDashboard::GetNumberArray(
- std::string_view key, wpi::span<const double> defaultValue) {
+ std::string_view key, std::span<const double> defaultValue) {
return GetInstance().table->GetEntry(key).GetDoubleArray(defaultValue);
}
bool SmartDashboard::PutStringArray(std::string_view key,
- wpi::span<const std::string> value) {
+ std::span<const std::string> value) {
return GetInstance().table->GetEntry(key).SetStringArray(value);
}
bool SmartDashboard::SetDefaultStringArray(
- std::string_view key, wpi::span<const std::string> defaultValue) {
+ std::string_view key, std::span<const std::string> defaultValue) {
return GetInstance().table->GetEntry(key).SetDefaultStringArray(defaultValue);
}
std::vector<std::string> SmartDashboard::GetStringArray(
- std::string_view key, wpi::span<const std::string> defaultValue) {
+ std::string_view key, std::span<const std::string> defaultValue) {
return GetInstance().table->GetEntry(key).GetStringArray(defaultValue);
}
-bool SmartDashboard::PutRaw(std::string_view key, std::string_view value) {
+bool SmartDashboard::PutRaw(std::string_view key,
+ std::span<const uint8_t> value) {
return GetInstance().table->GetEntry(key).SetRaw(value);
}
bool SmartDashboard::SetDefaultRaw(std::string_view key,
- std::string_view defaultValue) {
+ std::span<const uint8_t> defaultValue) {
return GetInstance().table->GetEntry(key).SetDefaultRaw(defaultValue);
}
-std::string SmartDashboard::GetRaw(std::string_view key,
- std::string_view defaultValue) {
+std::vector<uint8_t> SmartDashboard::GetRaw(
+ std::string_view key, std::span<const uint8_t> defaultValue) {
return GetInstance().table->GetEntry(key).GetRaw(defaultValue);
}
bool SmartDashboard::PutValue(std::string_view keyName,
- std::shared_ptr<nt::Value> value) {
+ const nt::Value& value) {
return GetInstance().table->GetEntry(keyName).SetValue(value);
}
bool SmartDashboard::SetDefaultValue(std::string_view key,
- std::shared_ptr<nt::Value> defaultValue) {
+ const nt::Value& defaultValue) {
return GetInstance().table->GetEntry(key).SetDefaultValue(defaultValue);
}
-std::shared_ptr<nt::Value> SmartDashboard::GetValue(std::string_view keyName) {
+nt::Value SmartDashboard::GetValue(std::string_view keyName) {
return GetInstance().table->GetEntry(keyName).GetValue();
}
diff --git a/wpilibc/src/main/native/cpp/util/Color.cpp b/wpilibc/src/main/native/cpp/util/Color.cpp
new file mode 100644
index 0000000..e3adaf2
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/util/Color.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/util/Color.h"
+
+#include <fmt/format.h>
+
+using namespace frc;
+
+std::string Color::HexString() const {
+ return fmt::format("#{:02X}{:02X}{:02X}", static_cast<int>(255.0 * red),
+ static_cast<int>(255.0 * green),
+ static_cast<int>(255.0 * blue));
+}
diff --git a/wpilibc/src/main/native/cpp/util/Color8Bit.cpp b/wpilibc/src/main/native/cpp/util/Color8Bit.cpp
new file mode 100644
index 0000000..af200a2
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/util/Color8Bit.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/util/Color8Bit.h"
+
+#include <fmt/format.h>
+
+using namespace frc;
+
+std::string Color8Bit::HexString() const {
+ return fmt::format("#{:02X}{:02X}{:02X}", red, green, blue);
+}
diff --git a/wpilibc/src/main/native/cppcs/RobotBase.cpp b/wpilibc/src/main/native/cppcs/RobotBase.cpp
index 3433a02..535d20d 100644
--- a/wpilibc/src/main/native/cppcs/RobotBase.cpp
+++ b/wpilibc/src/main/native/cppcs/RobotBase.cpp
@@ -45,7 +45,7 @@
HALUsageReporting::kLanguage_CPlusPlus, 0, GetWPILibVersion());
if (!frc::Notifier::SetHALThreadPriority(true, 40)) {
- FRC_ReportError(warn::Warning, "{}",
+ FRC_ReportError(warn::Warning,
"Setting HAL Notifier RT priority to 40 failed\n");
}
@@ -192,18 +192,10 @@
return DriverStation::IsAutonomousEnabled();
}
-bool RobotBase::IsOperatorControl() const {
- return DriverStation::IsTeleop();
-}
-
bool RobotBase::IsTeleop() const {
return DriverStation::IsTeleop();
}
-bool RobotBase::IsOperatorControlEnabled() const {
- return DriverStation::IsTeleopEnabled();
-}
-
bool RobotBase::IsTeleopEnabled() const {
return DriverStation::IsTeleopEnabled();
}
@@ -212,10 +204,6 @@
return DriverStation::IsTest();
}
-bool RobotBase::IsNewDataAvailable() const {
- return DriverStation::IsNewControlData();
-}
-
std::thread::id RobotBase::GetThreadId() {
return m_threadId;
}
@@ -231,13 +219,26 @@
SetupMathShared();
auto inst = nt::NetworkTableInstance::GetDefault();
- inst.SetNetworkIdentity("Robot");
+ // subscribe to "" to force persistent values to progagate to local
+ nt::SubscribeMultiple(inst.GetHandle(), {{std::string_view{}}});
#ifdef __FRC_ROBORIO__
- inst.StartServer("/home/lvuser/networktables.ini");
+ inst.StartServer("/home/lvuser/networktables.json");
#else
inst.StartServer();
#endif
+ // wait for the NT server to actually start
+ int count = 0;
+ while ((inst.GetNetworkMode() & NT_NET_MODE_STARTING) != 0) {
+ using namespace std::chrono_literals;
+ std::this_thread::sleep_for(10ms);
+ ++count;
+ if (count > 100) {
+ fmt::print(stderr, "timed out while waiting for NT server to start\n");
+ break;
+ }
+ }
+
SmartDashboard::init();
if (IsReal()) {
@@ -251,14 +252,9 @@
}
}
- // Call DriverStation::InDisabled() to kick off DS thread
- DriverStation::InDisabled(true);
+ // Call DriverStation::RefreshData() to kick things off
+ DriverStation::RefreshData();
// First and one-time initialization
- inst.GetTable("LiveWindow")
- ->GetSubTable(".status")
- ->GetEntry("LW Enabled")
- .SetBoolean(false);
-
LiveWindow::SetEnabled(false);
}
diff --git a/wpilibc/src/main/native/include/frc/ADIS16448_IMU.h b/wpilibc/src/main/native/include/frc/ADIS16448_IMU.h
index 0dbfa68..60d57a9 100644
--- a/wpilibc/src/main/native/include/frc/ADIS16448_IMU.h
+++ b/wpilibc/src/main/native/include/frc/ADIS16448_IMU.h
@@ -205,6 +205,8 @@
int SetYawAxis(IMUAxis yaw_axis);
+ bool IsConnected() const;
+
int ConfigDecRate(uint16_t DecimationRate);
/**
@@ -285,6 +287,10 @@
double gyro_rate_z = 0.0;
};
+ /** @brief Internal Resources **/
+ DigitalInput* m_reset_in;
+ DigitalOutput* m_status_led;
+
bool SwitchToStandardSPI();
bool SwitchToAutoSPI();
@@ -357,10 +363,12 @@
CalibrationTime m_calibration_time{0};
SPI* m_spi = nullptr;
DigitalInput* m_auto_interrupt = nullptr;
+ bool m_connected{false};
std::thread m_acquire_task;
hal::SimDevice m_simDevice;
+ hal::SimBoolean m_simConnected;
hal::SimDouble m_simGyroAngleX;
hal::SimDouble m_simGyroAngleY;
hal::SimDouble m_simGyroAngleZ;
diff --git a/wpilibc/src/main/native/include/frc/ADIS16470_IMU.h b/wpilibc/src/main/native/include/frc/ADIS16470_IMU.h
index e6f3ce7..4619819 100644
--- a/wpilibc/src/main/native/include/frc/ADIS16470_IMU.h
+++ b/wpilibc/src/main/native/include/frc/ADIS16470_IMU.h
@@ -93,7 +93,8 @@
CalibrationTime cal_time);
/**
- * @brief Destructor. Kills the acquisiton loop and closes the SPI peripheral.
+ * @brief Destructor. Kills the acquisition loop and closes the SPI
+ * peripheral.
*/
~ADIS16470_IMU() override;
@@ -159,6 +160,8 @@
int SetYawAxis(IMUAxis yaw_axis);
+ bool IsConnected() const;
+
// IMU yaw axis
IMUAxis m_yaw_axis;
@@ -296,6 +299,10 @@
static constexpr double deg_to_rad = 0.0174532;
static constexpr double grav = 9.81;
+ /** @brief Resources **/
+ DigitalInput* m_reset_in;
+ DigitalOutput* m_status_led;
+
/**
* @brief Switches to standard SPI operation. Primarily used when exiting auto
* SPI mode.
@@ -378,10 +385,12 @@
SPI* m_spi = nullptr;
DigitalInput* m_auto_interrupt = nullptr;
double m_scaled_sample_rate = 2500.0; // Default sample rate setting
+ bool m_connected{false};
std::thread m_acquire_task;
hal::SimDevice m_simDevice;
+ hal::SimBoolean m_simConnected;
hal::SimDouble m_simGyroAngleX;
hal::SimDouble m_simGyroAngleY;
hal::SimDouble m_simGyroAngleZ;
diff --git a/wpilibc/src/main/native/include/frc/ADXL345_I2C.h b/wpilibc/src/main/native/include/frc/ADXL345_I2C.h
index c997327..6b6b76c 100644
--- a/wpilibc/src/main/native/include/frc/ADXL345_I2C.h
+++ b/wpilibc/src/main/native/include/frc/ADXL345_I2C.h
@@ -19,6 +19,10 @@
* This class allows access to a Analog Devices ADXL345 3-axis accelerometer on
* an I2C bus. This class assumes the default (not alternate) sensor address of
* 0x1D (7-bit address).
+ *
+ * The Onboard I2C port is subject to system lockups. See <a
+ * href="https://docs.wpilib.org/en/stable/docs/yearly-overview/known-issues.html#onboard-i2c-causing-system-lockups">
+ * WPILib Known Issues</a> page for details.
*/
class ADXL345_I2C : public Accelerometer,
public nt::NTSendable,
diff --git a/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h b/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h
index cb0dff8..55414d4 100644
--- a/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h
+++ b/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h
@@ -49,6 +49,8 @@
ADXRS450_Gyro(ADXRS450_Gyro&&) = default;
ADXRS450_Gyro& operator=(ADXRS450_Gyro&&) = default;
+ bool IsConnected() const;
+
/**
* Return the actual angle in degrees that the robot is currently facing.
*
@@ -105,8 +107,10 @@
private:
SPI m_spi;
SPI::Port m_port;
+ bool m_connected{false};
hal::SimDevice m_simDevice;
+ hal::SimBoolean m_simConnected;
hal::SimDouble m_simAngle;
hal::SimDouble m_simRate;
diff --git a/wpilibc/src/main/native/include/frc/AddressableLED.h b/wpilibc/src/main/native/include/frc/AddressableLED.h
index 561eb37..e6adfca 100644
--- a/wpilibc/src/main/native/include/frc/AddressableLED.h
+++ b/wpilibc/src/main/native/include/frc/AddressableLED.h
@@ -5,11 +5,11 @@
#pragma once
#include <initializer_list>
+#include <span>
#include <hal/AddressableLEDTypes.h>
#include <hal/Types.h>
#include <units/time.h>
-#include <wpi/span.h>
#include "util/Color.h"
#include "util/Color8Bit.h"
@@ -107,7 +107,7 @@
*
* @param ledData the buffer to write
*/
- void SetData(wpi::span<const LEDData> ledData);
+ void SetData(std::span<const LEDData> ledData);
/**
* Sets the led output data.
diff --git a/wpilibc/src/main/native/include/frc/AnalogEncoder.h b/wpilibc/src/main/native/include/frc/AnalogEncoder.h
index 6f12cb8..1860273 100644
--- a/wpilibc/src/main/native/include/frc/AnalogEncoder.h
+++ b/wpilibc/src/main/native/include/frc/AnalogEncoder.h
@@ -72,9 +72,23 @@
units::turn_t Get() const;
/**
+ * Get the absolute position of the analog encoder.
+ *
+ * <p>GetAbsolutePosition() - GetPositionOffset() will give an encoder
+ * absolute position relative to the last reset. This could potentially be
+ * negative, which needs to be accounted for.
+ *
+ * <p>This will not account for rollovers, and will always be just the raw
+ * absolute position.
+ *
+ * @return the absolute position
+ */
+ double GetAbsolutePosition() const;
+
+ /**
* Get the offset of position relative to the last reset.
*
- * GetPositionInRotation() - GetPositionOffset() will give an encoder absolute
+ * GetAbsolutePosition() - GetPositionOffset() will give an encoder absolute
* position relative to the last reset. This could potentially be negative,
* which needs to be accounted for.
*
@@ -83,6 +97,15 @@
double GetPositionOffset() const;
/**
+ * Set the position offset.
+ *
+ * <p>This must be in the range of 0-1.
+ *
+ * @param offset the offset
+ */
+ void SetPositionOffset(double offset);
+
+ /**
* Set the distance per rotation of the encoder. This sets the multiplier used
* to determine the distance driven based on the rotation value from the
* encoder. Set this value based on the how far the mechanism travels in 1
@@ -131,5 +154,6 @@
hal::SimDevice m_simDevice;
hal::SimDouble m_simPosition;
+ hal::SimDouble m_simAbsolutePosition;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h b/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h
index 4531dfd..0dea5bc 100644
--- a/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h
+++ b/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h
@@ -82,7 +82,8 @@
* @param source the DigitalSource the interrupts are triggered from
* @param f the callback function to call when the interrupt is triggered
* @param arg the first argument, interrupt was triggered on rising edge
- * @param args the remaing arguments, interrupt was triggered on falling edge
+ * @param args the remaining arguments, interrupt was triggered on falling
+ * edge
*/
template <typename Callable, typename Arg, typename... Args>
AsynchronousInterrupt(DigitalSource& source, Callable&& f, Arg&& arg,
@@ -99,7 +100,8 @@
* @param source the DigitalSource the interrupts are triggered from
* @param f the callback function to call when the interrupt is triggered
* @param arg the first argument, interrupt was triggered on rising edge
- * @param args the remaing arguments, interrupt was triggered on falling edge
+ * @param args the remaining arguments, interrupt was triggered on falling
+ * edge
*/
template <typename Callable, typename Arg, typename... Args>
AsynchronousInterrupt(DigitalSource* source, Callable&& f, Arg&& arg,
@@ -116,7 +118,8 @@
* @param source the DigitalSource the interrupts are triggered from
* @param f the callback function to call when the interrupt is triggered
* @param arg the first argument, interrupt was triggered on rising edge
- * @param args the remaing arguments, interrupt was triggered on falling edge
+ * @param args the remaining arguments, interrupt was triggered on falling
+ * edge
*/
template <typename Callable, typename Arg, typename... Args>
AsynchronousInterrupt(std::shared_ptr<DigitalSource> source, Callable&& f,
diff --git a/wpilibc/src/main/native/include/frc/Compressor.h b/wpilibc/src/main/native/include/frc/Compressor.h
index d8125ed..1329a3b 100644
--- a/wpilibc/src/main/native/include/frc/Compressor.h
+++ b/wpilibc/src/main/native/include/frc/Compressor.h
@@ -59,56 +59,59 @@
Compressor& operator=(Compressor&&) = default;
/**
- * Starts closed-loop control. Note that closed loop control is enabled by
- * default.
- *
- * @deprecated Use EnableDigital() instead.
- */
- WPI_DEPRECATED("Use EnableDigital() instead")
- void Start();
-
- /**
- * Stops closed-loop control. Note that closed loop control is enabled by
- * default.
- *
- * @deprecated Use Disable() instead.
- */
- WPI_DEPRECATED("Use Disable() instead")
- void Stop();
-
- /**
* Check if compressor output is active.
+ * To (re)enable the compressor use EnableDigital() or EnableAnalog(...).
*
- * @return true if the compressor is on
+ * @return true if the compressor is on.
+ * @deprecated To avoid confusion in thinking this (re)enables the compressor
+ * use IsEnabled().
*/
+ WPI_DEPRECATED(
+ "To avoid confusion in thinking this (re)enables the compressor use "
+ "IsEnabled()")
bool Enabled() const;
/**
- * Check if the pressure switch is triggered.
+ * Returns whether the compressor is active or not.
*
- * @return true if pressure is low
+ * @return true if the compressor is on - otherwise false.
+ */
+ bool IsEnabled() const;
+
+ /**
+ * Returns the state of the pressure switch.
+ *
+ * @return True if pressure switch indicates that the system is not full,
+ * otherwise false.
*/
bool GetPressureSwitchValue() const;
/**
- * Query how much current the compressor is drawing.
+ * Get the current drawn by the compressor.
*
- * @return The current through the compressor, in amps
+ * @return Current drawn by the compressor.
*/
units::ampere_t GetCurrent() const;
/**
- * Query the analog input voltage (on channel 0) (if supported).
+ * If supported by the device, returns the analog input voltage (on channel
+ * 0).
*
- * @return The analog input voltage, in volts
+ * This function is only supported by the REV PH. On CTRE PCM, this will
+ * return 0.
+ *
+ * @return The analog input voltage, in volts.
*/
units::volt_t GetAnalogVoltage() const;
/**
- * Query the analog sensor pressure (on channel 0) (if supported). Note this
- * is only for use with the REV Analog Pressure Sensor.
+ * If supported by the device, returns the pressure read by the analog
+ * pressure sensor (on channel 0).
*
- * @return The analog sensor pressure, in PSI
+ * This function is only supported by the REV PH with the REV Analog Pressure
+ * Sensor. On CTRE PCM, this will return 0.
+ *
+ * @return The pressure read by the analog pressure sensor.
*/
units::pounds_per_square_inch_t GetPressure() const;
@@ -118,34 +121,68 @@
void Disable();
/**
- * Enable compressor closed loop control using digital input.
+ * Enables the compressor in digital mode using the digital pressure switch.
+ * The compressor will turn on when the pressure switch indicates that the
+ * system is not full, and will turn off when the pressure switch indicates
+ * that the system is full.
*/
void EnableDigital();
/**
- * Enable compressor closed loop control using analog input. Note this is only
- * for use with the REV Analog Pressure Sensor.
+ * If supported by the device, enables the compressor in analog mode. This
+ * mode uses an analog pressure sensor connected to analog channel 0 to cycle
+ * the compressor. The compressor will turn on when the pressure drops below
+ * {@code minPressure} and will turn off when the pressure reaches {@code
+ * maxPressure}. This mode is only supported by the REV PH with the REV Analog
+ * Pressure Sensor connected to analog channel 0.
*
- * <p>On CTRE PCM, this will enable digital control.
+ * On CTRE PCM, this will enable digital control.
*
- * @param minPressure The minimum pressure in PSI to enable compressor
- * @param maxPressure The maximum pressure in PSI to disable compressor
+ * @param minPressure The minimum pressure. The compressor will turn on when
+ * the pressure drops below this value.
+ * @param maxPressure The maximum pressure. The compressor will turn off when
+ * the pressure reaches this value.
*/
void EnableAnalog(units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure);
/**
- * Enable compressor closed loop control using hybrid input. Note this is only
- * for use with the REV Analog Pressure Sensor.
+ * If supported by the device, enables the compressor in hybrid mode. This
+ * mode uses both a digital pressure switch and an analog pressure sensor
+ * connected to analog channel 0 to cycle the compressor. This mode is only
+ * supported by the REV PH with the REV Analog Pressure Sensor connected to
+ * analog channel 0.
+ *
+ * The compressor will turn on when \a both:
+ *
+ * - The digital pressure switch indicates the system is not full AND
+ * - The analog pressure sensor indicates that the pressure in the system
+ * is below the specified minimum pressure.
+ *
+ * The compressor will turn off when \a either:
+ *
+ * - The digital pressure switch is disconnected or indicates that the system
+ * is full OR
+ * - The pressure detected by the analog sensor is greater than the specified
+ * maximum pressure.
*
* On CTRE PCM, this will enable digital control.
*
- * @param minPressure The minimum pressure in PSI to enable compressor
- * @param maxPressure The maximum pressure in PSI to disable compressor
+ * @param minPressure The minimum pressure. The compressor will turn on
+ * when the pressure drops below this value and the pressure switch indicates
+ * that the system is not full.
+ * @param maxPressure The maximum pressure. The compressor will turn
+ * off when the pressure reaches this value or the pressure switch is
+ * disconnected or indicates that the system is full.
*/
void EnableHybrid(units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure);
+ /**
+ * Returns the active compressor configuration.
+ *
+ * @return The active compressor configuration.
+ */
CompressorConfigType GetConfigType() const;
void InitSendable(wpi::SendableBuilder& builder) override;
diff --git a/wpilibc/src/main/native/include/frc/Controller.h b/wpilibc/src/main/native/include/frc/Controller.h
deleted file mode 100644
index d750a0e..0000000
--- a/wpilibc/src/main/native/include/frc/Controller.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <wpi/deprecated.h>
-
-namespace frc {
-
-/**
- * Interface for Controllers.
- *
- * Common interface for controllers. Controllers run control loops, the most
- * common are PID controllers and their variants, but this includes anything
- * that is controlling an actuator in a separate thread.
- *
- * @deprecated Only used by the deprecated PIDController
- */
-class Controller {
- public:
- WPI_DEPRECATED("Only used by the deprecated PIDController")
- Controller() = default;
- virtual ~Controller() = default;
-
- Controller(Controller&&) = default;
- Controller& operator=(Controller&&) = default;
-
- /**
- * Allows the control loop to run
- */
- virtual void Enable() = 0;
-
- /**
- * Stops the control loop from running until explicitly re-enabled by calling
- * enable()
- */
- virtual void Disable() = 0;
-};
-
-} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DataLogManager.h b/wpilibc/src/main/native/include/frc/DataLogManager.h
new file mode 100644
index 0000000..fa7abba
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DataLogManager.h
@@ -0,0 +1,85 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <string>
+#include <string_view>
+
+namespace wpi::log {
+class DataLog;
+} // namespace wpi::log
+
+namespace frc {
+
+/**
+ * Centralized data log that provides automatic data log file management. It
+ * automatically cleans up old files when disk space is low and renames the file
+ * based either on current date/time or (if available) competition match number.
+ * The deta file will be saved to a USB flash drive if one is attached, or to
+ * /home/lvuser otherwise.
+ *
+ * Log files are initially named "FRC_TBD_{random}.wpilog" until the DS
+ * connects. After the DS connects, the log file is renamed to
+ * "FRC_yyyyMMdd_HHmmss.wpilog" (where the date/time is UTC). If the FMS is
+ * connected and provides a match number, the log file is renamed to
+ * "FRC_yyyyMMdd_HHmmss_{event}_{match}.wpilog".
+ *
+ * On startup, all existing FRC_TBD log files are deleted. If there is less than
+ * 50 MB of free space on the target storage, FRC_ log files are deleted (oldest
+ * to newest) until there is 50 MB free OR there are 10 files remaining.
+ *
+ * By default, all NetworkTables value changes are stored to the data log.
+ */
+class DataLogManager final {
+ public:
+ DataLogManager() = delete;
+
+ /**
+ * Start data log manager. The parameters have no effect if the data log
+ * manager was already started (e.g. by calling another static function).
+ *
+ * @param dir if not empty, directory to use for data log storage
+ * @param filename filename to use; if none provided, the filename is
+ * automatically generated
+ * @param period time between automatic flushes to disk, in seconds;
+ * this is a time/storage tradeoff
+ */
+ static void Start(std::string_view dir = "", std::string_view filename = "",
+ double period = 0.25);
+
+ /**
+ * Log a message to the "messages" entry. The message is also printed to
+ * standard output (followed by a newline).
+ *
+ * @param message message
+ */
+ static void Log(std::string_view message);
+
+ /**
+ * Get the managed data log (for custom logging). Starts the data log manager
+ * if not already started.
+ *
+ * @return data log
+ */
+ static wpi::log::DataLog& GetLog();
+
+ /**
+ * Get the log directory.
+ *
+ * @return log directory
+ */
+ static std::string GetLogDir();
+
+ /**
+ * Enable or disable logging of NetworkTables data. Note that unlike the
+ * network interface for NetworkTables, this will capture every value change.
+ * Defaults to enabled.
+ *
+ * @param enabled true to enable, false to disable
+ */
+ static void LogNetworkTables(bool enabled);
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DigitalOutput.h b/wpilibc/src/main/native/include/frc/DigitalOutput.h
index 0e124f1..d2981fa 100644
--- a/wpilibc/src/main/native/include/frc/DigitalOutput.h
+++ b/wpilibc/src/main/native/include/frc/DigitalOutput.h
@@ -5,6 +5,7 @@
#pragma once
#include <hal/Types.h>
+#include <units/time.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -79,11 +80,11 @@
* Output a single pulse on the digital output line.
*
* Send a single pulse on the digital output line where the pulse duration is
- * specified in seconds. Maximum pulse length is 0.0016 seconds.
+ * specified in seconds. Maximum of 65535 microseconds.
*
- * @param length The pulse length in seconds
+ * @param pulseLength The pulse length in seconds
*/
- void Pulse(double length);
+ void Pulse(units::second_t pulseLength);
/**
* Determine if the pulse is still going.
@@ -105,6 +106,19 @@
void SetPWMRate(double rate);
/**
+ * Enable a PWM PPS (Pulse Per Second) Output on this line.
+ *
+ * Allocate one of the 6 DO PWM generator resources from this module.
+ *
+ * Supply the duty-cycle to output.
+ *
+ * The resolution of the duty cycle is 8-bit.
+ *
+ * @param dutyCycle The duty-cycle to start generating. [0..1]
+ */
+ void EnablePPS(double dutyCycle);
+
+ /**
* Enable a PWM Output on this line.
*
* Allocate one of the 6 DO PWM generator resources from this module.
diff --git a/wpilibc/src/main/native/include/frc/DriverStation.h b/wpilibc/src/main/native/include/frc/DriverStation.h
index 30bf4fc..4cbf6da 100644
--- a/wpilibc/src/main/native/include/frc/DriverStation.h
+++ b/wpilibc/src/main/native/include/frc/DriverStation.h
@@ -7,7 +7,11 @@
#include <string>
#include <units/time.h>
-#include <wpi/deprecated.h>
+#include <wpi/Synchronization.h>
+
+namespace wpi::log {
+class DataLog;
+} // namespace wpi::log
namespace frc {
@@ -15,20 +19,11 @@
* Provide access to the network communication data to / from the Driver
* Station.
*/
-class DriverStation {
+class DriverStation final {
public:
enum Alliance { kRed, kBlue, kInvalid };
enum MatchType { kNone, kPractice, kQualification, kElimination };
- /**
- * Return a reference to the singleton DriverStation.
- *
- * @return Reference to the DS instance
- * @deprecated Use the static methods
- */
- WPI_DEPRECATED("Use static methods")
- static DriverStation& GetInstance();
-
static constexpr int kJoystickPorts = 6;
/**
@@ -196,15 +191,6 @@
* Check if the DS is commanding teleop mode.
*
* @return True if the robot is being commanded to be in teleop mode
- * @deprecated Use IsTeleop() instead.
- */
- WPI_DEPRECATED("Use IsTeleop() instead")
- static bool IsOperatorControl();
-
- /**
- * Check if the DS is commanding teleop mode.
- *
- * @return True if the robot is being commanded to be in teleop mode
*/
static bool IsTeleop();
@@ -213,16 +199,6 @@
*
* @return True if the robot is being commanded to be in teleop mode and
* enabled.
- * @deprecated Use IsTeleopEnabled() instead.
- */
- WPI_DEPRECATED("Use IsTeleopEnabled() instead")
- static bool IsOperatorControlEnabled();
-
- /**
- * Check if the DS is commanding teleop mode and if it has enabled the robot.
- *
- * @return True if the robot is being commanded to be in teleop mode and
- * enabled.
*/
static bool IsTeleopEnabled();
@@ -241,17 +217,6 @@
static bool IsDSAttached();
/**
- * Has a new control packet from the driver station arrived since the last
- * time this function was called?
- *
- * Warning: If you call this function from more than one place at the same
- * time, you will not get the intended behavior.
- *
- * @return True if the control data has been updated since the last call.
- */
- static bool IsNewControlData();
-
- /**
* Is the driver station attached to a Field Management System?
*
* @return True if the robot is competing on a field being controlled by a
@@ -315,41 +280,6 @@
static int GetLocation();
/**
- * Wait until a new packet comes from the driver station.
- *
- * This blocks on a semaphore, so the waiting is efficient.
- *
- * This is a good way to delay processing until there is new driver station
- * data to act on.
- *
- * Checks if new control data has arrived since the last waitForData call
- * on the current thread. If new data has not arrived, returns immediately.
- */
- static void WaitForData();
-
- /**
- * Wait until a new packet comes from the driver station, or wait for a
- * timeout.
- *
- * Checks if new control data has arrived since the last waitForData call
- * on the current thread. If new data has not arrived, returns immediately.
- *
- * If the timeout is less then or equal to 0, wait indefinitely.
- *
- * Timeout is in milliseconds
- *
- * This blocks on a semaphore, so the waiting is efficient.
- *
- * This is a good way to delay processing until there is new driver station
- * data to act on.
- *
- * @param timeout Timeout
- *
- * @return true if new data, otherwise false
- */
- static bool WaitForData(units::second_t timeout);
-
- /**
* Return the approximate match time.
*
* The FMS does not send an official match time to the robots, but does send
@@ -373,56 +303,10 @@
*/
static double GetBatteryVoltage();
- /**
- * Only to be used to tell the Driver Station what code you claim to be
- * executing for diagnostic purposes only.
- *
- * @param entering If true, starting disabled code; if false, leaving disabled
- * code.
- */
- static void InDisabled(bool entering);
+ static void RefreshData();
- /**
- * Only to be used to tell the Driver Station what code you claim to be
- * executing for diagnostic purposes only.
- *
- * @param entering If true, starting autonomous code; if false, leaving
- * autonomous code.
- */
- static void InAutonomous(bool entering);
-
- /**
- * Only to be used to tell the Driver Station what code you claim to be
- * executing for diagnostic purposes only.
- *
- * @param entering If true, starting teleop code; if false, leaving teleop
- * code.
- * @deprecated Use InTeleop() instead.
- */
- WPI_DEPRECATED("Use InTeleop() instead")
- static void InOperatorControl(bool entering);
-
- /**
- * Only to be used to tell the Driver Station what code you claim to be
- * executing for diagnostic purposes only.
- *
- * @param entering If true, starting teleop code; if false, leaving teleop
- * code.
- */
- static void InTeleop(bool entering);
-
- /**
- * Only to be used to tell the Driver Station what code you claim to be
- * executing for diagnostic purposes only.
- *
- * @param entering If true, starting test code; if false, leaving test code.
- */
- static void InTest(bool entering);
-
- /**
- * Forces WaitForData() to return immediately.
- */
- static void WakeupWaitForData();
+ static void ProvideRefreshedDataEventHandle(WPI_EventHandle handle);
+ static void RemoveRefreshedDataEventHandle(WPI_EventHandle handle);
/**
* Allows the user to specify whether they want joystick connection warnings
@@ -441,6 +325,14 @@
*/
static bool IsJoystickConnectionWarningSilenced();
+ /**
+ * Starts logging DriverStation data to data log. Repeated calls are ignored.
+ *
+ * @param log data log
+ * @param logJoysticks if true, log joystick data
+ */
+ static void StartDataLog(wpi::log::DataLog& log, bool logJoysticks = true);
+
private:
DriverStation() = default;
};
diff --git a/wpilibc/src/main/native/include/frc/DutyCycle.h b/wpilibc/src/main/native/include/frc/DutyCycle.h
index 7f45d06..e222045 100644
--- a/wpilibc/src/main/native/include/frc/DutyCycle.h
+++ b/wpilibc/src/main/native/include/frc/DutyCycle.h
@@ -7,6 +7,7 @@
#include <memory>
#include <hal/Types.h>
+#include <units/time.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -83,21 +84,18 @@
double GetOutput() const;
/**
- * Get the raw output ratio of the duty cycle signal.
+ * Get the raw high time of the duty cycle signal.
*
- * <p> 0 means always low, an output equal to
- * GetOutputScaleFactor() means always high.
- *
- * @return output ratio in raw units
+ * @return high time of last pulse
*/
- unsigned int GetOutputRaw() const;
+ units::second_t GetHighTime() const;
/**
* Get the scale factor of the output.
*
* <p> An output equal to this value is always high, and then linearly scales
- * down to 0. Divide the result of getOutputRaw by this in order to get the
- * percentage between 0 and 1.
+ * down to 0. Divide a raw result by this in order to get the
+ * percentage between 0 and 1. Used by DMA.
*
* @return the output scale factor
*/
diff --git a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h
index ab7ded9..5d04ada 100644
--- a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h
+++ b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h
@@ -122,6 +122,40 @@
units::turn_t Get() const;
/**
+ * Get the absolute position of the duty cycle encoder encoder.
+ *
+ * <p>GetAbsolutePosition() - GetPositionOffset() will give an encoder
+ * absolute position relative to the last reset. This could potentially be
+ * negative, which needs to be accounted for.
+ *
+ * <p>This will not account for rollovers, and will always be just the raw
+ * absolute position.
+ *
+ * @return the absolute position
+ */
+ double GetAbsolutePosition() const;
+
+ /**
+ * Get the offset of position relative to the last reset.
+ *
+ * GetAbsolutePosition() - GetPositionOffset() will give an encoder absolute
+ * position relative to the last reset. This could potentially be negative,
+ * which needs to be accounted for.
+ *
+ * @return the position offset
+ */
+ double GetPositionOffset() const;
+
+ /**
+ * Set the position offset.
+ *
+ * <p>This must be in the range of 0-1.
+ *
+ * @param offset the offset
+ */
+ void SetPositionOffset(double offset);
+
+ /**
* Set the encoder duty cycle range. As the encoder needs to maintain a duty
* cycle, the duty cycle cannot go all the way to 0% or all the way to 100%.
* For example, an encoder with a 4096 us period might have a minimum duty
@@ -182,6 +216,7 @@
private:
void Init();
+ double MapSensorRange(double pos) const;
std::shared_ptr<DutyCycle> m_dutyCycle;
std::unique_ptr<AnalogTrigger> m_analogTrigger;
@@ -195,6 +230,7 @@
hal::SimDevice m_simDevice;
hal::SimDouble m_simPosition;
+ hal::SimDouble m_simAbsolutePosition;
hal::SimDouble m_simDistancePerRotation;
hal::SimBoolean m_simIsConnected;
};
diff --git a/wpilibc/src/main/native/include/frc/Encoder.h b/wpilibc/src/main/native/include/frc/Encoder.h
index f6753c2..deb36c0 100644
--- a/wpilibc/src/main/native/include/frc/Encoder.h
+++ b/wpilibc/src/main/native/include/frc/Encoder.h
@@ -166,7 +166,9 @@
* scaled using the value from SetDistancePerPulse().
*
* @return Period in seconds of the most recent pulse.
+ * @deprecated Use getRate() in favor of this method.
*/
+ WPI_DEPRECATED("Use GetRate() in favor of this method")
units::second_t GetPeriod() const override;
/**
@@ -177,13 +179,12 @@
* to determine if the wheels or other shaft has stopped rotating.
* This method compensates for the decoding type.
*
- * @deprecated Use SetMinRate() in favor of this method. This takes unscaled
- * periods and SetMinRate() scales using value from
- * SetDistancePerPulse().
- *
* @param maxPeriod The maximum time between rising and falling edges before
* the FPGA will report the device stopped. This is expressed
* in seconds.
+ * @deprecated Use SetMinRate() in favor of this method. This takes unscaled
+ * periods and SetMinRate() scales using value from
+ * SetDistancePerPulse().
*/
WPI_DEPRECATED(
"Use SetMinRate() in favor of this method. This takes unscaled periods "
diff --git a/wpilibc/src/main/native/include/frc/Errors.h b/wpilibc/src/main/native/include/frc/Errors.h
index 84edc18..252a335 100644
--- a/wpilibc/src/main/native/include/frc/Errors.h
+++ b/wpilibc/src/main/native/include/frc/Errors.h
@@ -74,11 +74,12 @@
* @param[in] format error message format
* @param[in] args error message format args
*/
-template <typename S, typename... Args>
+template <typename... Args>
inline void ReportError(int32_t status, const char* fileName, int lineNumber,
- const char* funcName, const S& format, Args&&... args) {
+ const char* funcName, fmt::string_view format,
+ Args&&... args) {
ReportErrorV(status, fileName, lineNumber, funcName, format,
- fmt::make_args_checked<Args...>(format, args...));
+ fmt::make_format_args(args...));
}
/**
@@ -99,14 +100,12 @@
fmt::string_view format,
fmt::format_args args);
-template <typename S, typename... Args>
-[[nodiscard]] inline RuntimeError MakeError(int32_t status,
- const char* fileName,
- int lineNumber,
- const char* funcName,
- const S& format, Args&&... args) {
+template <typename... Args>
+[[nodiscard]] inline RuntimeError MakeError(
+ int32_t status, const char* fileName, int lineNumber, const char* funcName,
+ fmt::string_view format, Args&&... args) {
return MakeErrorV(status, fileName, lineNumber, funcName, format,
- fmt::make_args_checked<Args...>(format, args...));
+ fmt::make_format_args(args...));
}
namespace err {
@@ -122,18 +121,24 @@
} // namespace warn
} // namespace frc
+// C++20 relaxed the number of arguments to variadics, but Apple Clang's
+// warnings haven't caught up yet: https://stackoverflow.com/a/67996331
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#endif
+
/**
* Reports an error to the driver station (using HAL_SendError).
*
* @param[out] status error code
* @param[in] format error message format
*/
-#define FRC_ReportError(status, format, ...) \
- do { \
- if ((status) != 0) { \
- ::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
- FMT_STRING(format), __VA_ARGS__); \
- } \
+#define FRC_ReportError(status, format, ...) \
+ do { \
+ if ((status) != 0) { \
+ ::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
+ FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__); \
+ } \
} while (0)
/**
@@ -146,7 +151,7 @@
*/
#define FRC_MakeError(status, format, ...) \
::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
- FMT_STRING(format), __VA_ARGS__)
+ FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__)
/**
* Checks a status code and depending on its value, either throws a
@@ -155,23 +160,24 @@
* @param[out] status error code
* @param[in] format error message format
*/
-#define FRC_CheckErrorStatus(status, format, ...) \
- do { \
- if ((status) < 0) { \
- throw ::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
- FMT_STRING(format), __VA_ARGS__); \
- } else if ((status) > 0) { \
- ::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
- FMT_STRING(format), __VA_ARGS__); \
- } \
+#define FRC_CheckErrorStatus(status, format, ...) \
+ do { \
+ if ((status) < 0) { \
+ throw ::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
+ FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__); \
+ } else if ((status) > 0) { \
+ ::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
+ FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__); \
+ } \
} while (0)
#define FRC_AssertMessage(condition, format, ...) \
do { \
if (!(condition)) { \
throw ::frc::MakeError(err::AssertionFailure, __FILE__, __LINE__, \
- __FUNCTION__, FMT_STRING(format), __VA_ARGS__); \
+ __FUNCTION__, \
+ FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
-#define FRC_Assert(condition) FRC_AssertMessage(condition, "{}", #condition)
+#define FRC_Assert(condition) FRC_AssertMessage(condition, #condition)
diff --git a/wpilibc/src/main/native/include/frc/GenericHID.h b/wpilibc/src/main/native/include/frc/GenericHID.h
index b6c18d3..f6db94c 100644
--- a/wpilibc/src/main/native/include/frc/GenericHID.h
+++ b/wpilibc/src/main/native/include/frc/GenericHID.h
@@ -10,7 +10,8 @@
namespace frc {
-class DriverStation;
+class BooleanEvent;
+class EventLoop;
/**
* Handle input from standard HID devices connected to the Driver Station.
@@ -22,7 +23,7 @@
*/
class GenericHID {
public:
- enum RumbleType { kLeftRumble, kRightRumble };
+ enum RumbleType { kLeftRumble, kRightRumble, kBothRumble };
enum HIDType {
kUnknown = -1,
@@ -92,6 +93,16 @@
bool GetRawButtonReleased(int button);
/**
+ * Constructs an event instance around this button's digital signal.
+ *
+ * @param button the button index
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the button's digital signal attached
+ * to the given loop.
+ */
+ BooleanEvent Button(int button, EventLoop* loop) const;
+
+ /**
* Get the value of the axis.
*
* @param axis The axis to read, starting at 0.
@@ -111,6 +122,141 @@
int GetPOV(int pov = 0) const;
/**
+ * Constructs a BooleanEvent instance based around this angle of a POV on the
+ * HID.
+ *
+ * <p>The POV angles start at 0 in the up direction, and increase clockwise
+ * (eg right is 90, upper-left is 315).
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @param angle POV angle in degrees, or -1 for the center / not pressed.
+ * @return a BooleanEvent instance based around this angle of a POV on the
+ * HID.
+ */
+ BooleanEvent POV(int angle, EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around this angle of a POV on the
+ * HID.
+ *
+ * <p>The POV angles start at 0 in the up direction, and increase clockwise
+ * (eg right is 90, upper-left is 315).
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @param pov index of the POV to read (starting at 0). Defaults to 0.
+ * @param angle POV angle in degrees, or -1 for the center / not pressed.
+ * @return a BooleanEvent instance based around this angle of a POV on the
+ * HID.
+ */
+ BooleanEvent POV(int pov, int angle, EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 0 degree angle (up) of
+ * the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 0 degree angle of a POV on
+ * the HID.
+ */
+ BooleanEvent POVUp(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 45 degree angle (right
+ * up) of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 45 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVUpRight(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 90 degree angle (right)
+ * of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 90 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVRight(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 135 degree angle (right
+ * down) of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 135 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVDownRight(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 180 degree angle (down)
+ * of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 180 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVDown(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 225 degree angle (down
+ * left) of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 225 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVDownLeft(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 270 degree angle (left)
+ * of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 270 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVLeft(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the 315 degree angle (left
+ * up) of the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the 315 degree angle of a POV
+ * on the HID.
+ */
+ BooleanEvent POVUpLeft(EventLoop* loop) const;
+
+ /**
+ * Constructs a BooleanEvent instance based around the center (not pressed) of
+ * the default (index 0) POV on the HID.
+ *
+ * @return a BooleanEvent instance based around the center of a POV on the
+ * HID.
+ */
+ BooleanEvent POVCenter(EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance that is true when the axis value is less than
+ * threshold
+ *
+ * @param axis The axis to read, starting at 0.
+ * @param threshold The value below which this trigger should return true.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the axis value is less than the
+ * provided threshold.
+ */
+ BooleanEvent AxisLessThan(int axis, double threshold, EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance that is true when the axis value is greater
+ * than threshold
+ *
+ * @param axis The axis to read, starting at 0.
+ * @param threshold The value above which this trigger should return true.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the axis value is greater than
+ * the provided threshold.
+ */
+ BooleanEvent AxisGreaterThan(int axis, double threshold,
+ EventLoop* loop) const;
+
+ /**
* Get the number of axes for the HID.
*
* @return the number of axis for the current HID
diff --git a/wpilibc/src/main/native/include/frc/I2C.h b/wpilibc/src/main/native/include/frc/I2C.h
index d874a46..9489fcf 100644
--- a/wpilibc/src/main/native/include/frc/I2C.h
+++ b/wpilibc/src/main/native/include/frc/I2C.h
@@ -15,6 +15,10 @@
*
* This class is intended to be used by sensor (and other I2C device) drivers.
* It probably should not be used directly.
+ *
+ * The Onboard I2C port is subject to system lockups. See <a
+ * href="https://docs.wpilib.org/en/stable/docs/yearly-overview/known-issues.html#onboard-i2c-causing-system-lockups">
+ * WPILib Known Issues</a> page for details.
*/
class I2C {
public:
diff --git a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h
index c4253ef..77ed197 100644
--- a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h
+++ b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h
@@ -5,7 +5,6 @@
#pragma once
#include <units/time.h>
-#include <wpi/deprecated.h>
#include "frc/RobotBase.h"
#include "frc/Watchdog.h"
@@ -196,13 +195,26 @@
/**
* Enables or disables flushing NetworkTables every loop iteration.
- * By default, this is disabled.
+ * By default, this is enabled.
*
* @param enabled True to enable, false to disable
*/
void SetNetworkTablesFlushEnabled(bool enabled);
/**
+ * Sets whether LiveWindow operation is enabled during test mode.
+ *
+ * @param testLW True to enable, false to disable. Defaults to true.
+ * @throws if called in test mode.
+ */
+ void EnableLiveWindowInTest(bool testLW);
+
+ /**
+ * Whether LiveWindow operation is enabled during test mode.
+ */
+ bool IsLiveWindowEnabledInTest();
+
+ /**
* Gets time period between calls to Periodic() functions.
*/
units::second_t GetPeriod() const;
@@ -210,17 +222,6 @@
/**
* Constructor for IterativeRobotBase.
*
- * @param period Period in seconds.
- *
- * @deprecated Use IterativeRobotBase(units::second_t period) with unit-safety
- * instead
- */
- WPI_DEPRECATED("Use constructor with unit-safety instead.")
- explicit IterativeRobotBase(double period);
-
- /**
- * Constructor for IterativeRobotBase.
- *
* @param period Period.
*/
explicit IterativeRobotBase(units::second_t period);
@@ -239,7 +240,8 @@
Mode m_lastMode = Mode::kNone;
units::second_t m_period;
Watchdog m_watchdog;
- bool m_ntFlushEnabled = false;
+ bool m_ntFlushEnabled = true;
+ bool m_lwEnabledInTest = true;
void PrintLoopOverrunMessage();
};
diff --git a/wpilibc/src/main/native/include/frc/Joystick.h b/wpilibc/src/main/native/include/frc/Joystick.h
index 0d63e4e..fc0df35 100644
--- a/wpilibc/src/main/native/include/frc/Joystick.h
+++ b/wpilibc/src/main/native/include/frc/Joystick.h
@@ -173,6 +173,15 @@
bool GetTriggerReleased();
/**
+ * Constructs an event instance around the trigger button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the trigger button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Trigger(EventLoop* loop) const;
+
+ /**
* Read the state of the top button on the joystick.
*
* Look up which button has been assigned to the top and read its state.
@@ -196,6 +205,15 @@
bool GetTopReleased();
/**
+ * Constructs an event instance around the top button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the top button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Top(EventLoop* loop) const;
+
+ /**
* Get the magnitude of the direction vector formed by the joystick's
* current position relative to its origin.
*
diff --git a/wpilibc/src/main/native/include/frc/MotorSafety.h b/wpilibc/src/main/native/include/frc/MotorSafety.h
index 1bfd34a..a17cdc0 100644
--- a/wpilibc/src/main/native/include/frc/MotorSafety.h
+++ b/wpilibc/src/main/native/include/frc/MotorSafety.h
@@ -14,8 +14,11 @@
namespace frc {
/**
- * This base class runs a watchdog timer and calls the subclass's StopMotor()
- * function if the timeout expires.
+ * The Motor Safety feature acts as a watchdog timer for an individual motor. It
+ * operates by maintaining a timer that tracks how long it has been since the
+ * feed() method has been called for that actuator. Code in the Driver Station
+ * class initiates a comparison of these timers to the timeout values for any
+ * actuator with safety enabled every 5 received packets (100ms nominal).
*
* The subclass should call Feed() whenever the motor value is updated.
*/
diff --git a/wpilibc/src/main/native/include/frc/Notifier.h b/wpilibc/src/main/native/include/frc/Notifier.h
index 61b7fbb..bda685c 100644
--- a/wpilibc/src/main/native/include/frc/Notifier.h
+++ b/wpilibc/src/main/native/include/frc/Notifier.h
@@ -19,6 +19,13 @@
namespace frc {
+/**
+ * Notifiers run a callback function on a separate thread at a specified period.
+ *
+ * If StartSingle() is used, the callback will run once. If StartPeriodic() is
+ * used, the callback will run repeatedly with the given period until stop() is
+ * called.
+ */
class Notifier {
public:
/**
@@ -95,6 +102,9 @@
* interrupt occurs, the event will be immediately requeued for the same time
* interval.
*
+ * The user-provided callback should be written in a nonblocking manner so the
+ * callback can be recalled at the next periodic event notification.
+ *
* @param period Period to call the handler starting one period
* after the call to this method.
*/
diff --git a/wpilibc/src/main/native/include/frc/PS4Controller.h b/wpilibc/src/main/native/include/frc/PS4Controller.h
index ee87501..9487634 100644
--- a/wpilibc/src/main/native/include/frc/PS4Controller.h
+++ b/wpilibc/src/main/native/include/frc/PS4Controller.h
@@ -99,6 +99,15 @@
bool GetSquareButtonReleased();
/**
+ * Constructs an event instance around the square button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the square button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Square(EventLoop* loop) const;
+
+ /**
* Read the value of the Cross button on the controller.
*
* @return The state of the button.
@@ -120,6 +129,15 @@
bool GetCrossButtonReleased();
/**
+ * Constructs an event instance around the cross button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the cross button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Cross(EventLoop* loop) const;
+
+ /**
* Read the value of the Circle button on the controller.
*
* @return The state of the button.
@@ -141,6 +159,15 @@
bool GetCircleButtonReleased();
/**
+ * Constructs an event instance around the circle button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the circle button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Circle(EventLoop* loop) const;
+
+ /**
* Read the value of the Triangle button on the controller.
*
* @return The state of the button.
@@ -162,6 +189,15 @@
bool GetTriangleButtonReleased();
/**
+ * Constructs an event instance around the triangle button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the triangle button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Triangle(EventLoop* loop) const;
+
+ /**
* Read the value of the L1 button on the controller.
*
* @return The state of the button.
@@ -183,6 +219,15 @@
bool GetL1ButtonReleased();
/**
+ * Constructs an event instance around the L1 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the L1 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent L1(EventLoop* loop) const;
+
+ /**
* Read the value of the R1 button on the controller.
*
* @return The state of the button.
@@ -204,6 +249,15 @@
bool GetR1ButtonReleased();
/**
+ * Constructs an event instance around the R1 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the R1 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent R1(EventLoop* loop) const;
+
+ /**
* Read the value of the L2 button on the controller.
*
* @return The state of the button.
@@ -225,6 +279,15 @@
bool GetL2ButtonReleased();
/**
+ * Constructs an event instance around the L2 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the L2 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent L2(EventLoop* loop) const;
+
+ /**
* Read the value of the R2 button on the controller.
*
* @return The state of the button.
@@ -246,6 +309,15 @@
bool GetR2ButtonReleased();
/**
+ * Constructs an event instance around the R2 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the R2 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent R2(EventLoop* loop) const;
+
+ /**
* Read the value of the Share button on the controller.
*
* @return The state of the button.
@@ -267,6 +339,15 @@
bool GetShareButtonReleased();
/**
+ * Constructs an event instance around the share button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the share button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Share(EventLoop* loop) const;
+
+ /**
* Read the value of the Options button on the controller.
*
* @return The state of the button.
@@ -288,6 +369,15 @@
bool GetOptionsButtonReleased();
/**
+ * Constructs an event instance around the options button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the options button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Options(EventLoop* loop) const;
+
+ /**
* Read the value of the L3 button (pressing the left analog stick) on the
* controller.
*
@@ -310,6 +400,15 @@
bool GetL3ButtonReleased();
/**
+ * Constructs an event instance around the L3 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the L3 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent L3(EventLoop* loop) const;
+
+ /**
* Read the value of the R3 button (pressing the right analog stick) on the
* controller.
*
@@ -332,6 +431,15 @@
bool GetR3ButtonReleased();
/**
+ * Constructs an event instance around the R3 button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the R3 button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent R3(EventLoop* loop) const;
+
+ /**
* Read the value of the PS button on the controller.
*
* @return The state of the button.
@@ -353,6 +461,15 @@
bool GetPSButtonReleased();
/**
+ * Constructs an event instance around the PS button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the PS button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent PS(EventLoop* loop) const;
+
+ /**
* Read the value of the touchpad button on the controller.
*
* @return The state of the button.
@@ -373,6 +490,15 @@
*/
bool GetTouchpadReleased();
+ /**
+ * Constructs an event instance around the touchpad's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the touchpad's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Touchpad(EventLoop* loop) const;
+
struct Button {
static constexpr int kSquare = 1;
static constexpr int kCross = 2;
diff --git a/wpilibc/src/main/native/include/frc/PWM.h b/wpilibc/src/main/native/include/frc/PWM.h
index efff540..e508915 100644
--- a/wpilibc/src/main/native/include/frc/PWM.h
+++ b/wpilibc/src/main/native/include/frc/PWM.h
@@ -166,7 +166,7 @@
/**
* Optionally eliminate the deadband from a motor controller.
*
- * @param eliminateDeadband If true, set the motor curve on the speed
+ * @param eliminateDeadband If true, set the motor curve on the motor
* controller to eliminate the deadband in the middle
* of the range. Otherwise, keep the full range
* without modifying any values.
diff --git a/wpilibc/src/main/native/include/frc/PneumaticHub.h b/wpilibc/src/main/native/include/frc/PneumaticHub.h
index d412bb6..f876b7a 100644
--- a/wpilibc/src/main/native/include/frc/PneumaticHub.h
+++ b/wpilibc/src/main/native/include/frc/PneumaticHub.h
@@ -13,23 +13,72 @@
#include "PneumaticsBase.h"
namespace frc {
+/** Module class for controlling a REV Robotics Pneumatic Hub. */
class PneumaticHub : public PneumaticsBase {
public:
+ /** Constructs a PneumaticHub with the default ID (1). */
PneumaticHub();
+
+ /**
+ * Constructs a PneumaticHub.
+ *
+ * @param module module number to construct
+ */
explicit PneumaticHub(int module);
~PneumaticHub() override = default;
bool GetCompressor() const override;
+ /**
+ * Disables the compressor. The compressor will not turn on until
+ * EnableCompressorDigital(), EnableCompressorAnalog(), or
+ * EnableCompressorHybrid() are called.
+ */
void DisableCompressor() override;
void EnableCompressorDigital() override;
+ /**
+ * Enables the compressor in analog mode. This mode uses an analog pressure
+ * sensor connected to analog channel 0 to cycle the compressor. The
+ * compressor will turn on when the pressure drops below {@code minPressure}
+ * and will turn off when the pressure reaches {@code maxPressure}.
+ *
+ * @param minPressure The minimum pressure. The compressor will turn on when
+ * the pressure drops below this value.
+ * @param maxPressure The maximum pressure. The compressor will turn off when
+ * the pressure reaches this value.
+ */
void EnableCompressorAnalog(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) override;
+ /**
+ * Enables the compressor in hybrid mode. This mode uses both a digital
+ * pressure switch and an analog pressure sensor connected to analog channel 0
+ * to cycle the compressor.
+ *
+ * The compressor will turn on when \a both:
+ *
+ * - The digital pressure switch indicates the system is not full AND
+ * - The analog pressure sensor indicates that the pressure in the system is
+ * below the specified minimum pressure.
+ *
+ * The compressor will turn off when \a either:
+ *
+ * - The digital pressure switch is disconnected or indicates that the system
+ * is full OR
+ * - The pressure detected by the analog sensor is greater than the specified
+ * maximum pressure.
+ *
+ * @param minPressure The minimum pressure. The compressor will turn on when
+ * the pressure drops below this value and the pressure switch indicates that
+ * the system is not full.
+ * @param maxPressure The maximum pressure. The compressor will turn off when
+ * the pressure reaches this value or the pressure switch is disconnected or
+ * indicates that the system is full.
+ */
void EnableCompressorHybrid(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) override;
@@ -76,6 +125,11 @@
uint32_t UniqueId;
};
+ /**
+ * Returns the hardware and firmware versions of this device.
+ *
+ * @return The hardware and firmware versions.
+ */
Version GetVersion() const;
struct Faults {
@@ -103,6 +157,11 @@
uint32_t HardwareFault : 1;
};
+ /**
+ * Returns the faults currently active on this device.
+ *
+ * @return The faults.
+ */
Faults GetFaults() const;
struct StickyFaults {
@@ -115,20 +174,60 @@
uint32_t HasReset : 1;
};
+ /**
+ * Returns the sticky faults currently active on this device.
+ *
+ * @return The sticky faults.
+ */
StickyFaults GetStickyFaults() const;
+ /** Clears the sticky faults. */
void ClearStickyFaults();
+ /**
+ * Returns the current input voltage for this device.
+ *
+ * @return The input voltage.
+ */
units::volt_t GetInputVoltage() const;
+ /**
+ * Returns the current voltage of the regulated 5v supply.
+ *
+ * @return The current voltage of the 5v supply.
+ */
units::volt_t Get5VRegulatedVoltage() const;
+ /**
+ * Returns the total current drawn by all solenoids.
+ *
+ * @return Total current drawn by all solenoids.
+ */
units::ampere_t GetSolenoidsTotalCurrent() const;
+ /**
+ * Returns the current voltage of the solenoid power supply.
+ *
+ * @return The current voltage of the solenoid power supply.
+ */
units::volt_t GetSolenoidsVoltage() const;
+ /**
+ * Returns the raw voltage of the specified analog input channel.
+ *
+ * @param channel The analog input channel to read voltage from.
+ * @return The voltage of the specified analog input channel.
+ */
units::volt_t GetAnalogVoltage(int channel) const override;
+ /**
+ * Returns the pressure read by an analog pressure sensor on the specified
+ * analog input channel.
+ *
+ * @param channel The analog input channel to read pressure from.
+ * @return The pressure read by an analog pressure sensor on the specified
+ * analog input channel.
+ */
units::pounds_per_square_inch_t GetPressure(int channel) const override;
private:
diff --git a/wpilibc/src/main/native/include/frc/PneumaticsBase.h b/wpilibc/src/main/native/include/frc/PneumaticsBase.h
index 50ceb87..b455dc6 100644
--- a/wpilibc/src/main/native/include/frc/PneumaticsBase.h
+++ b/wpilibc/src/main/native/include/frc/PneumaticsBase.h
@@ -22,50 +22,194 @@
public:
virtual ~PneumaticsBase() = default;
+ /**
+ * Returns whether the compressor is active or not.
+ *
+ * @return True if the compressor is on - otherwise false.
+ */
virtual bool GetCompressor() const = 0;
+ /**
+ * Returns the state of the pressure switch.
+ *
+ * @return True if pressure switch indicates that the system is full,
+ * otherwise false.
+ */
virtual bool GetPressureSwitch() const = 0;
+ /**
+ * Returns the current drawn by the compressor.
+ *
+ * @return The current drawn by the compressor.
+ */
virtual units::ampere_t GetCompressorCurrent() const = 0;
+ /** Disables the compressor. */
virtual void DisableCompressor() = 0;
+ /**
+ * Enables the compressor in digital mode using the digital pressure switch.
+ * The compressor will turn on when the pressure switch indicates that the
+ * system is not full, and will turn off when the pressure switch indicates
+ * that the system is full.
+ */
virtual void EnableCompressorDigital() = 0;
+ /**
+ * If supported by the device, enables the compressor in analog mode. This
+ * mode uses an analog pressure sensor connected to analog channel 0 to cycle
+ * the compressor. The compressor will turn on when the pressure drops below
+ * {@code minPressure} and will turn off when the pressure reaches {@code
+ * maxPressure}. This mode is only supported by the REV PH with the REV Analog
+ * Pressure Sensor connected to analog channel 0.
+ *
+ * On CTRE PCM, this will enable digital control.
+ *
+ * @param minPressure The minimum pressure. The compressor will turn on
+ * when the pressure drops below this value.
+ * @param maxPressure The maximum pressure. The compressor will turn
+ * off when the pressure reaches this value.
+ */
virtual void EnableCompressorAnalog(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) = 0;
+ /**
+ * If supported by the device, enables the compressor in hybrid mode. This
+ * mode uses both a digital pressure switch and an analog pressure sensor
+ * connected to analog channel 0 to cycle the compressor. This mode is only
+ * supported by the REV PH with the REV Analog Pressure Sensor connected to
+ * analog channel 0.
+ *
+ * The compressor will turn on when \a both:
+ *
+ * - The digital pressure switch indicates the system is not full AND
+ * - The analog pressure sensor indicates that the pressure in the system
+ * is below the specified minimum pressure.
+ *
+ * The compressor will turn off when \a either:
+ *
+ * - The digital pressure switch is disconnected or indicates that the system
+ * is full OR
+ * - The pressure detected by the analog sensor is greater than the specified
+ * maximum pressure.
+ *
+ * On CTRE PCM, this will enable digital control.
+ *
+ * @param minPressure The minimum pressure. The compressor will turn on
+ * when the pressure drops below this value and the pressure switch indicates
+ * that the system is not full.
+ * @param maxPressure The maximum pressure. The compressor will turn
+ * off when the pressure reaches this value or the pressure switch is
+ * disconnected or indicates that the system is full.
+ */
virtual void EnableCompressorHybrid(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) = 0;
+ /**
+ * Returns the active compressor configuration.
+ *
+ * @return The active compressor configuration.
+ */
virtual CompressorConfigType GetCompressorConfigType() const = 0;
+ /**
+ * Sets solenoids on a pneumatics module.
+ *
+ * @param mask mask
+ * @param values values
+ */
virtual void SetSolenoids(int mask, int values) = 0;
+ /**
+ * Gets a bitmask of solenoid values.
+ *
+ * @return values
+ */
virtual int GetSolenoids() const = 0;
+ /**
+ * Get module number for this module.
+ *
+ * @return module number
+ */
virtual int GetModuleNumber() const = 0;
+ /**
+ * Get a bitmask of disabled solenoids.
+ *
+ * @return bitmask of disabled solenoids
+ */
virtual int GetSolenoidDisabledList() const = 0;
+ /**
+ * Fire a single solenoid shot.
+ *
+ * @param index solenoid index
+ */
virtual void FireOneShot(int index) = 0;
+ /**
+ * Set the duration for a single solenoid shot.
+ *
+ * @param index solenoid index
+ * @param duration shot duration
+ */
virtual void SetOneShotDuration(int index, units::second_t duration) = 0;
+ /**
+ * Check if a solenoid channel is valid.
+ *
+ * @param channel Channel to check
+ * @return True if channel exists
+ */
virtual bool CheckSolenoidChannel(int channel) const = 0;
+ /**
+ * Check to see if the masked solenoids can be reserved, and if not reserve
+ * them.
+ *
+ * @param mask The bitmask of solenoids to reserve
+ * @return 0 if successful; mask of solenoids that couldn't be allocated
+ * otherwise
+ */
virtual int CheckAndReserveSolenoids(int mask) = 0;
+ /**
+ * Unreserve the masked solenoids.
+ *
+ * @param mask The bitmask of solenoids to unreserve
+ */
virtual void UnreserveSolenoids(int mask) = 0;
virtual bool ReserveCompressor() = 0;
virtual void UnreserveCompressor() = 0;
+ /**
+ * If supported by the device, returns the raw voltage of the specified analog
+ * input channel.
+ *
+ * This function is only supported by the REV PH. On CTRE PCM, this will
+ * return 0.
+ *
+ * @param channel The analog input channel to read voltage from.
+ * @return The voltage of the specified analog input channel.
+ */
virtual units::volt_t GetAnalogVoltage(int channel) const = 0;
+ /**
+ * If supported by the device, returns the pressure read by an analog
+ * pressure sensor on the specified analog input channel.
+ *
+ * This function is only supported by the REV PH. On CTRE PCM, this will
+ * return 0.
+ *
+ * @param channel The analog input channel to read pressure from.
+ * @return The pressure read by an analog pressure sensor on the
+ * specified analog input channel.
+ */
virtual units::pounds_per_square_inch_t GetPressure(int channel) const = 0;
virtual Solenoid MakeSolenoid(int channel) = 0;
@@ -73,8 +217,22 @@
int reverseChannel) = 0;
virtual Compressor MakeCompressor() = 0;
+ /**
+ * For internal use to get a module for a specific type.
+ *
+ * @param module module number
+ * @param moduleType module type
+ * @return module
+ */
static std::shared_ptr<PneumaticsBase> GetForType(
int module, PneumaticsModuleType moduleType);
+
+ /**
+ * For internal use to get the default for a specific type.
+ *
+ * @param moduleType module type
+ * @return module default
+ */
static int GetDefaultForType(PneumaticsModuleType moduleType);
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h
index ea4517b..acad5a1 100644
--- a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h
+++ b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h
@@ -13,23 +13,52 @@
#include "PneumaticsBase.h"
namespace frc {
+/** Module class for controlling a Cross The Road Electronics Pneumatics Control
+ * Module. */
class PneumaticsControlModule : public PneumaticsBase {
public:
+ /** Constructs a PneumaticsControlModule with the default ID (0). */
PneumaticsControlModule();
+
+ /**
+ * Constructs a PneumaticsControlModule.
+ *
+ * @param module module number to construct
+ */
explicit PneumaticsControlModule(int module);
~PneumaticsControlModule() override = default;
bool GetCompressor() const override;
+ /**
+ * Disables the compressor. The compressor will not turn on until
+ * EnableCompressorDigital() is called.
+ */
void DisableCompressor() override;
void EnableCompressorDigital() override;
+ /**
+ * Enables the compressor in digital mode. Analog mode is unsupported by the
+ * CTRE PCM.
+ *
+ * @param minPressure Unsupported.
+ * @param maxPressure Unsupported.
+ * @see EnableCompressorDigital()
+ */
void EnableCompressorAnalog(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) override;
+ /**
+ * Enables the compressor in digital mode. Hybrid mode is unsupported by the
+ * CTRE PCM.
+ *
+ * @param minPressure Unsupported.
+ * @param maxPressure Unsupported.
+ * @see EnableCompressorDigital()
+ */
void EnableCompressorHybrid(
units::pounds_per_square_inch_t minPressure,
units::pounds_per_square_inch_t maxPressure) override;
@@ -40,16 +69,67 @@
units::ampere_t GetCompressorCurrent() const override;
+ /**
+ * Return whether the compressor current is currently too high.
+ *
+ * @return True if the compressor current is too high, otherwise false.
+ * @see GetCompressorCurrentTooHighStickyFault()
+ */
bool GetCompressorCurrentTooHighFault() const;
+
+ /**
+ * Returns whether the compressor current has been too high since sticky
+ * faults were last cleared. This fault is persistent and can be cleared by
+ * ClearAllStickyFaults()
+ *
+ * @return True if the compressor current has been too high since sticky
+ * faults were last cleared.
+ * @see GetCompressorCurrentTooHighFault()
+ */
bool GetCompressorCurrentTooHighStickyFault() const;
+
+ /**
+ * Returns whether the compressor is currently shorted.
+ *
+ * @return True if the compressor is currently shorted, otherwise false.
+ * @see GetCompressorShortedStickyFault()
+ */
bool GetCompressorShortedFault() const;
+
+ /**
+ * Returns whether the compressor has been shorted since sticky faults were
+ * last cleared. This fault is persistent and can be cleared by
+ * ClearAllStickyFaults()
+ *
+ * @return True if the compressor has been shorted since sticky faults were
+ * last cleared, otherwise false.
+ * @see GetCompressorShortedFault()
+ */
bool GetCompressorShortedStickyFault() const;
+
+ /**
+ * Returns whether the compressor is currently disconnected.
+ *
+ * @return True if compressor is currently disconnected, otherwise false.
+ * @see GetCompressorNotConnectedStickyFault()
+ */
bool GetCompressorNotConnectedFault() const;
+
+ /**
+ * Returns whether the compressor has been disconnected since sticky faults
+ * were last cleared. This fault is persistent and can be cleared by
+ * ClearAllStickyFaults()}
+ *
+ * @return True if the compressor has been disconnected since sticky faults
+ * were last cleared, otherwise false.
+ * @see GetCompressorNotConnectedFault()
+ */
bool GetCompressorNotConnectedStickyFault() const;
bool GetSolenoidVoltageFault() const;
bool GetSolenoidVoltageStickyFault() const;
+ /** Clears all sticky faults on this device. */
void ClearAllStickyFaults();
void SetSolenoids(int mask, int values) override;
@@ -74,8 +154,20 @@
void UnreserveCompressor() override;
+ /**
+ * Unsupported by the CTRE PCM.
+ *
+ * @param channel Unsupported.
+ * @return 0
+ */
units::volt_t GetAnalogVoltage(int channel) const override;
+ /**
+ * Unsupported by the CTRE PCM.
+ *
+ * @param channel Unsupported.
+ * @return 0
+ */
units::pounds_per_square_inch_t GetPressure(int channel) const override;
Solenoid MakeSolenoid(int channel) override;
diff --git a/wpilibc/src/main/native/include/frc/Preferences.h b/wpilibc/src/main/native/include/frc/Preferences.h
index b939d9e..0094ad0 100644
--- a/wpilibc/src/main/native/include/frc/Preferences.h
+++ b/wpilibc/src/main/native/include/frc/Preferences.h
@@ -10,8 +10,6 @@
#include <string_view>
#include <vector>
-#include <wpi/deprecated.h>
-
namespace frc {
/**
@@ -31,15 +29,6 @@
class Preferences {
public:
/**
- * Get the one and only {@link Preferences} object.
- *
- * @return pointer to the {@link Preferences}
- * @deprecated Use the static methods
- */
- WPI_DEPRECATED("Use static methods")
- static Preferences* GetInstance();
-
- /**
* Returns a vector of all the keys.
*
* @return a vector of the keys
@@ -120,18 +109,6 @@
static void SetString(std::string_view key, std::string_view value);
/**
- * Puts the given string into the preferences table.
- *
- * The value may not have quotation marks, nor may the key have any whitespace
- * nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetString instead.")
- static void PutString(std::string_view key, std::string_view value);
-
- /**
* Puts the given string into the preferences table if it doesn't
* already exist.
*/
@@ -148,17 +125,6 @@
static void SetInt(std::string_view key, int value);
/**
- * Puts the given int into the preferences table.
- *
- * The key may not have any whitespace nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetInt instead.")
- static void PutInt(std::string_view key, int value);
-
- /**
* Puts the given int into the preferences table if it doesn't
* already exist.
*/
@@ -175,17 +141,6 @@
static void SetDouble(std::string_view key, double value);
/**
- * Puts the given double into the preferences table.
- *
- * The key may not have any whitespace nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetDouble instead.")
- static void PutDouble(std::string_view key, double value);
-
- /**
* Puts the given double into the preferences table if it doesn't
* already exist.
*/
@@ -202,17 +157,6 @@
static void SetFloat(std::string_view key, float value);
/**
- * Puts the given float into the preferences table.
- *
- * The key may not have any whitespace nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetFloat instead.")
- static void PutFloat(std::string_view key, float value);
-
- /**
* Puts the given float into the preferences table if it doesn't
* already exist.
*/
@@ -229,17 +173,6 @@
static void SetBoolean(std::string_view key, bool value);
/**
- * Puts the given boolean into the preferences table.
- *
- * The key may not have any whitespace nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetBoolean instead.")
- static void PutBoolean(std::string_view key, bool value);
-
- /**
* Puts the given boolean into the preferences table if it doesn't
* already exist.
*/
@@ -256,17 +189,6 @@
static void SetLong(std::string_view key, int64_t value);
/**
- * Puts the given long (int64_t) into the preferences table.
- *
- * The key may not have any whitespace nor an equals sign.
- *
- * @param key the key
- * @param value the value
- */
- WPI_DEPRECATED("Use SetLong instead.")
- static void PutLong(std::string_view key, int64_t value);
-
- /**
* Puts the given long into the preferences table if it doesn't
* already exist.
*/
diff --git a/wpilibc/src/main/native/include/frc/RobotBase.h b/wpilibc/src/main/native/include/frc/RobotBase.h
index 70c6093..3ff4617 100644
--- a/wpilibc/src/main/native/include/frc/RobotBase.h
+++ b/wpilibc/src/main/native/include/frc/RobotBase.h
@@ -11,7 +11,6 @@
#include <hal/HALBase.h>
#include <hal/Main.h>
#include <wpi/condition_variable.h>
-#include <wpi/deprecated.h>
#include <wpi/mutex.h>
#include "frc/Errors.h"
@@ -22,6 +21,9 @@
int RunHALInitialization();
namespace impl {
+#ifndef __FRC_ROBORIO__
+void ResetMotorSafety();
+#endif
template <class Robot>
void RunRobot(wpi::mutex& m, Robot** robot) {
@@ -35,7 +37,7 @@
} catch (const frc::RuntimeError& e) {
e.Report();
FRC_ReportError(
- err::Error, "{}",
+ err::Error,
"The robot program quit unexpectedly."
" This is usually due to a code error.\n"
" The above stacktrace can help determine where the error occurred.\n"
@@ -104,6 +106,9 @@
impl::RunRobot<Robot>(m, &robot);
}
+#ifndef __FRC_ROBORIO__
+ frc::impl::ResetMotorSafety();
+#endif
HAL_Shutdown();
return 0;
@@ -156,16 +161,6 @@
*
* @return True if the robot is currently operating in Tele-Op mode as
* determined by the field controls.
- * @deprecated Use IsTeleop() instead.
- */
- WPI_DEPRECATED("Use IsTeleop() instead")
- bool IsOperatorControl() const;
-
- /**
- * Determine if the robot is currently in Operator Control mode.
- *
- * @return True if the robot is currently operating in Tele-Op mode as
- * determined by the field controls.
*/
bool IsTeleop() const;
@@ -173,16 +168,6 @@
* Determine if the robot is current in Operator Control mode and enabled.
*
* @return True if the robot is currently operating in Tele-Op mode while
- * enabled as determined by the field-controls.
- * @deprecated Use IsTeleopEnabled() instead.
- */
- WPI_DEPRECATED("Use IsTeleopEnabled() instead")
- bool IsOperatorControlEnabled() const;
-
- /**
- * Determine if the robot is current in Operator Control mode and enabled.
- *
- * @return True if the robot is currently operating in Tele-Op mode while
* wnabled as determined by the field-controls.
*/
bool IsTeleopEnabled() const;
@@ -196,14 +181,6 @@
bool IsTest() const;
/**
- * Indicates if new data is available from the driver station.
- *
- * @return Has new data arrived over the network since the last time this
- * function was called?
- */
- bool IsNewDataAvailable() const;
-
- /**
* Gets the ID of the main robot thread.
*/
static std::thread::id GetThreadId();
@@ -237,7 +214,9 @@
*
* @return If the robot is running in simulation.
*/
- static constexpr bool IsSimulation() { return !IsReal(); }
+ static constexpr bool IsSimulation() {
+ return !IsReal();
+ }
/**
* Constructor for a generic robot program.
diff --git a/wpilibc/src/main/native/include/frc/RobotController.h b/wpilibc/src/main/native/include/frc/RobotController.h
index e9750f0..c020d34 100644
--- a/wpilibc/src/main/native/include/frc/RobotController.h
+++ b/wpilibc/src/main/native/include/frc/RobotController.h
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <string>
+
#include <units/voltage.h>
namespace frc {
@@ -43,6 +45,24 @@
static int64_t GetFPGARevision();
/**
+ * Return the serial number of the roboRIO.
+ *
+ * @return The serial number of the roboRIO.
+ */
+ static std::string GetSerialNumber();
+
+ /**
+ * Return the comments from the roboRIO web interface.
+ *
+ * The comments string is cached after the first call to this function on the
+ * RoboRIO - restart the robot code to reload the comments string after
+ * changing it in the web interface.
+ *
+ * @return The comments from the roboRIO web interface.
+ */
+ static std::string GetComments();
+
+ /**
* Read the microsecond-resolution timer on the FPGA.
*
* @return The current time in microseconds according to the FPGA (since FPGA
diff --git a/wpilibc/src/main/native/include/frc/RobotState.h b/wpilibc/src/main/native/include/frc/RobotState.h
index cb97b13..0489b9b 100644
--- a/wpilibc/src/main/native/include/frc/RobotState.h
+++ b/wpilibc/src/main/native/include/frc/RobotState.h
@@ -4,8 +4,6 @@
#pragma once
-#include <wpi/deprecated.h>
-
namespace frc {
class RobotState {
@@ -15,8 +13,6 @@
static bool IsDisabled();
static bool IsEnabled();
static bool IsEStopped();
- WPI_DEPRECATED("Use IsTeleop() instead")
- static bool IsOperatorControl();
static bool IsTeleop();
static bool IsAutonomous();
static bool IsTest();
diff --git a/wpilibc/src/main/native/include/frc/SPI.h b/wpilibc/src/main/native/include/frc/SPI.h
index 4f12cbe..0d5b468 100644
--- a/wpilibc/src/main/native/include/frc/SPI.h
+++ b/wpilibc/src/main/native/include/frc/SPI.h
@@ -7,11 +7,11 @@
#include <stdint.h>
#include <memory>
+#include <span>
#include <hal/SPITypes.h>
#include <units/time.h>
#include <wpi/deprecated.h>
-#include <wpi/span.h>
namespace frc {
@@ -27,6 +27,12 @@
class SPI {
public:
enum Port { kOnboardCS0 = 0, kOnboardCS1, kOnboardCS2, kOnboardCS3, kMXP };
+ enum Mode {
+ kMode0 = HAL_SPI_kMode0,
+ kMode1 = HAL_SPI_kMode1,
+ kMode2 = HAL_SPI_kMode2,
+ kMode3 = HAL_SPI_kMode3
+ };
/**
* Constructor
@@ -55,60 +61,73 @@
/**
* Configure the order that bits are sent and received on the wire
* to be most significant bit first.
+ *
+ * @deprecated Does not work, will be removed.
*/
+ WPI_DEPRECATED("Not supported by roboRIO.")
void SetMSBFirst();
/**
* Configure the order that bits are sent and received on the wire
* to be least significant bit first.
+ *
+ * @deprecated Does not work, will be removed.
*/
+ WPI_DEPRECATED("Not supported by roboRIO.")
void SetLSBFirst();
/**
* Configure that the data is stable on the leading edge and the data
* changes on the trailing edge.
+ *
+ * @deprecated Use SetMode() instead.
*/
+ WPI_DEPRECATED("Use SetMode() instead")
void SetSampleDataOnLeadingEdge();
/**
* Configure that the data is stable on the trailing edge and the data
* changes on the leading edge.
+ *
+ * @deprecated Use SetMode() instead.
*/
+ WPI_DEPRECATED("Use SetMode() instead")
void SetSampleDataOnTrailingEdge();
/**
- * Configure that the data is stable on the falling edge and the data
- * changes on the rising edge.
- *
- * @deprecated Use SetSampleDataOnTrailingEdge() instead.
- *
- */
- WPI_DEPRECATED("Use SetSampleDataOnTrailingEdge instead.")
- void SetSampleDataOnFalling();
-
- /**
- * Configure that the data is stable on the rising edge and the data
- * changes on the falling edge.
- *
- * @deprecated Use SetSampleDataOnLeadingEdge() instead.
- *
- */
- WPI_DEPRECATED("Use SetSampleDataOnLeadingEdge instead")
- void SetSampleDataOnRising();
-
- /**
* Configure the clock output line to be active low.
* This is sometimes called clock polarity high or clock idle high.
+ *
+ * @deprecated Use SetMode() instead.
*/
+ WPI_DEPRECATED("Use SetMode() instead")
void SetClockActiveLow();
/**
* Configure the clock output line to be active high.
* This is sometimes called clock polarity low or clock idle low.
+ *
+ * @deprecated Use SetMode() instead.
*/
+ WPI_DEPRECATED("Use SetMode() instead")
void SetClockActiveHigh();
/**
+ * Sets the mode for the SPI device.
+ *
+ * <p>Mode 0 is Clock idle low, data sampled on rising edge
+ *
+ * <p>Mode 1 is Clock idle low, data sampled on falling edge
+ *
+ * <p>Mode 2 is Clock idle high, data sampled on falling edge
+ *
+ * <p>Mode 3 is Clock idle high, data sampled on rising edge
+ *
+ * @param mode The mode to set.
+ */
+ void SetMode(Mode mode);
+
+ /**
* Configure the chip select line to be active high.
*/
void SetChipSelectActiveHigh();
@@ -177,7 +196,7 @@
* @param dataToSend data to send (maximum 16 bytes)
* @param zeroSize number of zeros to send after the data
*/
- void SetAutoTransmitData(wpi::span<const uint8_t> dataToSend, int zeroSize);
+ void SetAutoTransmitData(std::span<const uint8_t> dataToSend, int zeroSize);
/**
* Start running the automatic SPI transfer engine at a periodic rate.
@@ -190,19 +209,6 @@
void StartAutoRate(units::second_t period);
/**
- * Start running the automatic SPI transfer engine at a periodic rate.
- *
- * InitAuto() and SetAutoTransmitData() must be called before calling this
- * function.
- *
- * @deprecated use unit-safe StartAutoRate(units::second_t period) instead.
- *
- * @param period period between transfers, in seconds (us resolution)
- */
- WPI_DEPRECATED("Use StartAutoRate with unit-safety instead")
- void StartAutoRate(double period);
-
- /**
* Start running the automatic SPI transfer engine when a trigger occurs.
*
* InitAuto() and SetAutoTransmitData() must be called before calling this
@@ -287,31 +293,6 @@
int dataSize, bool isSigned, bool bigEndian);
/**
- * Initialize the accumulator.
- *
- * @deprecated Use unit-safe version instead.
- * InitAccumulator(units::second_t period, int cmd, int <!--
- * --> xferSize, int validMask, int validValue, int dataShift, <!--
- * --> int dataSize, bool isSigned, bool bigEndian)
- *
- * @param period Time between reads
- * @param cmd SPI command to send to request data
- * @param xferSize SPI transfer size, in bytes
- * @param validMask Mask to apply to received data for validity checking
- * @param validValue After valid_mask is applied, required matching value for
- * validity checking
- * @param dataShift Bit shift to apply to received data to get actual data
- * value
- * @param dataSize Size (in bits) of data field
- * @param isSigned Is data field signed?
- * @param bigEndian Is device big endian?
- */
- WPI_DEPRECATED("Use InitAccumulator with unit-safety instead")
- void InitAccumulator(double period, int cmd, int xferSize, int validMask,
- int validValue, int dataShift, int dataSize,
- bool isSigned, bool bigEndian);
-
- /**
* Frees the accumulator.
*/
void FreeAccumulator();
@@ -404,9 +385,7 @@
protected:
hal::SPIPort m_port;
- bool m_msbFirst = false; // Default little-endian
- bool m_sampleOnTrailing = false; // Default data updated on falling edge
- bool m_clockIdleHigh = false; // Default clock active high
+ HAL_SPIMode m_mode = HAL_SPIMode::HAL_SPI_kMode0;
private:
void Init();
diff --git a/wpilibc/src/main/native/include/frc/SpeedController.h b/wpilibc/src/main/native/include/frc/SpeedController.h
deleted file mode 100644
index 8473015..0000000
--- a/wpilibc/src/main/native/include/frc/SpeedController.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <units/voltage.h>
-#include <wpi/deprecated.h>
-
-namespace frc {
-
-/**
- * Interface for speed controlling devices.
- *
- * @deprecated Use MotorController.
- */
-class WPI_DEPRECATED("use MotorController") SpeedController {
- public:
- virtual ~SpeedController() = default;
-
- /**
- * Common interface for setting the speed of a speed controller.
- *
- * @param speed The speed to set. Value should be between -1.0 and 1.0.
- */
- virtual void Set(double speed) = 0;
-
- /**
- * Sets the voltage output of the SpeedController. Compensates for
- * the current bus voltage to ensure that the desired voltage is output even
- * if the battery voltage is below 12V - highly useful when the voltage
- * outputs are "meaningful" (e.g. they come from a feedforward calculation).
- *
- * <p>NOTE: This function *must* be called regularly in order for voltage
- * compensation to work properly - unlike the ordinary set function, it is not
- * "set it and forget it."
- *
- * @param output The voltage to output.
- */
- virtual void SetVoltage(units::volt_t output);
-
- /**
- * Common interface for getting the current set speed of a speed controller.
- *
- * @return The current set speed. Value is between -1.0 and 1.0.
- */
- virtual double Get() const = 0;
-
- /**
- * Common interface for inverting direction of a speed controller.
- *
- * @param isInverted The state of inversion, true is inverted.
- */
- virtual void SetInverted(bool isInverted) = 0;
-
- /**
- * Common interface for returning the inversion state of a speed controller.
- *
- * @return isInverted The state of inversion, true is inverted.
- */
- virtual bool GetInverted() const = 0;
-
- /**
- * Common interface for disabling a motor.
- */
- virtual void Disable() = 0;
-
- /**
- * Common interface to stop the motor until Set is called again.
- */
- virtual void StopMotor() = 0;
-};
-
-} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h
deleted file mode 100644
index 5a097b5..0000000
--- a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <functional>
-#include <vector>
-
-#include <wpi/deprecated.h>
-#include <wpi/sendable/Sendable.h>
-#include <wpi/sendable/SendableHelper.h>
-
-#include "frc/motorcontrol/MotorController.h"
-
-namespace frc {
-
-/**
- * Allows multiple SpeedController objects to be linked together.
- *
- * @deprecated Use MotorControllerGroup.
- */
-class WPI_DEPRECATED("use MotorControllerGroup") SpeedControllerGroup
- : public wpi::Sendable,
- public MotorController,
- public wpi::SendableHelper<SpeedControllerGroup> {
- public:
- template <class... SpeedControllers>
- explicit SpeedControllerGroup(SpeedController& speedController,
- SpeedControllers&... speedControllers);
- explicit SpeedControllerGroup(
- std::vector<std::reference_wrapper<SpeedController>>&& speedControllers);
-
- SpeedControllerGroup(SpeedControllerGroup&&) = default;
- SpeedControllerGroup& operator=(SpeedControllerGroup&&) = default;
-
- void Set(double speed) override;
- double Get() const override;
- void SetInverted(bool isInverted) override;
- bool GetInverted() const override;
- void Disable() override;
- void StopMotor() override;
-
- void InitSendable(wpi::SendableBuilder& builder) override;
-
- private:
- bool m_isInverted = false;
- std::vector<std::reference_wrapper<SpeedController>> m_speedControllers;
-
- void Initialize();
-};
-
-} // namespace frc
-
-#include "frc/SpeedControllerGroup.inc"
diff --git a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc
deleted file mode 100644
index d5f17b4..0000000
--- a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <functional>
-#include <vector>
-
-#include "frc/SpeedControllerGroup.h"
-
-namespace frc {
-
-template <class... SpeedControllers>
-SpeedControllerGroup::SpeedControllerGroup(
- SpeedController& speedController, SpeedControllers&... speedControllers)
- : m_speedControllers(std::vector<std::reference_wrapper<SpeedController>>{
- speedController, speedControllers...}) {
- Initialize();
-}
-
-} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h b/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h
index 03cc4f8..fbe0fca 100644
--- a/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h
+++ b/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h
@@ -21,6 +21,9 @@
*/
class SynchronousInterrupt {
public:
+ /**
+ * Event trigger combinations for a synchronous interrupt.
+ */
enum WaitResult {
kTimeout = 0x0,
kRisingEdge = 0x1,
@@ -62,7 +65,7 @@
*
* @param timeout The timeout to wait for. 0s or less will return immediately.
* @param ignorePrevious True to ignore any previous interrupts, false to
- * return interrupt value if an interrupt has occured since last call.
+ * return interrupt value if an interrupt has occurred since last call.
* @return The edge(s) that were triggered, or timeout.
*/
WaitResult WaitForInterrupt(units::second_t timeout,
diff --git a/wpilibc/src/main/native/include/frc/TimedRobot.h b/wpilibc/src/main/native/include/frc/TimedRobot.h
index cc64c03..f32e748 100644
--- a/wpilibc/src/main/native/include/frc/TimedRobot.h
+++ b/wpilibc/src/main/native/include/frc/TimedRobot.h
@@ -11,7 +11,6 @@
#include <hal/Types.h>
#include <units/math.h>
#include <units/time.h>
-#include <wpi/deprecated.h>
#include <wpi/priority_queue.h>
#include "frc/IterativeRobotBase.h"
@@ -45,17 +44,6 @@
/**
* Constructor for TimedRobot.
*
- * @deprecated use unit safe constructor instead.
- * TimedRobot(units::second_t period = kDefaultPeriod)
- *
- * @param period Period in seconds.
- */
- WPI_DEPRECATED("Use constructor with unit-safety instead.")
- explicit TimedRobot(double period);
-
- /**
- * Constructor for TimedRobot.
- *
* @param period Period.
*/
explicit TimedRobot(units::second_t period = kDefaultPeriod);
diff --git a/wpilibc/src/main/native/include/frc/Timer.h b/wpilibc/src/main/native/include/frc/Timer.h
index 0aed658..14674ee 100644
--- a/wpilibc/src/main/native/include/frc/Timer.h
+++ b/wpilibc/src/main/native/include/frc/Timer.h
@@ -5,7 +5,6 @@
#pragma once
#include <units/time.h>
-#include <wpi/deprecated.h>
namespace frc {
@@ -101,18 +100,6 @@
*
* @param period The period to check for.
* @return True if the period has passed.
- * @deprecated Use AdvanceIfElapsed() instead.
- */
- WPI_DEPRECATED("Use AdvanceIfElapsed() instead.")
- bool HasPeriodPassed(units::second_t period);
-
- /**
- * Check if the period specified has passed and if it has, advance the start
- * time by that period. This is useful to decide if it's time to do periodic
- * work without drifting later by the time it took to get around to checking.
- *
- * @param period The period to check for.
- * @return True if the period has passed.
*/
bool AdvanceIfElapsed(units::second_t period);
diff --git a/wpilibc/src/main/native/include/frc/Ultrasonic.h b/wpilibc/src/main/native/include/frc/Ultrasonic.h
index 253192f..137a5b7 100644
--- a/wpilibc/src/main/native/include/frc/Ultrasonic.h
+++ b/wpilibc/src/main/native/include/frc/Ultrasonic.h
@@ -164,11 +164,8 @@
*/
static void UltrasonicChecker();
- // Time (sec) for the ping trigger pulse.
- static constexpr double kPingTime = 10 * 1e-6;
-
- // Priority that the ultrasonic round robin task runs.
- static constexpr int kPriority = 64;
+ // Time (usec) for the ping trigger pulse.
+ static constexpr auto kPingTime = 10_us;
// Max time (ms) between readings.
static constexpr auto kMaxUltrasonicTime = 0.1_s;
diff --git a/wpilibc/src/main/native/include/frc/XboxController.h b/wpilibc/src/main/native/include/frc/XboxController.h
index cbdc7d7..370e46e 100644
--- a/wpilibc/src/main/native/include/frc/XboxController.h
+++ b/wpilibc/src/main/native/include/frc/XboxController.h
@@ -97,6 +97,24 @@
bool GetRightBumperReleased();
/**
+ * Constructs an event instance around the left bumper's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the left bumper's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent LeftBumper(EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the right bumper's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the right bumper's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent RightBumper(EventLoop* loop) const;
+
+ /**
* Read the value of the left stick button (LSB) on the controller.
*/
bool GetLeftStickButton() const;
@@ -127,6 +145,24 @@
bool GetRightStickButtonReleased();
/**
+ * Constructs an event instance around the left stick's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the left stick's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent LeftStick(EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the right stick's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the right stick's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent RightStick(EventLoop* loop) const;
+
+ /**
* Read the value of the A button on the controller.
*
* @return The state of the button.
@@ -148,6 +184,15 @@
bool GetAButtonReleased();
/**
+ * Constructs an event instance around the A button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the A button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent A(EventLoop* loop) const;
+
+ /**
* Read the value of the B button on the controller.
*
* @return The state of the button.
@@ -169,6 +214,15 @@
bool GetBButtonReleased();
/**
+ * Constructs an event instance around the B button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the B button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent B(EventLoop* loop) const;
+
+ /**
* Read the value of the X button on the controller.
*
* @return The state of the button.
@@ -190,6 +244,15 @@
bool GetXButtonReleased();
/**
+ * Constructs an event instance around the X button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the X button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent X(EventLoop* loop) const;
+
+ /**
* Read the value of the Y button on the controller.
*
* @return The state of the button.
@@ -211,6 +274,15 @@
bool GetYButtonReleased();
/**
+ * Constructs an event instance around the Y button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the Y button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Y(EventLoop* loop) const;
+
+ /**
* Whether the Y button was released since the last check.
*
* @return Whether the button was released since the last check.
@@ -232,6 +304,15 @@
bool GetBackButtonReleased();
/**
+ * Constructs an event instance around the back button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the back button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Back(EventLoop* loop) const;
+
+ /**
* Read the value of the start button on the controller.
*
* @return The state of the button.
@@ -252,6 +333,59 @@
*/
bool GetStartButtonReleased();
+ /**
+ * Constructs an event instance around the start button's digital signal.
+ *
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance representing the start button's digital signal
+ * attached to the given loop.
+ */
+ BooleanEvent Start(EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the axis value of the left trigger. The
+ * returned trigger will be true when the axis value is greater than {@code
+ * threshold}.
+ * @param threshold the minimum axis value for the returned event to be true.
+ * This value should be in the range [0, 1] where 0 is the unpressed state of
+ * the axis.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the left trigger's axis exceeds
+ * the provided threshold, attached to the given event loop
+ */
+ BooleanEvent LeftTrigger(double threshold, EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the axis value of the left trigger.
+ * The returned trigger will be true when the axis value is greater than 0.5.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the right trigger's axis
+ * exceeds 0.5, attached to the given event loop
+ */
+ BooleanEvent LeftTrigger(EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the axis value of the right trigger.
+ * The returned trigger will be true when the axis value is greater than
+ * {@code threshold}.
+ * @param threshold the minimum axis value for the returned event to be true.
+ * This value should be in the range [0, 1] where 0 is the unpressed state of
+ * the axis.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the right trigger's axis
+ * exceeds the provided threshold, attached to the given event loop
+ */
+ BooleanEvent RightTrigger(double threshold, EventLoop* loop) const;
+
+ /**
+ * Constructs an event instance around the axis value of the right trigger.
+ * The returned trigger will be true when the axis value is greater than 0.5.
+ * @param loop the event loop instance to attach the event to.
+ * @return an event instance that is true when the right trigger's axis
+ * exceeds 0.5, attached to the given event loop
+ */
+ BooleanEvent RightTrigger(EventLoop* loop) const;
+
struct Button {
static constexpr int kLeftBumper = 5;
static constexpr int kRightBumper = 6;
diff --git a/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h b/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h
index 7009eb9..2e701a3 100644
--- a/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h
+++ b/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h
@@ -13,18 +13,7 @@
namespace frc {
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-class SpeedController;
+class MotorController;
/**
* A class for driving differential drive/skid-steer drive platforms such as
@@ -81,21 +70,22 @@
* | |
* </pre>
*
- * Each Drive() function provides different inverse kinematic relations for a
- * differential drive robot. Motor outputs for the right side are negated, so
- * motor direction inversion by the user is usually unnecessary.
+ * Each drive function provides different inverse kinematic relations for a
+ * differential drive robot.
*
- * This library uses the NED axes convention (North-East-Down as external
- * reference in the world frame):
- * http://www.nuclearprojects.com/ins/images/axis_big.png.
- *
- * The positive X axis points ahead, the positive Y axis points to the right,
- * and the positive Z axis points down. Rotations follow the right-hand rule, so
- * clockwise rotation around the Z axis is positive.
+ * This library uses the NWU axes convention (North-West-Up as external
+ * reference in the world frame). The positive X axis points ahead, the positive
+ * Y axis points to the left, and the positive Z axis points up. Rotations
+ * follow the right-hand rule, so counterclockwise rotation around the Z axis is
+ * positive.
*
* Inputs smaller then 0.02 will be set to 0, and larger values will be scaled
* so that the full range is still used. This deadband value can be changed
* with SetDeadband().
+ *
+ * MotorSafety is enabled by default. The tankDrive, arcadeDrive,
+ * or curvatureDrive methods should be called periodically to avoid Motor
+ * Safety timeouts.
*/
class DifferentialDrive : public RobotDriveBase,
public wpi::Sendable,
@@ -117,7 +107,7 @@
* To pass multiple motors per side, use a MotorControllerGroup. If a motor
* needs to be inverted, do so before passing it in.
*/
- DifferentialDrive(SpeedController& leftMotor, SpeedController& rightMotor);
+ DifferentialDrive(MotorController& leftMotor, MotorController& rightMotor);
~DifferentialDrive() override = default;
@@ -133,7 +123,7 @@
* @param xSpeed The speed at which the robot should drive along the X
* axis [-1.0..1.0]. Forward is positive.
* @param zRotation The rotation rate of the robot around the Z axis
- * [-1.0..1.0]. Clockwise is positive.
+ * [-1.0..1.0]. Counterclockwise is positive.
* @param squareInputs If set, decreases the input sensitivity at low speeds.
*/
void ArcadeDrive(double xSpeed, double zRotation, bool squareInputs = true);
@@ -147,8 +137,8 @@
*
* @param xSpeed The robot's speed along the X axis [-1.0..1.0].
* Forward is positive.
- * @param zRotation The normalized curvature [-1.0..1.0]. Clockwise is
- * positive.
+ * @param zRotation The normalized curvature [-1.0..1.0].
+ * Counterclockwise is positive.
* @param allowTurnInPlace If set, overrides constant-curvature turning for
* turn-in-place maneuvers. zRotation will control
* turning rate instead of curvature.
@@ -220,16 +210,8 @@
void InitSendable(wpi::SendableBuilder& builder) override;
private:
- SpeedController* m_leftMotor;
- SpeedController* m_rightMotor;
+ MotorController* m_leftMotor;
+ MotorController* m_rightMotor;
};
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#elif defined(__clang__)
-#pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h b/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h
deleted file mode 100644
index d4c5c5c..0000000
--- a/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-#include <wpi/sendable/Sendable.h>
-#include <wpi/sendable/SendableHelper.h>
-
-#include "frc/drive/RobotDriveBase.h"
-#include "frc/drive/Vector2d.h"
-
-namespace frc {
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-class SpeedController;
-
-/**
- * A class for driving Killough drive platforms.
- *
- * Killough drives are triangular with one omni wheel on each corner.
- *
- * Drive base diagram:
- * <pre>
- * /_____\
- * / \ / \
- * \ /
- * ---
- * </pre>
- *
- * Each Drive() function provides different inverse kinematic relations for a
- * Killough drive. The default wheel vectors are parallel to their respective
- * opposite sides, but can be overridden. See the constructor for more
- * information.
- *
- * This library uses the NED axes convention (North-East-Down as external
- * reference in the world frame):
- * http://www.nuclearprojects.com/ins/images/axis_big.png.
- *
- * The positive X axis points ahead, the positive Y axis points right, and the
- * and the positive Z axis points down. Rotations follow the right-hand rule, so
- * clockwise rotation around the Z axis is positive.
- */
-class KilloughDrive : public RobotDriveBase,
- public wpi::Sendable,
- public wpi::SendableHelper<KilloughDrive> {
- public:
- static constexpr double kDefaultLeftMotorAngle = 60.0;
- static constexpr double kDefaultRightMotorAngle = 120.0;
- static constexpr double kDefaultBackMotorAngle = 270.0;
-
- /**
- * Wheel speeds for a Killough drive.
- *
- * Uses normalized voltage [-1.0..1.0].
- */
- struct WheelSpeeds {
- double left = 0.0;
- double right = 0.0;
- double back = 0.0;
- };
-
- /**
- * Construct a Killough drive with the given motors and default motor angles.
- *
- * The default motor angles make the wheels on each corner parallel to their
- * respective opposite sides.
- *
- * If a motor needs to be inverted, do so before passing it in.
- *
- * @param leftMotor The motor on the left corner.
- * @param rightMotor The motor on the right corner.
- * @param backMotor The motor on the back corner.
- */
- KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
- SpeedController& backMotor);
-
- /**
- * Construct a Killough drive with the given motors.
- *
- * Angles are measured in degrees clockwise from the positive X axis.
- *
- * @param leftMotor The motor on the left corner.
- * @param rightMotor The motor on the right corner.
- * @param backMotor The motor on the back corner.
- * @param leftMotorAngle The angle of the left wheel's forward direction of
- * travel.
- * @param rightMotorAngle The angle of the right wheel's forward direction of
- * travel.
- * @param backMotorAngle The angle of the back wheel's forward direction of
- * travel.
- */
- KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
- SpeedController& backMotor, double leftMotorAngle,
- double rightMotorAngle, double backMotorAngle);
-
- ~KilloughDrive() override = default;
-
- KilloughDrive(KilloughDrive&&) = default;
- KilloughDrive& operator=(KilloughDrive&&) = default;
-
- /**
- * Drive method for Killough platform.
- *
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
- *
- * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
- * positive.
- * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
- * positive.
- * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
- * @param gyroAngle The current angle reading from the gyro in degrees around
- * the Z axis. Use this to implement field-oriented controls.
- */
- void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
- double gyroAngle = 0.0);
-
- /**
- * Drive method for Killough platform.
- *
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
- *
- * @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
- * positive.
- * @param angle The angle around the Z axis at which the robot drives in
- * degrees [-180..180].
- * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
- */
- void DrivePolar(double magnitude, double angle, double zRotation);
-
- /**
- * Cartesian inverse kinematics for Killough platform.
- *
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
- *
- * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
- * positive.
- * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
- * positive.
- * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
- * @param gyroAngle The current angle reading from the gyro in degrees around
- * the Z axis. Use this to implement field-oriented controls.
- * @return Wheel speeds [-1.0..1.0].
- */
- WheelSpeeds DriveCartesianIK(double ySpeed, double xSpeed, double zRotation,
- double gyroAngle = 0.0);
-
- void StopMotor() override;
- std::string GetDescription() const override;
-
- void InitSendable(wpi::SendableBuilder& builder) override;
-
- private:
- SpeedController* m_leftMotor;
- SpeedController* m_rightMotor;
- SpeedController* m_backMotor;
-
- Vector2d m_leftVec;
- Vector2d m_rightVec;
- Vector2d m_backVec;
-
- bool reported = false;
-};
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#elif defined(__clang__)
-#pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h b/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h
index 757ae67..f4c28f4 100644
--- a/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h
+++ b/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h
@@ -7,25 +7,16 @@
#include <memory>
#include <string>
+#include <units/angle.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
#include "frc/drive/RobotDriveBase.h"
+#include "frc/geometry/Rotation2d.h"
namespace frc {
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-class SpeedController;
+class MotorController;
/**
* A class for driving Mecanum drive platforms.
@@ -46,9 +37,11 @@
* Each Drive() function provides different inverse kinematic relations for a
* Mecanum drive robot.
*
- * The positive Y axis points ahead, the positive X axis points to the right,
- * and the positive Z axis points down. Rotations follow the right-hand rule, so
- * clockwise rotation around the Z axis is positive.
+ * This library uses the NWU axes convention (North-West-Up as external
+ * reference in the world frame). The positive X axis points ahead, the positive
+ * Y axis points to the left, and the positive Z axis points up. Rotations
+ * follow the right-hand rule, so counterclockwise rotation around the Z axis is
+ * positive.
*
* Note: the axis conventions used in this class differ from DifferentialDrive.
* This may change in a future year's WPILib release.
@@ -57,15 +50,8 @@
* so that the full range is still used. This deadband value can be changed
* with SetDeadband().
*
- * RobotDrive porting guide:
- * <br>DriveCartesian(double, double, double, double) is equivalent to
- * RobotDrive's MecanumDrive_Cartesian(double, double, double, double)
- * if a deadband of 0 is used, and the ySpeed and gyroAngle values are inverted
- * compared to RobotDrive (eg DriveCartesian(xSpeed, -ySpeed, zRotation,
- * -gyroAngle).
- * <br>DrivePolar(double, double, double) is equivalent to
- * RobotDrive's MecanumDrive_Polar(double, double, double) if a
- * deadband of 0 is used.
+ * MotorSafety is enabled by default. The DriveCartesian or DrivePolar
+ * methods should be called periodically to avoid Motor Safety timeouts.
*/
class MecanumDrive : public RobotDriveBase,
public wpi::Sendable,
@@ -88,9 +74,9 @@
*
* If a motor needs to be inverted, do so before passing it in.
*/
- MecanumDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor,
- SpeedController& frontRightMotor,
- SpeedController& rearRightMotor);
+ MecanumDrive(MotorController& frontLeftMotor, MotorController& rearLeftMotor,
+ MotorController& frontRightMotor,
+ MotorController& rearRightMotor);
~MecanumDrive() override = default;
@@ -100,54 +86,54 @@
/**
* Drive method for Mecanum platform.
*
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
+ * Angles are measured counterclockwise from the positive X axis. The robot's
+ * speed is independent from its angle or rotation rate.
*
- * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Forward is
+ * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
* positive.
- * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Right is
+ * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Left is
* positive.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
- * @param gyroAngle The current angle reading from the gyro in degrees around
- * the Z axis. Use this to implement field-oriented controls.
+ * Counterclockwise is positive.
+ * @param gyroAngle The gyro heading around the Z axis. Use this to implement
+ * field-oriented controls.
*/
- void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
- double gyroAngle = 0.0);
+ void DriveCartesian(double xSpeed, double ySpeed, double zRotation,
+ Rotation2d gyroAngle = 0_rad);
/**
* Drive method for Mecanum platform.
*
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
+ * Angles are measured counterclockwise from the positive X axis. The robot's
+ * speed is independent from its angle or rotation rate.
*
* @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
* positive.
- * @param angle The angle around the Z axis at which the robot drives in
- * degrees [-180..180].
+ * @param angle The angle around the Z axis at which the robot drives.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
+ * Counterclockwise is positive.
*/
- void DrivePolar(double magnitude, double angle, double zRotation);
+ void DrivePolar(double magnitude, Rotation2d angle, double zRotation);
/**
* Cartesian inverse kinematics for Mecanum platform.
*
- * Angles are measured clockwise from the positive X axis. The robot's speed
- * is independent from its angle or rotation rate.
+ * Angles are measured counterclockwise from the positive X axis. The robot's
+ * speed is independent from its angle or rotation rate.
*
- * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Forward is
+ * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
* positive.
- * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Right is
+ * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Left is
* positive.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
- * Clockwise is positive.
- * @param gyroAngle The current angle reading from the gyro in degrees around
- * the Z axis. Use this to implement field-oriented controls.
+ * Counterclockwise is positive.
+ * @param gyroAngle The gyro heading around the Z axis. Use this to implement
+ * field-oriented controls.
* @return Wheel speeds [-1.0..1.0].
*/
- static WheelSpeeds DriveCartesianIK(double ySpeed, double xSpeed,
- double zRotation, double gyroAngle = 0.0);
+ static WheelSpeeds DriveCartesianIK(double xSpeed, double ySpeed,
+ double zRotation,
+ Rotation2d gyroAngle = 0_rad);
void StopMotor() override;
std::string GetDescription() const override;
@@ -155,20 +141,12 @@
void InitSendable(wpi::SendableBuilder& builder) override;
private:
- SpeedController* m_frontLeftMotor;
- SpeedController* m_rearLeftMotor;
- SpeedController* m_frontRightMotor;
- SpeedController* m_rearRightMotor;
+ MotorController* m_frontLeftMotor;
+ MotorController* m_rearLeftMotor;
+ MotorController* m_frontRightMotor;
+ MotorController* m_rearRightMotor;
bool reported = false;
};
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#elif defined(__clang__)
-#pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h b/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h
index 8ce5636..b3fb56b 100644
--- a/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h
+++ b/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h
@@ -5,17 +5,17 @@
#pragma once
#include <memory>
+#include <span>
#include <string>
-#include <wpi/deprecated.h>
-#include <wpi/span.h>
-
#include "frc/MotorSafety.h"
namespace frc {
/**
* Common base class for drive platforms.
+ *
+ * MotorSafety is enabled by default.
*/
class RobotDriveBase : public MotorSafety {
public:
@@ -71,21 +71,10 @@
protected:
/**
- * Returns 0.0 if the given value is within the specified range around zero.
- * The remaining range between the deadband and 1.0 is scaled from 0.0 to 1.0.
- *
- * @param value value to clip
- * @param deadband range around zero
- * @deprecated Use ApplyDeadband() in frc/MathUtil.h.
- */
- WPI_DEPRECATED("Use ApplyDeadband() in frc/MathUtil.h")
- static double ApplyDeadband(double value, double deadband);
-
- /**
* Renormalize all wheel speeds if the magnitude of any wheel is greater than
* 1.0.
*/
- static void Desaturate(wpi::span<double> wheelSpeeds);
+ static void Desaturate(std::span<double> wheelSpeeds);
double m_deadband = 0.02;
double m_maxOutput = 1.0;
diff --git a/wpilibc/src/main/native/include/frc/drive/Vector2d.h b/wpilibc/src/main/native/include/frc/drive/Vector2d.h
deleted file mode 100644
index 92a3de6..0000000
--- a/wpilibc/src/main/native/include/frc/drive/Vector2d.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-namespace frc {
-
-/**
- * This is a 2D vector struct that supports basic vector operations.
- */
-struct Vector2d {
- Vector2d() = default;
- Vector2d(double x, double y);
-
- /**
- * Rotate a vector in Cartesian space.
- *
- * @param angle angle in degrees by which to rotate vector counter-clockwise.
- */
- void Rotate(double angle);
-
- /**
- * Returns dot product of this vector with argument.
- *
- * @param vec Vector with which to perform dot product.
- */
- double Dot(const Vector2d& vec) const;
-
- /**
- * Returns magnitude of vector.
- */
- double Magnitude() const;
-
- /**
- * Returns scalar projection of this vector onto argument.
- *
- * @param vec Vector onto which to project this vector.
- */
- double ScalarProject(const Vector2d& vec) const;
-
- double x = 0.0;
- double y = 0.0;
-};
-
-} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/event/BooleanEvent.h b/wpilibc/src/main/native/include/frc/event/BooleanEvent.h
new file mode 100644
index 0000000..745a53c
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/event/BooleanEvent.h
@@ -0,0 +1,135 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <frc/filter/Debouncer.h>
+
+#include <functional>
+#include <memory>
+
+#include <units/time.h>
+#include <wpi/FunctionExtras.h>
+
+#include "EventLoop.h"
+
+namespace frc {
+
+/**
+ * This class provides an easy way to link actions to inputs. Each object
+ * represents a boolean condition to which callback actions can be bound using
+ * {@link #IfHigh(std::function<void()>)}.
+ *
+ * <p>These events can easily be composed using factories such as {@link
+ * #operator!},
+ * {@link #operator||}, {@link #operator&&} etc.
+ *
+ * <p>To get an event that activates only when this one changes, see {@link
+ * #Falling()} and {@link #Rising()}.
+ */
+class BooleanEvent {
+ public:
+ /**
+ * Creates a new event with the given condition determining whether it is
+ * active.
+ *
+ * @param loop the loop that polls this event
+ * @param condition returns whether or not the event should be active
+ */
+ BooleanEvent(EventLoop* loop, std::function<bool()> condition);
+
+ /**
+ * Check whether this event is active or not.
+ *
+ * @return true if active.
+ */
+ bool GetAsBoolean() const;
+
+ /**
+ * Bind an action to this event.
+ *
+ * @param action the action to run if this event is active.
+ */
+ void IfHigh(std::function<void()> action);
+
+ operator std::function<bool()>(); // NOLINT
+
+ /**
+ * A method to "downcast" a BooleanEvent instance to a subclass (for example,
+ * to a command-based version of this class).
+ *
+ * @param ctor a method reference to the constructor of the subclass that
+ * accepts the loop as the first parameter and the condition/signal as the
+ * second.
+ * @return an instance of the subclass.
+ */
+ template <class T>
+ T CastTo(std::function<T(EventLoop*, std::function<bool()>)> ctor =
+ [](EventLoop* loop, std::function<bool()> condition) {
+ return T(loop, condition);
+ }) {
+ return ctor(m_loop, m_condition);
+ }
+
+ /**
+ * Creates a new event that is active when this event is inactive, i.e. that
+ * acts as the negation of this event.
+ *
+ * @return the negated event
+ */
+ BooleanEvent operator!();
+
+ /**
+ * Composes this event with another event, returning a new event that is
+ * active when both events are active.
+ *
+ * <p>The new event will use this event's polling loop.
+ *
+ * @param rhs the event to compose with
+ * @return the event that is active when both events are active
+ */
+ BooleanEvent operator&&(std::function<bool()> rhs);
+
+ /**
+ * Composes this event with another event, returning a new event that is
+ * active when either event is active.
+ *
+ * <p>The new event will use this event's polling loop.
+ *
+ * @param rhs the event to compose with
+ * @return the event that is active when either event is active
+ */
+ BooleanEvent operator||(std::function<bool()> rhs);
+
+ /**
+ * Get a new event that events only when this one newly changes to true.
+ *
+ * @return a new event representing when this one newly changes to true.
+ */
+ BooleanEvent Rising();
+
+ /**
+ * Get a new event that triggers only when this one newly changes to false.
+ *
+ * @return a new event representing when this one newly changes to false.
+ */
+ BooleanEvent Falling();
+
+ /**
+ * Creates a new debounced event from this event - it will become active when
+ * this event has been active for longer than the specified period.
+ *
+ * @param debounceTime The debounce period.
+ * @param type The debounce type.
+ * @return The debounced event.
+ */
+ BooleanEvent Debounce(units::second_t debounceTime,
+ frc::Debouncer::DebounceType type =
+ frc::Debouncer::DebounceType::kRising);
+
+ private:
+ EventLoop* m_loop;
+ std::function<bool()> m_condition;
+};
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/event/EventLoop.h b/wpilibc/src/main/native/include/frc/event/EventLoop.h
new file mode 100644
index 0000000..d18fac3
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/event/EventLoop.h
@@ -0,0 +1,42 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+#include <wpi/FunctionExtras.h>
+
+namespace frc {
+/** The loop polling BooleanEvent objects and executing the actions bound to
+ * them. */
+class EventLoop {
+ public:
+ EventLoop();
+
+ EventLoop(const EventLoop&) = delete;
+ EventLoop& operator=(const EventLoop&) = delete;
+
+ /**
+ * Bind a new action to run.
+ *
+ * @param action the action to run.
+ */
+ void Bind(wpi::unique_function<void()> action);
+
+ /**
+ * Poll all bindings.
+ */
+ void Poll();
+
+ /**
+ * Clear all bindings.
+ */
+ void Clear();
+
+ private:
+ std::vector<wpi::unique_function<void()>> m_bindings;
+};
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/event/NetworkBooleanEvent.h b/wpilibc/src/main/native/include/frc/event/NetworkBooleanEvent.h
new file mode 100644
index 0000000..85f7039
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/event/NetworkBooleanEvent.h
@@ -0,0 +1,79 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <memory>
+#include <string_view>
+
+#include "BooleanEvent.h"
+
+namespace nt {
+class BooleanSubscriber;
+class BooleanTopic;
+class NetworkTable;
+class NetworkTableInstance;
+} // namespace nt
+
+namespace frc {
+/**
+ * A Button that uses a NetworkTable boolean field.
+ *
+ * This class is provided by the NewCommands VendorDep
+ */
+class NetworkBooleanEvent : public BooleanEvent {
+ public:
+ /**
+ * Creates a new event with the given boolean topic determining whether it is
+ * active.
+ *
+ * @param loop the loop that polls this event
+ * @param topic The boolean topic that contains the value
+ */
+ NetworkBooleanEvent(EventLoop* loop, nt::BooleanTopic topic);
+
+ /**
+ * Creates a new event with the given boolean subscriber determining whether
+ * it is active.
+ *
+ * @param loop the loop that polls this event
+ * @param sub The boolean subscriber that provides the value
+ */
+ NetworkBooleanEvent(EventLoop* loop, nt::BooleanSubscriber sub);
+
+ /**
+ * Creates a new event with the given boolean topic determining whether it is
+ * active.
+ *
+ * @param loop the loop that polls this event
+ * @param table The NetworkTable that contains the topic
+ * @param topicName The topic name within the table that contains the value
+ */
+ NetworkBooleanEvent(EventLoop* loop, std::shared_ptr<nt::NetworkTable> table,
+ std::string_view topicName);
+
+ /**
+ * Creates a new event with the given boolean topic determining whether it is
+ * active.
+ *
+ * @param loop the loop that polls this event
+ * @param tableName The NetworkTable name that contains the topic
+ * @param topicName The topic name within the table that contains the value
+ */
+ NetworkBooleanEvent(EventLoop* loop, std::string_view tableName,
+ std::string_view topicName);
+
+ /**
+ * Creates a new event with the given boolean topic determining whether it is
+ * active.
+ *
+ * @param loop the loop that polls this event
+ * @param inst The NetworkTable instance to use
+ * @param tableName The NetworkTable that contains the topic
+ * @param topicName The topic name within the table that contains the value
+ */
+ NetworkBooleanEvent(EventLoop* loop, nt::NetworkTableInstance inst,
+ std::string_view tableName, std::string_view topicName);
+};
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/interfaces/Gyro.h b/wpilibc/src/main/native/include/frc/interfaces/Gyro.h
index 50417ea..b74a3cf 100644
--- a/wpilibc/src/main/native/include/frc/interfaces/Gyro.h
+++ b/wpilibc/src/main/native/include/frc/interfaces/Gyro.h
@@ -77,7 +77,7 @@
* based on integration of the returned rate from the gyro.
*/
virtual Rotation2d GetRotation2d() const {
- return Rotation2d{units::degree_t{-GetAngle()}};
+ return units::degree_t{-GetAngle()};
}
};
diff --git a/wpilibc/src/main/native/include/frc/internal/DriverStationModeThread.h b/wpilibc/src/main/native/include/frc/internal/DriverStationModeThread.h
new file mode 100644
index 0000000..f4fd11c
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/internal/DriverStationModeThread.h
@@ -0,0 +1,36 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <atomic>
+#include <thread>
+
+namespace frc::internal {
+class DriverStationModeThread {
+ public:
+ DriverStationModeThread();
+ ~DriverStationModeThread();
+
+ DriverStationModeThread(const DriverStationModeThread& other) = delete;
+ DriverStationModeThread(DriverStationModeThread&& other) = delete;
+ DriverStationModeThread& operator=(const DriverStationModeThread& other) =
+ delete;
+ DriverStationModeThread& operator=(DriverStationModeThread&& other) = delete;
+
+ void InAutonomous(bool entering);
+ void InDisabled(bool entering);
+ void InTeleop(bool entering);
+ void InTest(bool entering);
+
+ private:
+ std::atomic_bool m_keepAlive{false};
+ std::thread m_thread;
+ void Run();
+ bool m_userInDisabled{false};
+ bool m_userInAutonomous{false};
+ bool m_userInTeleop{false};
+ bool m_userInTest{false};
+};
+} // namespace frc::internal
diff --git a/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h b/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h
index 6851cde..3714146 100644
--- a/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h
+++ b/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h
@@ -6,8 +6,6 @@
#include <functional>
-#include <wpi/deprecated.h>
-
namespace wpi {
class Sendable;
} // namespace wpi
@@ -18,20 +16,9 @@
* The LiveWindow class is the public interface for putting sensors and
* actuators on the LiveWindow.
*/
-class LiveWindow {
+class LiveWindow final {
public:
/**
- * Get an instance of the LiveWindow main class.
- *
- * This is a singleton to guarantee that there is only a single instance
- * regardless of how many times GetInstance is called.
- * @deprecated Use the static methods unless guaranteeing LiveWindow is
- * instantiated
- */
- WPI_DEPRECATED("Use static methods")
- static LiveWindow* GetInstance();
-
- /**
* Set function to be called when LiveWindow is enabled.
*
* @param func function (or nullptr for none)
@@ -64,6 +51,11 @@
*/
static void DisableAllTelemetry();
+ /**
+ * Enable ALL telemetry.
+ */
+ static void EnableAllTelemetry();
+
static bool IsEnabled();
/**
diff --git a/wpilibc/src/main/native/include/frc/motorcontrol/MotorController.h b/wpilibc/src/main/native/include/frc/motorcontrol/MotorController.h
index 8ed19bc..24e1b17 100644
--- a/wpilibc/src/main/native/include/frc/motorcontrol/MotorController.h
+++ b/wpilibc/src/main/native/include/frc/motorcontrol/MotorController.h
@@ -6,32 +6,66 @@
#include <units/voltage.h>
-#include "frc/SpeedController.h"
-
namespace frc {
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4996) // was declared deprecated
-#elif defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
/**
* Interface for motor controlling devices.
*/
-class MotorController : public SpeedController {};
+class MotorController {
+ public:
+ virtual ~MotorController() = default;
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#elif defined(__clang__)
-#pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
+ /**
+ * Common interface for setting the speed of a motor controller.
+ *
+ * @param speed The speed to set. Value should be between -1.0 and 1.0.
+ */
+ virtual void Set(double speed) = 0;
+
+ /**
+ * Sets the voltage output of the MotorController. Compensates for
+ * the current bus voltage to ensure that the desired voltage is output even
+ * if the battery voltage is below 12V - highly useful when the voltage
+ * outputs are "meaningful" (e.g. they come from a feedforward calculation).
+ *
+ * <p>NOTE: This function *must* be called regularly in order for voltage
+ * compensation to work properly - unlike the ordinary set function, it is not
+ * "set it and forget it."
+ *
+ * @param output The voltage to output.
+ */
+ virtual void SetVoltage(units::volt_t output);
+
+ /**
+ * Common interface for getting the current set speed of a motor controller.
+ *
+ * @return The current set speed. Value is between -1.0 and 1.0.
+ */
+ virtual double Get() const = 0;
+
+ /**
+ * Common interface for inverting direction of a motor controller.
+ *
+ * @param isInverted The state of inversion, true is inverted.
+ */
+ virtual void SetInverted(bool isInverted) = 0;
+
+ /**
+ * Common interface for returning the inversion state of a motor controller.
+ *
+ * @return isInverted The state of inversion, true is inverted.
+ */
+ virtual bool GetInverted() const = 0;
+
+ /**
+ * Common interface for disabling a motor.
+ */
+ virtual void Disable() = 0;
+
+ /**
+ * Common interface to stop the motor until Set is called again.
+ */
+ virtual void StopMotor() = 0;
+};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h b/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h
index 6f47bf9..99a9e4e 100644
--- a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h
+++ b/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h
@@ -31,6 +31,7 @@
MotorControllerGroup& operator=(MotorControllerGroup&&) = default;
void Set(double speed) override;
+ void SetVoltage(units::volt_t output) override;
double Get() const override;
void SetInverted(bool isInverted) override;
bool GetInverted() const override;
diff --git a/wpilibc/src/main/native/include/frc/motorcontrol/PWMMotorController.h b/wpilibc/src/main/native/include/frc/motorcontrol/PWMMotorController.h
index 7bb63fb..bca5d7f 100644
--- a/wpilibc/src/main/native/include/frc/motorcontrol/PWMMotorController.h
+++ b/wpilibc/src/main/native/include/frc/motorcontrol/PWMMotorController.h
@@ -64,7 +64,7 @@
/**
* Optionally eliminate the deadband from a motor controller.
*
- * @param eliminateDeadband If true, set the motor curve on the speed
+ * @param eliminateDeadband If true, set the motor curve on the motor
* controller to eliminate the deadband in the middle
* of the range. Otherwise, keep the full range
* without modifying any values.
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h
index dc49d64..a96f879 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h
@@ -21,7 +21,7 @@
class ShuffleboardContainer;
/**
- * A Shuffleboard widget that handles a Sendable object such as a speed
+ * A Shuffleboard widget that handles a Sendable object such as a motor
* controller or sensor.
*/
class ComplexWidget final : public ShuffleboardWidget<ComplexWidget> {
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h b/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h
index 83b23a4..3ef5120 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h
@@ -8,8 +8,10 @@
#include <string>
#include <string_view>
+#include <networktables/BooleanTopic.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
+#include <networktables/StringTopic.h>
#include <wpi/SmallVector.h>
#include "frc/shuffleboard/ShuffleboardEventImportance.h"
@@ -30,8 +32,8 @@
ShuffleboardEventImportance importance);
private:
- nt::NetworkTableEntry m_recordingControlEntry;
- nt::NetworkTableEntry m_recordingFileNameFormatEntry;
+ nt::BooleanPublisher m_recordingControlEntry;
+ nt::StringPublisher m_recordingFileNameFormatEntry;
std::shared_ptr<nt::NetworkTable> m_eventsTable;
};
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h b/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h
index 4792ce3..7951cf9 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h
@@ -6,6 +6,7 @@
#include <functional>
#include <memory>
+#include <span>
#include <string>
#include <string_view>
@@ -22,9 +23,9 @@
using CS_Source = CS_Handle; // NOLINT
#endif
+#include <networktables/StringArrayTopic.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
-#include <wpi/span.h>
namespace frc {
@@ -56,6 +57,17 @@
SendableCameraWrapper(std::string_view cameraName, const private_init&);
/**
+ * Creates a new sendable wrapper. Private constructor to avoid direct
+ * instantiation with multiple wrappers floating around for the same camera.
+ *
+ * @param cameraName the name of the camera to wrap
+ * @param cameraUrls camera URLs
+ */
+ SendableCameraWrapper(std::string_view cameraName,
+ std::span<const std::string> cameraUrls,
+ const private_init&);
+
+ /**
* Gets a sendable wrapper object for the given video source, creating the
* wrapper if one does not already exist for the source.
*
@@ -67,12 +79,13 @@
static SendableCameraWrapper& Wrap(CS_Source source);
static SendableCameraWrapper& Wrap(std::string_view cameraName,
- wpi::span<const std::string> cameraUrls);
+ std::span<const std::string> cameraUrls);
void InitSendable(wpi::SendableBuilder& builder) override;
private:
std::string m_uri;
+ nt::StringArrayPublisher m_streams;
};
#ifndef DYNAMIC_CAMERA_SERVER
@@ -83,6 +96,17 @@
m_uri += name;
}
+inline SendableCameraWrapper::SendableCameraWrapper(
+ std::string_view cameraName, std::span<const std::string> cameraUrls,
+ const private_init&)
+ : SendableCameraWrapper(cameraName, private_init{}) {
+ m_streams = nt::NetworkTableInstance::GetDefault()
+ .GetStringArrayTopic(
+ fmt::format("/CameraPublisher/{}/streams", cameraName))
+ .Publish();
+ m_streams.Set(cameraUrls);
+}
+
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
const cs::VideoSource& source) {
return Wrap(source.GetHandle());
@@ -99,15 +123,12 @@
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
- std::string_view cameraName, wpi::span<const std::string> cameraUrls) {
+ std::string_view cameraName, std::span<const std::string> cameraUrls) {
auto& wrapper = detail::GetSendableCameraWrapper(cameraName);
if (!wrapper) {
- wrapper =
- std::make_shared<SendableCameraWrapper>(cameraName, private_init{});
+ wrapper = std::make_shared<SendableCameraWrapper>(cameraName, cameraUrls,
+ private_init{});
}
- auto streams = fmt::format("/CameraPublisher/{}/streams", cameraName);
- nt::NetworkTableInstance::GetDefault().GetEntry(streams).SetStringArray(
- cameraUrls);
return *wrapper;
}
#endif
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h
index 24f65a3..fc15948 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h
@@ -37,8 +37,7 @@
* @param properties the properties for this component
* @return this component
*/
- Derived& WithProperties(
- const wpi::StringMap<std::shared_ptr<nt::Value>>& properties);
+ Derived& WithProperties(const wpi::StringMap<nt::Value>& properties);
/**
* Sets the position of this component in the tab. This has no effect if this
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc
index 9750d4a..63a4933 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc
@@ -21,7 +21,7 @@
template <typename Derived>
Derived& ShuffleboardComponent<Derived>::WithProperties(
- const wpi::StringMap<std::shared_ptr<nt::Value>>& properties) {
+ const wpi::StringMap<nt::Value>& properties) {
m_properties = properties;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h
index d33a234..de27b35 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h
@@ -35,7 +35,7 @@
const std::string& GetType() const;
protected:
- wpi::StringMap<std::shared_ptr<nt::Value>> m_properties;
+ wpi::StringMap<nt::Value> m_properties;
bool m_metadataDirty = true;
int m_column = -1;
int m_row = -1;
@@ -49,7 +49,7 @@
/**
* Gets the custom properties for this component. May be null.
*/
- const wpi::StringMap<std::shared_ptr<nt::Value>>& GetProperties() const;
+ const wpi::StringMap<nt::Value>& GetProperties() const;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h
index 13a5cee..5d20783 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h
@@ -6,6 +6,7 @@
#include <functional>
#include <memory>
+#include <span>
#include <string>
#include <string_view>
#include <vector>
@@ -14,7 +15,6 @@
#include <networktables/NetworkTableValue.h>
#include <wpi/SmallSet.h>
#include <wpi/StringMap.h>
-#include <wpi/span.h>
#include "frc/shuffleboard/BuiltInLayouts.h"
#include "frc/shuffleboard/LayoutType.h"
@@ -137,7 +137,7 @@
* @return a widget to display the camera stream
*/
ComplexWidget& AddCamera(std::string_view title, std::string_view cameraName,
- wpi::span<const std::string> cameraUrls);
+ std::span<const std::string> cameraUrls);
/**
* Adds a widget to this container to display the given sendable.
@@ -171,8 +171,7 @@
* @see AddPersistent(std::string_view, std::shared_ptr<nt::Value>)
* Add(std::string_view title, std::shared_ptr<nt::Value> defaultValue)
*/
- SimpleWidget& Add(std::string_view title,
- std::shared_ptr<nt::Value> defaultValue);
+ SimpleWidget& Add(std::string_view title, const nt::Value& defaultValue);
/**
* Adds a widget to this container to display the given data.
@@ -208,6 +207,19 @@
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
+ * @see AddPersistent(std::string_view, double)
+ * Add(std::string_view title, double defaultValue)
+ */
+ SimpleWidget& Add(std::string_view title, float defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
* @see AddPersistent(std::string_view, int)
* Add(std::string_view title, int defaultValue)
*/
@@ -247,10 +259,10 @@
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
- * @see AddPersistent(std::string_view, wpi::span<const bool>)
- * Add(std::string_view title, wpi::span<const bool> defaultValue)
+ * @see AddPersistent(std::string_view, std::span<const bool>)
+ * Add(std::string_view title, std::span<const bool> defaultValue)
*/
- SimpleWidget& Add(std::string_view title, wpi::span<const bool> defaultValue);
+ SimpleWidget& Add(std::string_view title, std::span<const bool> defaultValue);
/**
* Adds a widget to this container to display the given data.
@@ -260,11 +272,11 @@
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
- * @see AddPersistent(std::string_view, wpi::span<const double>)
- * Add(std::string_view title, wpi::span<const double> defaultValue)
+ * @see AddPersistent(std::string_view, std::span<const double>)
+ * Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
- wpi::span<const double> defaultValue);
+ std::span<const double> defaultValue);
/**
* Adds a widget to this container to display the given data.
@@ -274,11 +286,39 @@
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
- * @see AddPersistent(std::string_view, wpi::span<const std::string>)
- * Add(std::string_view title, wpi::span<const std::string> defaultValue)
+ * @see AddPersistent(std::string_view, std::span<const double>)
+ * Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
- wpi::span<const std::string> defaultValue);
+ std::span<const float> defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see AddPersistent(std::string_view, std::span<const double>)
+ * Add(std::string_view title, std::span<const double> defaultValue)
+ */
+ SimpleWidget& Add(std::string_view title,
+ std::span<const int64_t> defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see AddPersistent(std::string_view, std::span<const std::string>)
+ * Add(std::string_view title, std::span<const std::string> defaultValue)
+ */
+ SimpleWidget& Add(std::string_view title,
+ std::span<const std::string> defaultValue);
/**
* Adds a widget to this container. The widget will display the data provided
@@ -316,6 +356,45 @@
* @param supplier the supplier for values
* @return a widget to display data
*/
+ SuppliedValueWidget<double>& AddDouble(std::string_view title,
+ std::function<double()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
+ SuppliedValueWidget<float>& AddFloat(std::string_view title,
+ std::function<float()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
+ SuppliedValueWidget<int64_t>& AddInteger(std::string_view title,
+ std::function<int64_t()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
SuppliedValueWidget<bool>& AddBoolean(std::string_view title,
std::function<bool()> supplier);
@@ -356,6 +435,45 @@
* @param supplier the supplier for values
* @return a widget to display data
*/
+ SuppliedValueWidget<std::vector<double>>& AddDoubleArray(
+ std::string_view title, std::function<std::vector<double>()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
+ SuppliedValueWidget<std::vector<float>>& AddFloatArray(
+ std::string_view title, std::function<std::vector<float>()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
+ SuppliedValueWidget<std::vector<int64_t>>& AddIntegerArray(
+ std::string_view title, std::function<std::vector<int64_t>()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
SuppliedValueWidget<std::vector<int>>& AddBooleanArray(
std::string_view title, std::function<std::vector<int>()> supplier);
@@ -369,8 +487,23 @@
* @param supplier the supplier for values
* @return a widget to display data
*/
- SuppliedValueWidget<std::string_view>& AddRaw(
- std::string_view title, std::function<std::string_view()> supplier);
+ SuppliedValueWidget<std::vector<uint8_t>>& AddRaw(
+ std::string_view title, std::function<std::vector<uint8_t>()> supplier);
+
+ /**
+ * Adds a widget to this container. The widget will display the data provided
+ * by the value supplier. Changes made on the dashboard will not propagate to
+ * the widget object, and will be overridden by values from the value
+ * supplier.
+ *
+ * @param title the title of the widget
+ * @param typeString the NT type string
+ * @param supplier the supplier for values
+ * @return a widget to display data
+ */
+ SuppliedValueWidget<std::vector<uint8_t>>& AddRaw(
+ std::string_view title, std::string_view typeString,
+ std::function<std::vector<uint8_t>()> supplier);
/**
* Adds a widget to this container to display a simple piece of data.
@@ -386,7 +519,7 @@
* Add(std::string_view title, std::shared_ptr<nt::Value> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
- std::shared_ptr<nt::Value> defaultValue);
+ const nt::Value& defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
@@ -421,15 +554,30 @@
/**
* Adds a widget to this container to display a simple piece of data.
*
- * Unlike Add(std::string_view, int), the value in the widget will be saved on
- * the robot and will be used when the robot program next starts rather than
- * {@code defaultValue}.
+ * Unlike Add(std::string_view, float), the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
- * @see Add(std:string_view, int)
- * Add(std::string_view title, int defaultValue)
+ * @see Add(std::string_view, float)
+ * Add(std::string_view title, float defaultValue)
+ */
+ SimpleWidget& AddPersistent(std::string_view title, float defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike Add(std::string_view, int64_t), the value in the widget will be
+ * saved on the robot and will be used when the robot program next starts
+ * rather than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see Add(std:string_view, int64_t)
+ * Add(std::string_view title, int64_t defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title, int defaultValue);
@@ -452,50 +600,82 @@
/**
* Adds a widget to this container to display a simple piece of data.
*
- * Unlike Add(std::string_view, wpi::span<const bool>), the value in the
+ * Unlike Add(std::string_view, std::span<const bool>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
- * @see Add(std::string_view, wpi::span<const bool>)
- * Add(std::string_view title, wpi::span<const bool> defaultValue)
+ * @see Add(std::string_view, std::span<const bool>)
+ * Add(std::string_view title, std::span<const bool> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
- wpi::span<const bool> defaultValue);
+ std::span<const bool> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
- * Unlike Add(std::string_view, wpi::span<const double>), the value in the
+ * Unlike Add(std::string_view, std::span<const double>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
- * @see Add(std::string_view, wpi::span<const double>)
- * Add(std::string_view title, wpi::span<const double> defaultValue)
+ * @see Add(std::string_view, std::span<const double>)
+ * Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
- wpi::span<const double> defaultValue);
+ std::span<const double> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
- * Unlike Add(std::string_view, wpi::span<const std::string>), the value in
+ * Unlike Add(std::string_view, std::span<const float>), the value in the
+ * widget will be saved on the robot and will be used when the robot program
+ * next starts rather than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see Add(std::string_view, std::span<const float>)
+ * Add(std::string_view title, std::span<const float> defaultValue)
+ */
+ SimpleWidget& AddPersistent(std::string_view title,
+ std::span<const float> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike Add(std::string_view, std::span<const int64_t>), the value in the
+ * widget will be saved on the robot and will be used when the robot program
+ * next starts rather than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see Add(std::string_view, std::span<const int64_t>)
+ * Add(std::string_view title, std::span<const int64_t> defaultValue)
+ */
+ SimpleWidget& AddPersistent(std::string_view title,
+ std::span<const int64_t> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike Add(std::string_view, std::span<const std::string>), the value in
* the widget will be saved on the robot and will be used when the robot
* program next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
- * @see Add(std::string_view, wpi::span<const std::string>)
- * Add(std::string_view title, wpi::span<const std::string> defaultValue)
+ * @see Add(std::string_view, std::span<const std::string>)
+ * Add(std::string_view title, std::span<const std::string> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
- wpi::span<const std::string> defaultValue);
+ std::span<const std::string> defaultValue);
void EnableIfActuator() override;
@@ -541,7 +721,7 @@
inline frc::ComplexWidget& frc::ShuffleboardContainer::AddCamera(
std::string_view title, std::string_view cameraName,
- wpi::span<const std::string> cameraUrls) {
+ std::span<const std::string> cameraUrls) {
return Add(title, frc::SendableCameraWrapper::Wrap(cameraName, cameraUrls));
}
#endif
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h
index 746b7d6..97502be 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h
@@ -5,10 +5,11 @@
#pragma once
#include <memory>
+#include <string>
#include <string_view>
+#include <networktables/GenericEntry.h>
#include <networktables/NetworkTable.h>
-#include <networktables/NetworkTableEntry.h>
#include "frc/shuffleboard/ShuffleboardWidget.h"
@@ -26,14 +27,26 @@
/**
* Gets the NetworkTable entry that contains the data for this widget.
+ * The widget owns the entry; the returned pointer's lifetime is the same as
+ * that of the widget.
*/
- nt::NetworkTableEntry GetEntry();
+ nt::GenericEntry* GetEntry();
+
+ /**
+ * Gets the NetworkTable entry that contains the data for this widget.
+ * The widget owns the entry; the returned pointer's lifetime is the same as
+ * that of the widget.
+ *
+ * @param typeString NT type string
+ */
+ nt::GenericEntry* GetEntry(std::string_view typeString);
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override;
private:
- nt::NetworkTableEntry m_entry;
+ nt::GenericEntry m_entry;
+ std::string m_typeString;
void ForceGenerate();
};
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h
index a2b042e..4f82dc6 100644
--- a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h
@@ -6,10 +6,12 @@
#include <functional>
#include <memory>
+#include <string>
#include <string_view>
+#include <networktables/BooleanTopic.h>
+#include <networktables/GenericEntry.h>
#include <networktables/NetworkTable.h>
-#include <networktables/NetworkTableEntry.h>
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/ShuffleboardComponent.inc"
@@ -23,24 +25,35 @@
class SuppliedValueWidget : public ShuffleboardWidget<SuppliedValueWidget<T>> {
public:
SuppliedValueWidget(ShuffleboardContainer& parent, std::string_view title,
- std::function<T()> supplier,
- std::function<void(nt::NetworkTableEntry, T)> setter)
+ std::string_view typeString, std::function<T()> supplier,
+ std::function<void(nt::GenericPublisher&, T)> setter)
: ShuffleboardValue(title),
ShuffleboardWidget<SuppliedValueWidget<T>>(parent, title),
+ m_typeString(typeString),
m_supplier(supplier),
m_setter(setter) {}
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override {
this->BuildMetadata(metaTable);
- metaTable->GetEntry("Controllable").SetBoolean(false);
+ if (!m_controllablePub) {
+ m_controllablePub =
+ nt::BooleanTopic{metaTable->GetTopic("Controllable")}.Publish();
+ m_controllablePub.Set(false);
+ }
- auto entry = parentTable->GetEntry(this->GetTitle());
- m_setter(entry, m_supplier());
+ if (!m_entry) {
+ m_entry =
+ parentTable->GetTopic(this->GetTitle()).GenericPublish(m_typeString);
+ }
+ m_setter(m_entry, m_supplier());
}
private:
+ std::string m_typeString;
std::function<T()> m_supplier;
- std::function<void(nt::NetworkTableEntry, T)> m_setter;
+ std::function<void(nt::GenericPublisher&, T)> m_setter;
+ nt::BooleanPublisher m_controllablePub;
+ nt::GenericPublisher m_entry;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/simulation/BatterySim.h b/wpilibc/src/main/native/include/frc/simulation/BatterySim.h
index 4a350cf..ab79844 100644
--- a/wpilibc/src/main/native/include/frc/simulation/BatterySim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/BatterySim.h
@@ -5,6 +5,7 @@
#pragma once
#include <numeric>
+#include <span>
#include <units/current.h>
#include <units/impedance.h>
@@ -29,6 +30,25 @@
* @param currents The currents drawn from the battery.
* @return The battery's voltage under load.
*/
+ static units::volt_t Calculate(units::volt_t nominalVoltage,
+ units::ohm_t resistance,
+ std::span<const units::ampere_t> currents) {
+ return nominalVoltage -
+ std::accumulate(currents.begin(), currents.end(), 0_A) * resistance;
+ }
+
+ /**
+ * Calculate the loaded battery voltage. Use this with
+ * RoboRioSim::SetVInVoltage(double) to set the simulated battery voltage,
+ * which can then be retrieved with the RobotController::GetBatteryVoltage()
+ * method.
+ *
+ * @param nominalVoltage The nominal battery voltage. Usually 12v.
+ * @param resistance The forward resistance of the battery. Most batteries
+ * are at or below 20 milliohms.
+ * @param currents The currents drawn from the battery.
+ * @return The battery's voltage under load.
+ */
static units::volt_t Calculate(
units::volt_t nominalVoltage, units::ohm_t resistance,
std::initializer_list<units::ampere_t> currents) {
@@ -46,6 +66,20 @@
* @param currents The currents drawn from the battery.
* @return The battery's voltage under load.
*/
+ static units::volt_t Calculate(std::span<const units::ampere_t> currents) {
+ return Calculate(12_V, 0.02_Ohm, currents);
+ }
+
+ /**
+ * Calculate the loaded battery voltage. Use this with
+ * RoboRioSimSetVInVoltage(double) to set the simulated battery voltage, which
+ * can then be retrieved with the RobotController::GetBatteryVoltage() method.
+ * This function assumes a nominal voltage of 12V and a resistance of 20
+ * milliohms (0.020 ohms).
+ *
+ * @param currents The currents drawn from the battery.
+ * @return The battery's voltage under load.
+ */
static units::volt_t Calculate(
std::initializer_list<units::ampere_t> currents) {
return Calculate(12_V, 0.02_Ohm, currents);
diff --git a/wpilibc/src/main/native/include/frc/simulation/CTREPCMSim.h b/wpilibc/src/main/native/include/frc/simulation/CTREPCMSim.h
index 0929308..96959ed 100644
--- a/wpilibc/src/main/native/include/frc/simulation/CTREPCMSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/CTREPCMSim.h
@@ -8,17 +8,14 @@
#include "frc/PneumaticsBase.h"
#include "frc/simulation/CallbackStore.h"
+#include "frc/simulation/PneumaticsBaseSim.h"
-namespace frc {
-
-class Compressor;
-
-namespace sim {
+namespace frc::sim {
/**
* Class to control a simulated Pneumatic Control Module (PCM).
*/
-class CTREPCMSim {
+class CTREPCMSim : public PneumaticsBaseSim {
public:
/**
* Constructs with the default PCM module number (CAN ID).
@@ -34,81 +31,28 @@
explicit CTREPCMSim(const PneumaticsBase& pneumatics);
- /**
- * Register a callback to be run when a solenoid is initialized on a channel.
- *
- * @param callback the callback
- * @param initialNotify should the callback be run with the initial state
- * @return the CallbackStore object associated with this callback
- */
+ ~CTREPCMSim() override = default;
+
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
- /**
- * Check if a solenoid has been initialized on a specific channel.
- *
- * @return true if initialized
- */
- bool GetInitialized() const;
+ bool GetInitialized() const override;
- /**
- * Define whether a solenoid has been initialized on a specific channel.
- *
- * @param solenoidInitialized is there a solenoid initialized on that channel
- */
- void SetInitialized(bool solenoidInitialized);
+ void SetInitialized(bool initialized) override;
- /**
- * Register a callback to be run when the solenoid output on a channel
- * changes.
- *
- * @param channel the channel to monitor
- * @param callback the callback
- * @param initialNotify should the callback be run with the initial value
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterSolenoidOutputCallback(
- int channel, NotifyCallback callback, bool initialNotify);
+ int channel, NotifyCallback callback, bool initialNotify) override;
- /**
- * Check the solenoid output on a specific channel.
- *
- * @param channel the channel to check
- * @return the solenoid output
- */
- bool GetSolenoidOutput(int channel) const;
+ bool GetSolenoidOutput(int channel) const override;
- /**
- * Change the solenoid output on a specific channel.
- *
- * @param channel the channel to check
- * @param solenoidOutput the new solenoid output
- */
- void SetSolenoidOutput(int channel, bool solenoidOutput);
+ void SetSolenoidOutput(int channel, bool solenoidOutput) override;
- /**
- * Register a callback to be run when the compressor activates.
- *
- * @param callback the callback
- * @param initialNotify whether to run the callback with the initial state
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterCompressorOnCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
- /**
- * Check if the compressor is on.
- *
- * @return true if the compressor is active
- */
- bool GetCompressorOn() const;
+ bool GetCompressorOn() const override;
- /**
- * Set whether the compressor is active.
- *
- * @param compressorOn the new value
- */
- void SetCompressorOn(bool compressorOn);
+ void SetCompressorOn(bool compressorOn) override;
/**
* Register a callback to be run whenever the closed loop state changes.
@@ -145,21 +89,21 @@
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPressureSwitchCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
/**
* Check the value of the pressure switch.
*
* @return the pressure switch value
*/
- bool GetPressureSwitch() const;
+ bool GetPressureSwitch() const override;
/**
* Set the value of the pressure switch.
*
* @param pressureSwitch the new value
*/
- void SetPressureSwitch(bool pressureSwitch);
+ void SetPressureSwitch(bool pressureSwitch) override;
/**
* Register a callback to be run whenever the compressor current changes.
@@ -170,43 +114,26 @@
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterCompressorCurrentCallback(NotifyCallback callback,
- bool initialNotify);
+ bool initialNotify) override;
/**
* Read the compressor current.
*
* @return the current of the compressor connected to this module
*/
- double GetCompressorCurrent() const;
+ double GetCompressorCurrent() const override;
/**
* Set the compressor current.
*
* @param compressorCurrent the new compressor current
*/
- void SetCompressorCurrent(double compressorCurrent);
+ void SetCompressorCurrent(double compressorCurrent) override;
- /**
- * Get the current value of all solenoid outputs.
- *
- * @return the solenoid outputs (1 bit per output)
- */
- uint8_t GetAllSolenoidOutputs() const;
+ uint8_t GetAllSolenoidOutputs() const override;
- /**
- * Change all of the solenoid outputs.
- *
- * @param outputs the new solenoid outputs (1 bit per output)
- */
- void SetAllSolenoidOutputs(uint8_t outputs);
+ void SetAllSolenoidOutputs(uint8_t outputs) override;
- /**
- * Reset all simulation data for this object.
- */
- void ResetData();
-
- private:
- int m_index;
+ void ResetData() override;
};
-} // namespace sim
-} // namespace frc
+} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/DifferentialDrivetrainSim.h b/wpilibc/src/main/native/include/frc/simulation/DifferentialDrivetrainSim.h
index 7c53eb7..c1cc1d7 100644
--- a/wpilibc/src/main/native/include/frc/simulation/DifferentialDrivetrainSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/DifferentialDrivetrainSim.h
@@ -4,11 +4,11 @@
#pragma once
+#include <frc/EigenCore.h>
#include <frc/kinematics/DifferentialDriveKinematics.h>
#include <frc/system/LinearSystem.h>
#include <frc/system/plant/DCMotor.h>
-#include <Eigen/Core>
#include <units/length.h>
#include <units/moment_of_inertia.h>
#include <units/time.h>
@@ -80,7 +80,7 @@
* @param u The input vector.
* @return The normalized input.
*/
- Eigen::Vector<double, 2> ClampInput(const Eigen::Vector<double, 2>& u);
+ Vectord<2> ClampInput(const Vectord<2>& u);
/**
* Sets the applied voltage to the drivetrain. Note that positive voltage must
@@ -178,7 +178,7 @@
*
* @param state The state.
*/
- void SetState(const Eigen::Vector<double, 7>& state);
+ void SetState(const Vectord<7>& state);
/**
* Sets the system pose.
@@ -187,8 +187,7 @@
*/
void SetPose(const frc::Pose2d& pose);
- Eigen::Vector<double, 7> Dynamics(const Eigen::Vector<double, 7>& x,
- const Eigen::Vector<double, 2>& u);
+ Vectord<7> Dynamics(const Vectord<7>& x, const Vectord<2>& u);
class State {
public:
@@ -256,7 +255,7 @@
static DifferentialDrivetrainSim CreateKitbotSim(
frc::DCMotor motor, double gearing, units::meter_t wheelSize,
const std::array<double, 7>& measurementStdDevs = {}) {
- // MOI estimation -- note that I = m r^2 for point masses
+ // MOI estimation -- note that I = mr² for point masses
units::kilogram_square_meter_t batteryMoi = 12.5_lb * 10_in * 10_in;
units::kilogram_square_meter_t gearboxMoi = (2.8_lb + 2.0_lb) *
2 // CIM plus toughbox per side
@@ -301,7 +300,7 @@
/**
* Returns the current output vector y.
*/
- Eigen::Vector<double, 7> GetOutput() const;
+ Vectord<7> GetOutput() const;
/**
* Returns an element of the state vector. Note that this will not include
@@ -314,7 +313,7 @@
/**
* Returns the current state vector x. Note that this will not include noise!
*/
- Eigen::Vector<double, 7> GetState() const;
+ Vectord<7> GetState() const;
LinearSystem<2, 2, 2> m_plant;
units::meter_t m_rb;
@@ -325,9 +324,9 @@
double m_originalGearing;
double m_currentGearing;
- Eigen::Vector<double, 7> m_x;
- Eigen::Vector<double, 2> m_u;
- Eigen::Vector<double, 7> m_y;
+ Vectord<7> m_x;
+ Vectord<2> m_u;
+ Vectord<7> m_y;
std::array<double, 7> m_measurementStdDevs;
};
} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/DoubleSolenoidSim.h b/wpilibc/src/main/native/include/frc/simulation/DoubleSolenoidSim.h
new file mode 100644
index 0000000..eaa697f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/simulation/DoubleSolenoidSim.h
@@ -0,0 +1,33 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <memory>
+
+#include "frc/DoubleSolenoid.h"
+#include "frc/PneumaticsModuleType.h"
+#include "frc/simulation/PneumaticsBaseSim.h"
+
+namespace frc::sim {
+
+class DoubleSolenoidSim {
+ public:
+ DoubleSolenoidSim(std::shared_ptr<PneumaticsBaseSim> moduleSim, int fwd,
+ int rev);
+ DoubleSolenoidSim(int module, PneumaticsModuleType type, int fwd, int rev);
+ DoubleSolenoidSim(PneumaticsModuleType type, int fwd, int rev);
+
+ DoubleSolenoid::Value Get() const;
+ void Set(DoubleSolenoid::Value output);
+
+ std::shared_ptr<PneumaticsBaseSim> GetModuleSim() const;
+
+ private:
+ std::shared_ptr<PneumaticsBaseSim> m_module;
+ int m_fwd;
+ int m_rev;
+};
+
+} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/DriverStationSim.h b/wpilibc/src/main/native/include/frc/simulation/DriverStationSim.h
index 412a921..232c123 100644
--- a/wpilibc/src/main/native/include/frc/simulation/DriverStationSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/DriverStationSim.h
@@ -337,7 +337,7 @@
* @param stick The joystick number
* @param name The value of name
*/
- static void SetJoystickName(int stick, const char* name);
+ static void SetJoystickName(int stick, std::string_view name);
/**
* Sets the types of Axes for a joystick.
@@ -353,14 +353,14 @@
*
* @param message the game specific message
*/
- static void SetGameSpecificMessage(const char* message);
+ static void SetGameSpecificMessage(std::string_view message);
/**
* Sets the event name.
*
* @param name the event name
*/
- static void SetEventName(const char* name);
+ static void SetEventName(std::string_view name);
/**
* Sets the match type.
diff --git a/wpilibc/src/main/native/include/frc/simulation/ElevatorSim.h b/wpilibc/src/main/native/include/frc/simulation/ElevatorSim.h
index 14b6d2d..cf40810 100644
--- a/wpilibc/src/main/native/include/frc/simulation/ElevatorSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/ElevatorSim.h
@@ -31,11 +31,13 @@
* wrapped around.
* @param minHeight The minimum allowed height of the elevator.
* @param maxHeight The maximum allowed height of the elevator.
+ * @param simulateGravity Whether gravity should be simulated or not.
* @param measurementStdDevs The standard deviation of the measurements.
*/
ElevatorSim(const LinearSystem<2, 1, 1>& plant, const DCMotor& gearbox,
double gearing, units::meter_t drumRadius,
units::meter_t minHeight, units::meter_t maxHeight,
+ bool simulateGravity,
const std::array<double, 1>& measurementStdDevs = {0.0});
/**
@@ -50,11 +52,13 @@
* wrapped around.
* @param minHeight The minimum allowed height of the elevator.
* @param maxHeight The maximum allowed height of the elevator.
+ * @param simulateGravity Whether gravity should be simulated or not.
* @param measurementStdDevs The standard deviation of the measurements.
*/
ElevatorSim(const DCMotor& gearbox, double gearing,
units::kilogram_t carriageMass, units::meter_t drumRadius,
units::meter_t minHeight, units::meter_t maxHeight,
+ bool simulateGravity,
const std::array<double, 1>& measurementStdDevs = {0.0});
/**
@@ -123,9 +127,8 @@
* @param u The system inputs (voltage).
* @param dt The time difference between controller updates.
*/
- Eigen::Vector<double, 2> UpdateX(const Eigen::Vector<double, 2>& currentXhat,
- const Eigen::Vector<double, 1>& u,
- units::second_t dt) override;
+ Vectord<2> UpdateX(const Vectord<2>& currentXhat, const Vectord<1>& u,
+ units::second_t dt) override;
private:
DCMotor m_gearbox;
@@ -133,5 +136,6 @@
units::meter_t m_minHeight;
units::meter_t m_maxHeight;
double m_gearing;
+ bool m_simulateGravity;
};
} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/LinearSystemSim.h b/wpilibc/src/main/native/include/frc/simulation/LinearSystemSim.h
index 731fad3..cfc87b2 100644
--- a/wpilibc/src/main/native/include/frc/simulation/LinearSystemSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/LinearSystemSim.h
@@ -6,10 +6,10 @@
#include <array>
-#include <Eigen/Core>
#include <units/current.h>
#include <units/time.h>
+#include "frc/EigenCore.h"
#include "frc/RobotController.h"
#include "frc/StateSpaceUtil.h"
#include "frc/system/LinearSystem.h"
@@ -40,9 +40,9 @@
const LinearSystem<States, Inputs, Outputs>& system,
const std::array<double, Outputs>& measurementStdDevs = {})
: m_plant(system), m_measurementStdDevs(measurementStdDevs) {
- m_x = Eigen::Vector<double, States>::Zero();
- m_y = Eigen::Vector<double, Outputs>::Zero();
- m_u = Eigen::Vector<double, Inputs>::Zero();
+ m_x = Vectord<States>::Zero();
+ m_y = Vectord<Outputs>::Zero();
+ m_u = Vectord<Inputs>::Zero();
}
virtual ~LinearSystemSim() = default;
@@ -71,7 +71,7 @@
*
* @return The current output of the plant.
*/
- const Eigen::Vector<double, Outputs>& GetOutput() const { return m_y; }
+ const Vectord<Outputs>& GetOutput() const { return m_y; }
/**
* Returns an element of the current output of the plant.
@@ -86,7 +86,7 @@
*
* @param u The system inputs.
*/
- void SetInput(const Eigen::Vector<double, Inputs>& u) { m_u = ClampInput(u); }
+ void SetInput(const Vectord<Inputs>& u) { m_u = ClampInput(u); }
/*
* Sets the system inputs.
@@ -104,7 +104,7 @@
*
* @param state The new state.
*/
- void SetState(const Eigen::Vector<double, States>& state) { m_x = state; }
+ void SetState(const Vectord<States>& state) { m_x = state; }
/**
* Returns the current drawn by this simulated system. Override this method to
@@ -112,9 +112,7 @@
*
* @return The current drawn by this simulated mechanism.
*/
- virtual units::ampere_t GetCurrentDraw() const {
- return units::ampere_t(0.0);
- }
+ virtual units::ampere_t GetCurrentDraw() const { return 0_A; }
protected:
/**
@@ -124,9 +122,9 @@
* @param u The system inputs (usually voltage).
* @param dt The time difference between controller updates.
*/
- virtual Eigen::Vector<double, States> UpdateX(
- const Eigen::Vector<double, States>& currentXhat,
- const Eigen::Vector<double, Inputs>& u, units::second_t dt) {
+ virtual Vectord<States> UpdateX(const Vectord<States>& currentXhat,
+ const Vectord<Inputs>& u,
+ units::second_t dt) {
return m_plant.CalculateX(currentXhat, u, dt);
}
@@ -137,16 +135,16 @@
* @param u The input vector.
* @return The normalized input.
*/
- Eigen::Vector<double, Inputs> ClampInput(Eigen::Vector<double, Inputs> u) {
+ Vectord<Inputs> ClampInput(Vectord<Inputs> u) {
return frc::DesaturateInputVector<Inputs>(
u, frc::RobotController::GetInputVoltage());
}
LinearSystem<States, Inputs, Outputs> m_plant;
- Eigen::Vector<double, States> m_x;
- Eigen::Vector<double, Outputs> m_y;
- Eigen::Vector<double, Inputs> m_u;
+ Vectord<States> m_x;
+ Vectord<Outputs> m_y;
+ Vectord<Inputs> m_u;
std::array<double, Outputs> m_measurementStdDevs;
};
} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/PWMSim.h b/wpilibc/src/main/native/include/frc/simulation/PWMSim.h
index 97e9b1f..8b4156e 100644
--- a/wpilibc/src/main/native/include/frc/simulation/PWMSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/PWMSim.h
@@ -11,6 +11,7 @@
namespace frc {
class PWM;
+class PWMMotorController;
namespace sim {
@@ -27,6 +28,13 @@
explicit PWMSim(const PWM& pwm);
/**
+ * Constructs from a PWMMotorController object.
+ *
+ * @param motorctrl PWMMotorController to simulate
+ */
+ explicit PWMSim(const PWMMotorController& motorctrl);
+
+ /**
* Constructs from a PWM channel number.
*
* @param channel Channel number
diff --git a/wpilibc/src/main/native/include/frc/simulation/PneumaticsBaseSim.h b/wpilibc/src/main/native/include/frc/simulation/PneumaticsBaseSim.h
new file mode 100644
index 0000000..11110e3
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/simulation/PneumaticsBaseSim.h
@@ -0,0 +1,183 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <memory>
+
+#include "frc/PneumaticsBase.h"
+#include "frc/PneumaticsModuleType.h"
+#include "frc/simulation/CallbackStore.h"
+
+namespace frc::sim {
+
+class PneumaticsBaseSim {
+ public:
+ virtual ~PneumaticsBaseSim() = default;
+
+ static std::shared_ptr<PneumaticsBaseSim> GetForType(
+ int module, PneumaticsModuleType type);
+
+ /**
+ * Check whether the PCM/PH has been initialized.
+ *
+ * @return true if initialized
+ */
+ virtual bool GetInitialized() const = 0;
+
+ /**
+ * Define whether the PCM/PH has been initialized.
+ *
+ * @param initialized true for initialized
+ */
+ virtual void SetInitialized(bool initialized) = 0;
+
+ /**
+ * Register a callback to be run when the PCM/PH is initialized.
+ *
+ * @param callback the callback
+ * @param initialNotify whether to run the callback with the initial state
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore>
+ RegisterInitializedCallback(NotifyCallback callback, bool initialNotify) = 0;
+
+ /**
+ * Check if the compressor is on.
+ *
+ * @return true if the compressor is active
+ */
+ virtual bool GetCompressorOn() const = 0;
+
+ /**
+ * Set whether the compressor is active.
+ *
+ * @param compressorOn the new value
+ */
+ virtual void SetCompressorOn(bool compressorOn) = 0;
+
+ /**
+ * Register a callback to be run when the compressor activates.
+ *
+ * @param callback the callback
+ * @param initialNotify whether to run the callback with the initial state
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore>
+ RegisterCompressorOnCallback(NotifyCallback callback, bool initialNotify) = 0;
+
+ /**
+ * Check the solenoid output on a specific channel.
+ *
+ * @param channel the channel to check
+ * @return the solenoid output
+ */
+ virtual bool GetSolenoidOutput(int channel) const = 0;
+
+ /**
+ * Change the solenoid output on a specific channel.
+ *
+ * @param channel the channel to check
+ * @param solenoidOutput the new solenoid output
+ */
+ virtual void SetSolenoidOutput(int channel, bool solenoidOutput) = 0;
+
+ /**
+ * Register a callback to be run when the solenoid output on a channel
+ * changes.
+ *
+ * @param channel the channel to monitor
+ * @param callback the callback
+ * @param initialNotify should the callback be run with the initial value
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore>
+ RegisterSolenoidOutputCallback(int channel, NotifyCallback callback,
+ bool initialNotify) = 0;
+
+ /**
+ * Check the value of the pressure switch.
+ *
+ * @return the pressure switch value
+ */
+ virtual bool GetPressureSwitch() const = 0;
+
+ /**
+ * Set the value of the pressure switch.
+ *
+ * @param pressureSwitch the new value
+ */
+ virtual void SetPressureSwitch(bool pressureSwitch) = 0;
+
+ /**
+ * Register a callback to be run whenever the pressure switch value changes.
+ *
+ * @param callback the callback
+ * @param initialNotify whether the callback should be called with the initial
+ * value
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore>
+ RegisterPressureSwitchCallback(NotifyCallback callback,
+ bool initialNotify) = 0;
+
+ /**
+ * Read the compressor current.
+ *
+ * @return the current of the compressor connected to this module
+ */
+ virtual double GetCompressorCurrent() const = 0;
+
+ /**
+ * Set the compressor current.
+ *
+ * @param compressorCurrent the new compressor current
+ */
+ virtual void SetCompressorCurrent(double compressorCurrent) = 0;
+
+ /**
+ * Register a callback to be run whenever the compressor current changes.
+ *
+ * @param callback the callback
+ * @param initialNotify whether to call the callback with the initial state
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore>
+ RegisterCompressorCurrentCallback(NotifyCallback callback,
+ bool initialNotify) = 0;
+
+ /**
+ * Get the current value of all solenoid outputs.
+ *
+ * @return the solenoid outputs (1 bit per output)
+ */
+ virtual uint8_t GetAllSolenoidOutputs() const = 0;
+
+ /**
+ * Change all of the solenoid outputs.
+ *
+ * @param outputs the new solenoid outputs (1 bit per output)
+ */
+ virtual void SetAllSolenoidOutputs(uint8_t outputs) = 0;
+
+ /** Reset all simulation data for this object. */
+ virtual void ResetData() = 0;
+
+ protected:
+ const int m_index;
+ explicit PneumaticsBaseSim(const PneumaticsBase& module);
+ explicit PneumaticsBaseSim(const int index);
+};
+
+} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/simulation/REVPHSim.h b/wpilibc/src/main/native/include/frc/simulation/REVPHSim.h
index e5f4efe..fe305ba 100644
--- a/wpilibc/src/main/native/include/frc/simulation/REVPHSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/REVPHSim.h
@@ -8,6 +8,7 @@
#include "frc/PneumaticsBase.h"
#include "frc/simulation/CallbackStore.h"
+#include "frc/simulation/PneumaticsBaseSim.h"
namespace frc {
@@ -18,7 +19,7 @@
/**
* Class to control a simulated Pneumatic Control Module (PCM).
*/
-class REVPHSim {
+class REVPHSim : public PneumaticsBaseSim {
public:
/**
* Constructs with the default PCM module number (CAN ID).
@@ -34,81 +35,38 @@
explicit REVPHSim(const PneumaticsBase& pneumatics);
- /**
- * Register a callback to be run when a solenoid is initialized on a channel.
- *
- * @param callback the callback
- * @param initialNotify should the callback be run with the initial state
- * @return the CallbackStore object associated with this callback
- */
+ ~REVPHSim() override = default;
+
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
- /**
- * Check if a solenoid has been initialized on a specific channel.
- *
- * @return true if initialized
- */
- bool GetInitialized() const;
+ bool GetInitialized() const override;
- /**
- * Define whether a solenoid has been initialized on a specific channel.
- *
- * @param solenoidInitialized is there a solenoid initialized on that channel
- */
- void SetInitialized(bool solenoidInitialized);
+ void SetInitialized(bool solenoidInitialized) override;
- /**
- * Register a callback to be run when the solenoid output on a channel
- * changes.
- *
- * @param channel the channel to monitor
- * @param callback the callback
- * @param initialNotify should the callback be run with the initial value
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterSolenoidOutputCallback(
- int channel, NotifyCallback callback, bool initialNotify);
+ int channel, NotifyCallback callback, bool initialNotify) override;
- /**
- * Check the solenoid output on a specific channel.
- *
- * @param channel the channel to check
- * @return the solenoid output
- */
- bool GetSolenoidOutput(int channel) const;
+ bool GetSolenoidOutput(int channel) const override;
- /**
- * Change the solenoid output on a specific channel.
- *
- * @param channel the channel to check
- * @param solenoidOutput the new solenoid output
- */
- void SetSolenoidOutput(int channel, bool solenoidOutput);
+ void SetSolenoidOutput(int channel, bool solenoidOutput) override;
- /**
- * Register a callback to be run when the compressor activates.
- *
- * @param callback the callback
- * @param initialNotify whether to run the callback with the initial state
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterCompressorOnCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
/**
* Check if the compressor is on.
*
* @return true if the compressor is active
*/
- bool GetCompressorOn() const;
+ bool GetCompressorOn() const override;
/**
* Set whether the compressor is active.
*
* @param compressorOn the new value
*/
- void SetCompressorOn(bool compressorOn);
+ void SetCompressorOn(bool compressorOn) override;
/**
* Register a callback to be run whenever the closed loop state changes.
@@ -136,77 +94,26 @@
*/
void SetCompressorConfigType(int compressorConfigType);
- /**
- * Register a callback to be run whenever the pressure switch value changes.
- *
- * @param callback the callback
- * @param initialNotify whether the callback should be called with the
- * initial value
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPressureSwitchCallback(
- NotifyCallback callback, bool initialNotify);
+ NotifyCallback callback, bool initialNotify) override;
- /**
- * Check the value of the pressure switch.
- *
- * @return the pressure switch value
- */
- bool GetPressureSwitch() const;
+ bool GetPressureSwitch() const override;
- /**
- * Set the value of the pressure switch.
- *
- * @param pressureSwitch the new value
- */
- void SetPressureSwitch(bool pressureSwitch);
+ void SetPressureSwitch(bool pressureSwitch) override;
- /**
- * Register a callback to be run whenever the compressor current changes.
- *
- * @param callback the callback
- * @param initialNotify whether to call the callback with the initial state
- * @return the CallbackStore object associated with this callback
- */
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterCompressorCurrentCallback(NotifyCallback callback,
- bool initialNotify);
+ bool initialNotify) override;
- /**
- * Read the compressor current.
- *
- * @return the current of the compressor connected to this module
- */
- double GetCompressorCurrent() const;
+ double GetCompressorCurrent() const override;
- /**
- * Set the compressor current.
- *
- * @param compressorCurrent the new compressor current
- */
- void SetCompressorCurrent(double compressorCurrent);
+ void SetCompressorCurrent(double compressorCurrent) override;
- /**
- * Get the current value of all solenoid outputs.
- *
- * @return the solenoid outputs (1 bit per output)
- */
- uint8_t GetAllSolenoidOutputs() const;
+ uint8_t GetAllSolenoidOutputs() const override;
- /**
- * Change all of the solenoid outputs.
- *
- * @param outputs the new solenoid outputs (1 bit per output)
- */
- void SetAllSolenoidOutputs(uint8_t outputs);
+ void SetAllSolenoidOutputs(uint8_t outputs) override;
- /**
- * Reset all simulation data for this object.
- */
- void ResetData();
-
- private:
- int m_index;
+ void ResetData() override;
};
} // namespace sim
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h b/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h
index 1095106..ee959b66 100644
--- a/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <string>
#include <units/current.h>
#include <units/voltage.h>
@@ -419,6 +420,34 @@
static void SetBrownoutVoltage(units::volt_t brownoutVoltage);
/**
+ * Get the serial number.
+ *
+ * @return The serial number.
+ */
+ static std::string GetSerialNumber();
+
+ /**
+ * Set the serial number.
+ *
+ * @param serialNumber The serial number.
+ */
+ static void SetSerialNumber(std::string_view serialNumber);
+
+ /**
+ * Get the comments.
+ *
+ * @return The comments.
+ */
+ static std::string GetComments();
+
+ /**
+ * Set the comments.
+ *
+ * @param comments The comments.
+ */
+ static void SetComments(std::string_view comments);
+
+ /**
* Reset all simulation data.
*/
static void ResetData();
diff --git a/wpilibc/src/main/native/include/frc/simulation/SingleJointedArmSim.h b/wpilibc/src/main/native/include/frc/simulation/SingleJointedArmSim.h
index 4ff29cc..57ad6b1 100644
--- a/wpilibc/src/main/native/include/frc/simulation/SingleJointedArmSim.h
+++ b/wpilibc/src/main/native/include/frc/simulation/SingleJointedArmSim.h
@@ -30,14 +30,14 @@
* @param armLength The length of the arm.
* @param minAngle The minimum angle that the arm is capable of.
* @param maxAngle The maximum angle that the arm is capable of.
- * @param mass The mass of the arm.
- * @param measurementStdDevs The standard deviations of the measurements.
+ * @param armMass The mass of the arm.
* @param simulateGravity Whether gravity should be simulated or not.
+ * @param measurementStdDevs The standard deviations of the measurements.
*/
SingleJointedArmSim(const LinearSystem<2, 1, 1>& system,
const DCMotor& gearbox, double gearing,
units::meter_t armLength, units::radian_t minAngle,
- units::radian_t maxAngle, units::kilogram_t mass,
+ units::radian_t maxAngle, units::kilogram_t armMass,
bool simulateGravity,
const std::array<double, 1>& measurementStdDevs = {0.0});
/**
@@ -52,8 +52,8 @@
* @param minAngle The minimum angle that the arm is capable of.
* @param maxAngle The maximum angle that the arm is capable of.
* @param mass The mass of the arm.
- * @param measurementStdDevs The standard deviation of the measurement noise.
* @param simulateGravity Whether gravity should be simulated or not.
+ * @param measurementStdDevs The standard deviation of the measurement noise.
*/
SingleJointedArmSim(const DCMotor& gearbox, double gearing,
units::kilogram_square_meter_t moi,
@@ -142,15 +142,14 @@
* @param u The system inputs (voltage).
* @param dt The time difference between controller updates.
*/
- Eigen::Vector<double, 2> UpdateX(const Eigen::Vector<double, 2>& currentXhat,
- const Eigen::Vector<double, 1>& u,
- units::second_t dt) override;
+ Vectord<2> UpdateX(const Vectord<2>& currentXhat, const Vectord<1>& u,
+ units::second_t dt) override;
private:
units::meter_t m_r;
units::radian_t m_minAngle;
units::radian_t m_maxAngle;
- units::kilogram_t m_mass;
+ units::kilogram_t m_armMass;
const DCMotor m_gearbox;
double m_gearing;
bool m_simulateGravity;
diff --git a/wpilibc/src/main/native/include/frc/simulation/SolenoidSim.h b/wpilibc/src/main/native/include/frc/simulation/SolenoidSim.h
new file mode 100644
index 0000000..66e3589
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/simulation/SolenoidSim.h
@@ -0,0 +1,42 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <memory>
+
+#include "frc/PneumaticsModuleType.h"
+#include "frc/simulation/PneumaticsBaseSim.h"
+
+namespace frc::sim {
+
+class SolenoidSim {
+ public:
+ SolenoidSim(std::shared_ptr<PneumaticsBaseSim> moduleSim, int channel);
+ SolenoidSim(int module, PneumaticsModuleType type, int channel);
+ SolenoidSim(PneumaticsModuleType type, int channel);
+
+ bool GetOutput() const;
+ void SetOutput(bool output);
+
+ /**
+ * Register a callback to be run when the output of this solenoid has changed.
+ *
+ * @param callback the callback
+ * @param initialNotify whether to run the callback with the initial state
+ * @return the {@link CallbackStore} object associated with this callback.
+ * Save a reference to this object; it being deconstructed cancels the
+ * callback.
+ */
+ [[nodiscard]] virtual std::unique_ptr<CallbackStore> RegisterOutputCallback(
+ NotifyCallback callback, bool initialNotify);
+
+ std::shared_ptr<PneumaticsBaseSim> GetModuleSim() const;
+
+ private:
+ std::shared_ptr<PneumaticsBaseSim> m_module;
+ int m_channel;
+};
+
+} // namespace frc::sim
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/FieldObject2d.h b/wpilibc/src/main/native/include/frc/smartdashboard/FieldObject2d.h
index 2e41d84..f55938e 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/FieldObject2d.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/FieldObject2d.h
@@ -5,16 +5,16 @@
#pragma once
#include <initializer_list>
+#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
-#include <networktables/NetworkTableEntry.h>
+#include <networktables/DoubleArrayTopic.h>
#include <units/length.h>
#include <wpi/SmallVector.h>
#include <wpi/mutex.h>
-#include <wpi/span.h>
#include "frc/geometry/Pose2d.h"
#include "frc/geometry/Rotation2d.h"
@@ -66,7 +66,7 @@
*
* @param poses array of 2D poses
*/
- void SetPoses(wpi::span<const Pose2d> poses);
+ void SetPoses(std::span<const Pose2d> poses);
/**
* Set multiple poses from an array of Pose objects.
@@ -97,7 +97,7 @@
* @param out output SmallVector to hold 2D poses
* @return span referring to output SmallVector
*/
- wpi::span<const Pose2d> GetPoses(wpi::SmallVectorImpl<Pose2d>& out) const;
+ std::span<const Pose2d> GetPoses(wpi::SmallVectorImpl<Pose2d>& out) const;
private:
void UpdateEntry(bool setDefault = false);
@@ -105,7 +105,7 @@
mutable wpi::mutex m_mutex;
std::string m_name;
- nt::NetworkTableEntry m_entry;
+ nt::DoubleArrayEntry m_entry;
mutable wpi::SmallVector<Pose2d, 1> m_poses;
};
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/Mechanism2d.h b/wpilibc/src/main/native/include/frc/smartdashboard/Mechanism2d.h
index cbe25be..c71bcaf 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/Mechanism2d.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/Mechanism2d.h
@@ -7,8 +7,10 @@
#include <memory>
#include <string>
+#include <networktables/DoubleArrayTopic.h>
#include <networktables/NTSendable.h>
-#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTable.h>
+#include <networktables/StringTopic.h>
#include <wpi/StringMap.h>
#include <wpi/mutex.h>
#include <wpi/sendable/SendableHelper.h>
@@ -79,9 +81,11 @@
private:
double m_width;
double m_height;
- char m_color[10];
+ std::string m_color;
mutable wpi::mutex m_mutex;
std::shared_ptr<nt::NetworkTable> m_table;
wpi::StringMap<std::unique_ptr<MechanismRoot2d>> m_roots;
+ nt::DoubleArrayPublisher m_dimsPub;
+ nt::StringPublisher m_colorPub;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/MechanismLigament2d.h b/wpilibc/src/main/native/include/frc/smartdashboard/MechanismLigament2d.h
index f1bebb9..f9c86fc 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/MechanismLigament2d.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/MechanismLigament2d.h
@@ -7,7 +7,8 @@
#include <memory>
#include <string_view>
-#include <networktables/NetworkTableEntry.h>
+#include <networktables/DoubleTopic.h>
+#include <networktables/StringTopic.h>
#include <units/angle.h>
#include "frc/smartdashboard/MechanismObject2d.h"
@@ -89,14 +90,14 @@
void UpdateEntries(std::shared_ptr<nt::NetworkTable> table) override;
private:
- void Flush();
+ nt::StringPublisher m_typePub;
double m_length;
- nt::NetworkTableEntry m_lengthEntry;
+ nt::DoubleEntry m_lengthEntry;
double m_angle;
- nt::NetworkTableEntry m_angleEntry;
+ nt::DoubleEntry m_angleEntry;
double m_weight;
- nt::NetworkTableEntry m_weightEntry;
+ nt::DoubleEntry m_weightEntry;
char m_color[10];
- nt::NetworkTableEntry m_colorEntry;
+ nt::StringEntry m_colorEntry;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/MechanismRoot2d.h b/wpilibc/src/main/native/include/frc/smartdashboard/MechanismRoot2d.h
index 5072547..37e0f7b 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/MechanismRoot2d.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/MechanismRoot2d.h
@@ -7,7 +7,7 @@
#include <memory>
#include <string_view>
-#include <networktables/NetworkTableEntry.h>
+#include <networktables/DoubleTopic.h>
#include "MechanismObject2d.h"
@@ -48,7 +48,7 @@
inline void Flush();
double m_x;
double m_y;
- nt::NetworkTableEntry m_xEntry;
- nt::NetworkTableEntry m_yEntry;
+ nt::DoublePublisher m_xPub;
+ nt::DoublePublisher m_yPub;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h
index 36830f6..4bd4289 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h
@@ -6,17 +6,18 @@
#include <functional>
#include <memory>
+#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
+#include <networktables/BooleanTopic.h>
#include <networktables/NTSendableBuilder.h>
#include <networktables/NetworkTable.h>
-#include <networktables/NetworkTableEntry.h>
-#include <networktables/NetworkTableValue.h>
+#include <networktables/StringTopic.h>
+#include <wpi/FunctionExtras.h>
#include <wpi/SmallVector.h>
-#include <wpi/span.h>
namespace frc {
@@ -54,7 +55,8 @@
bool IsActuator() const;
/**
- * Update the network table values by calling the getters for all properties.
+ * Synchronize with network table values by calling the getters for all
+ * properties and setters when the network table value has changed.
*/
void Update() override;
@@ -88,12 +90,18 @@
void SetSmartDashboardType(std::string_view type) override;
void SetActuator(bool value) override;
void SetSafeState(std::function<void()> func) override;
- void SetUpdateTable(std::function<void()> func) override;
- nt::NetworkTableEntry GetEntry(std::string_view key) override;
+ void SetUpdateTable(wpi::unique_function<void()> func) override;
+ nt::Topic GetTopic(std::string_view key) override;
void AddBooleanProperty(std::string_view key, std::function<bool()> getter,
std::function<void(bool)> setter) override;
+ void AddIntegerProperty(std::string_view key, std::function<int64_t()> getter,
+ std::function<void(int64_t)> setter) override;
+
+ void AddFloatProperty(std::string_view key, std::function<float()> getter,
+ std::function<void(float)> setter) override;
+
void AddDoubleProperty(std::string_view key, std::function<double()> getter,
std::function<void(double)> setter) override;
@@ -103,22 +111,28 @@
void AddBooleanArrayProperty(
std::string_view key, std::function<std::vector<int>()> getter,
- std::function<void(wpi::span<const int>)> setter) override;
+ std::function<void(std::span<const int>)> setter) override;
+
+ void AddIntegerArrayProperty(
+ std::string_view key, std::function<std::vector<int64_t>()> getter,
+ std::function<void(std::span<const int64_t>)> setter) override;
+
+ void AddFloatArrayProperty(
+ std::string_view key, std::function<std::vector<float>()> getter,
+ std::function<void(std::span<const float>)> setter) override;
void AddDoubleArrayProperty(
std::string_view key, std::function<std::vector<double>()> getter,
- std::function<void(wpi::span<const double>)> setter) override;
+ std::function<void(std::span<const double>)> setter) override;
void AddStringArrayProperty(
std::string_view key, std::function<std::vector<std::string>()> getter,
- std::function<void(wpi::span<const std::string>)> setter) override;
+ std::function<void(std::span<const std::string>)> setter) override;
- void AddRawProperty(std::string_view key, std::function<std::string()> getter,
- std::function<void(std::string_view)> setter) override;
-
- void AddValueProperty(
- std::string_view key, std::function<std::shared_ptr<nt::Value>()> getter,
- std::function<void(std::shared_ptr<nt::Value>)> setter) override;
+ void AddRawProperty(
+ std::string_view key, std::string_view typeString,
+ std::function<std::vector<uint8_t>()> getter,
+ std::function<void(std::span<const uint8_t>)> setter) override;
void AddSmallStringProperty(
std::string_view key,
@@ -127,82 +141,77 @@
void AddSmallBooleanArrayProperty(
std::string_view key,
- std::function<wpi::span<const int>(wpi::SmallVectorImpl<int>& buf)>
+ std::function<std::span<const int>(wpi::SmallVectorImpl<int>& buf)>
getter,
- std::function<void(wpi::span<const int>)> setter) override;
+ std::function<void(std::span<const int>)> setter) override;
+
+ void AddSmallIntegerArrayProperty(
+ std::string_view key,
+ std::function<
+ std::span<const int64_t>(wpi::SmallVectorImpl<int64_t>& buf)>
+ getter,
+ std::function<void(std::span<const int64_t>)> setter) override;
+
+ void AddSmallFloatArrayProperty(
+ std::string_view key,
+ std::function<std::span<const float>(wpi::SmallVectorImpl<float>& buf)>
+ getter,
+ std::function<void(std::span<const float>)> setter) override;
void AddSmallDoubleArrayProperty(
std::string_view key,
- std::function<wpi::span<const double>(wpi::SmallVectorImpl<double>& buf)>
+ std::function<std::span<const double>(wpi::SmallVectorImpl<double>& buf)>
getter,
- std::function<void(wpi::span<const double>)> setter) override;
+ std::function<void(std::span<const double>)> setter) override;
void AddSmallStringArrayProperty(
std::string_view key,
std::function<
- wpi::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+ std::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
getter,
- std::function<void(wpi::span<const std::string>)> setter) override;
+ std::function<void(std::span<const std::string>)> setter) override;
void AddSmallRawProperty(
- std::string_view key,
- std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
- std::function<void(std::string_view)> setter) override;
+ std::string_view key, std::string_view typeString,
+ std::function<std::span<uint8_t>(wpi::SmallVectorImpl<uint8_t>& buf)>
+ getter,
+ std::function<void(std::span<const uint8_t>)> setter) override;
private:
struct Property {
- Property(nt::NetworkTable& table, std::string_view key)
- : entry(table.GetEntry(key)) {}
-
- Property(const Property&) = delete;
- Property& operator=(const Property&) = delete;
-
- Property(Property&& other) noexcept
- : entry(other.entry),
- listener(other.listener),
- update(std::move(other.update)),
- createListener(std::move(other.createListener)) {
- other.entry = nt::NetworkTableEntry();
- other.listener = 0;
- }
-
- Property& operator=(Property&& other) noexcept {
- entry = other.entry;
- listener = other.listener;
- other.entry = nt::NetworkTableEntry();
- other.listener = 0;
- update = std::move(other.update);
- createListener = std::move(other.createListener);
- return *this;
- }
-
- ~Property() { StopListener(); }
-
- void StartListener() {
- if (entry && listener == 0 && createListener) {
- listener = createListener(entry);
- }
- }
-
- void StopListener() {
- if (entry && listener != 0) {
- entry.RemoveListener(listener);
- listener = 0;
- }
- }
-
- nt::NetworkTableEntry entry;
- NT_EntryListener listener = 0;
- std::function<void(nt::NetworkTableEntry entry, uint64_t time)> update;
- std::function<NT_EntryListener(nt::NetworkTableEntry entry)> createListener;
+ virtual ~Property() = default;
+ virtual void Update(bool controllable, int64_t time) = 0;
};
- std::vector<Property> m_properties;
+ template <typename Topic>
+ struct PropertyImpl : public Property {
+ void Update(bool controllable, int64_t time) override;
+
+ using Publisher = typename Topic::PublisherType;
+ using Subscriber = typename Topic::SubscriberType;
+ Publisher pub;
+ Subscriber sub;
+ std::function<void(Publisher& pub, int64_t time)> updateNetwork;
+ std::function<void(Subscriber& sub)> updateLocal;
+ };
+
+ template <typename Topic, typename Getter, typename Setter>
+ void AddPropertyImpl(Topic topic, Getter getter, Setter setter);
+
+ template <typename T, size_t Size, typename Topic, typename Getter,
+ typename Setter>
+ void AddSmallPropertyImpl(Topic topic, Getter getter, Setter setter);
+
+ std::vector<std::unique_ptr<Property>> m_properties;
std::function<void()> m_safeState;
- std::vector<std::function<void()>> m_updateTables;
+ std::vector<wpi::unique_function<void()>> m_updateTables;
std::shared_ptr<nt::NetworkTable> m_table;
- nt::NetworkTableEntry m_controllableEntry;
+ bool m_controllable = false;
bool m_actuator = false;
+
+ nt::BooleanPublisher m_controllablePublisher;
+ nt::StringPublisher m_typePublisher;
+ nt::BooleanPublisher m_actuatorPublisher;
};
} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h
index b693762..7fe0b59 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h
@@ -8,7 +8,6 @@
#include <string_view>
#include <wpi/StringMap.h>
-#include <wpi/deprecated.h>
#include "frc/smartdashboard/SendableChooserBase.h"
@@ -69,36 +68,6 @@
void SetDefaultOption(std::string_view name, T object);
/**
- * Adds the given object to the list of options.
- *
- * On the SmartDashboard on the desktop, the object will appear as the given
- * name.
- *
- * @deprecated use AddOption(std::string_view name, T object) instead.
- *
- * @param name the name of the option
- * @param object the option
- */
- WPI_DEPRECATED("use AddOption() instead")
- void AddObject(std::string_view name, T object) { AddOption(name, object); }
-
- /**
- * Add the given object to the list of options and marks it as the default.
- *
- * Functionally, this is very close to AddOption() except that it will use
- * this as the default option if none other is explicitly selected.
- *
- * @deprecated use SetDefaultOption(std::string_view name, T object) instead.
- *
- * @param name the name of the option
- * @param object the option
- */
- WPI_DEPRECATED("use SetDefaultOption() instead")
- void AddDefault(std::string_view name, T object) {
- SetDefaultOption(name, object);
- }
-
- /**
* Returns a copy of the selected option (a raw pointer U* if T =
* std::unique_ptr<U> or a std::weak_ptr<U> if T = std::shared_ptr<U>).
*
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc
index 25e2551..e90542b 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc
@@ -48,10 +48,17 @@
template <class T>
void SendableChooser<T>::InitSendable(nt::NTSendableBuilder& builder) {
builder.SetSmartDashboardType("String Chooser");
- builder.GetEntry(kInstance).SetDouble(m_instance);
+ {
+ std::scoped_lock lock(m_mutex);
+ m_instancePubs.emplace_back(
+ nt::IntegerTopic{builder.GetTopic(kInstance)}.Publish());
+ m_instancePubs.back().Set(m_instance);
+ m_activePubs.emplace_back(
+ nt::StringTopic{builder.GetTopic(kActive)}.Publish());
+ }
builder.AddStringArrayProperty(
kOptions,
- [=] {
+ [=, this] {
std::vector<std::string> keys;
for (const auto& choice : m_choices) {
keys.emplace_back(choice.first());
@@ -66,13 +73,13 @@
nullptr);
builder.AddSmallStringProperty(
kDefault,
- [=](wpi::SmallVectorImpl<char>&) -> std::string_view {
+ [=, this](wpi::SmallVectorImpl<char>&) -> std::string_view {
return m_defaultChoice;
},
nullptr);
builder.AddSmallStringProperty(
kActive,
- [=](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
+ [=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
std::scoped_lock lock(m_mutex);
if (m_haveSelected) {
buf.assign(m_selected.begin(), m_selected.end());
@@ -82,18 +89,15 @@
}
},
nullptr);
- {
- std::scoped_lock lock(m_mutex);
- m_activeEntries.emplace_back(builder.GetEntry(kActive));
- }
- builder.AddStringProperty(kSelected, nullptr, [=](std::string_view val) {
- std::scoped_lock lock(m_mutex);
- m_haveSelected = true;
- m_selected = val;
- for (auto& entry : m_activeEntries) {
- entry.SetString(val);
- }
- });
+ builder.AddStringProperty(kSelected, nullptr,
+ [=, this](std::string_view val) {
+ std::scoped_lock lock(m_mutex);
+ m_haveSelected = true;
+ m_selected = val;
+ for (auto& pub : m_activePubs) {
+ pub.Set(val);
+ }
+ });
}
template <class T>
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h
index 78f891a..b5df73c 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h
@@ -7,8 +7,9 @@
#include <atomic>
#include <string>
+#include <networktables/IntegerTopic.h>
#include <networktables/NTSendable.h>
-#include <networktables/NetworkTableEntry.h>
+#include <networktables/StringTopic.h>
#include <wpi/SmallVector.h>
#include <wpi/mutex.h>
#include <wpi/sendable/SendableHelper.h>
@@ -40,7 +41,8 @@
std::string m_defaultChoice;
std::string m_selected;
bool m_haveSelected = false;
- wpi::SmallVector<nt::NetworkTableEntry, 2> m_activeEntries;
+ wpi::SmallVector<nt::IntegerPublisher, 2> m_instancePubs;
+ wpi::SmallVector<nt::StringPublisher, 2> m_activePubs;
wpi::mutex m_mutex;
int m_instance;
static std::atomic_int s_instances;
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h b/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h
index 47c4a28..aeb4947 100644
--- a/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h
@@ -5,13 +5,13 @@
#pragma once
#include <memory>
+#include <span>
#include <string>
#include <string_view>
#include <vector>
#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableValue.h>
-#include <wpi/span.h>
namespace wpi {
class Sendable;
@@ -63,39 +63,6 @@
static bool IsPersistent(std::string_view key);
/**
- * Sets flags on the specified key in this table. The key can
- * not be null.
- *
- * @param key the key name
- * @param flags the flags to set (bitmask)
- */
- static void SetFlags(std::string_view key, unsigned int flags);
-
- /**
- * Clears flags on the specified key in this table. The key can
- * not be null.
- *
- * @param key the key name
- * @param flags the flags to clear (bitmask)
- */
- static void ClearFlags(std::string_view key, unsigned int flags);
-
- /**
- * Returns the flags for the specified key.
- *
- * @param key the key name
- * @return the flags, or 0 if the key is not defined
- */
- static unsigned int GetFlags(std::string_view key);
-
- /**
- * Deletes the specified key in this table.
- *
- * @param key the key name
- */
- static void Delete(std::string_view key);
-
- /**
* Returns an NT Entry mapping to the specified key
*
* This is useful if an entry is used often, or is read and then modified.
@@ -249,7 +216,7 @@
* std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
- static bool PutBooleanArray(std::string_view key, wpi::span<const int> value);
+ static bool PutBooleanArray(std::string_view key, std::span<const int> value);
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -259,7 +226,7 @@
* @returns False if the table key exists with a different type
*/
static bool SetDefaultBooleanArray(std::string_view key,
- wpi::span<const int> defaultValue);
+ std::span<const int> defaultValue);
/**
* Returns the boolean array the key maps to.
@@ -280,7 +247,7 @@
* non-zero value is true.
*/
static std::vector<int> GetBooleanArray(std::string_view key,
- wpi::span<const int> defaultValue);
+ std::span<const int> defaultValue);
/**
* Put a number array in the table.
@@ -290,7 +257,7 @@
* @return False if the table key already exists with a different type
*/
static bool PutNumberArray(std::string_view key,
- wpi::span<const double> value);
+ std::span<const double> value);
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -300,7 +267,7 @@
* @returns False if the table key exists with a different type
*/
static bool SetDefaultNumberArray(std::string_view key,
- wpi::span<const double> defaultValue);
+ std::span<const double> defaultValue);
/**
* Returns the number array the key maps to.
@@ -317,7 +284,7 @@
* use GetValue() instead.
*/
static std::vector<double> GetNumberArray(
- std::string_view key, wpi::span<const double> defaultValue);
+ std::string_view key, std::span<const double> defaultValue);
/**
* Put a string array in the table.
@@ -327,7 +294,7 @@
* @return False if the table key already exists with a different type
*/
static bool PutStringArray(std::string_view key,
- wpi::span<const std::string> value);
+ std::span<const std::string> value);
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -337,7 +304,7 @@
* @returns False if the table key exists with a different type
*/
static bool SetDefaultStringArray(std::string_view key,
- wpi::span<const std::string> defaultValue);
+ std::span<const std::string> defaultValue);
/**
* Returns the string array the key maps to.
@@ -354,7 +321,7 @@
* use GetValue() instead.
*/
static std::vector<std::string> GetStringArray(
- std::string_view key, wpi::span<const std::string> defaultValue);
+ std::string_view key, std::span<const std::string> defaultValue);
/**
* Put a raw value (byte array) in the table.
@@ -363,7 +330,7 @@
* @param value The value that will be assigned.
* @return False if the table key already exists with a different type
*/
- static bool PutRaw(std::string_view key, std::string_view value);
+ static bool PutRaw(std::string_view key, std::span<const uint8_t> value);
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -373,7 +340,7 @@
* @returns False if the table key exists with a different type
*/
static bool SetDefaultRaw(std::string_view key,
- std::string_view defaultValue);
+ std::span<const uint8_t> defaultValue);
/**
* Returns the raw value (byte array) the key maps to.
@@ -389,8 +356,8 @@
* @note This makes a copy of the raw contents. If the overhead of this is a
* concern, use GetValue() instead.
*/
- static std::string GetRaw(std::string_view key,
- std::string_view defaultValue);
+ static std::vector<uint8_t> GetRaw(std::string_view key,
+ std::span<const uint8_t> defaultValue);
/**
* Maps the specified key to the specified complex value (such as an array) in
@@ -403,8 +370,7 @@
* @param value the value
* @return False if the table key already exists with a different type
*/
- static bool PutValue(std::string_view keyName,
- std::shared_ptr<nt::Value> value);
+ static bool PutValue(std::string_view keyName, const nt::Value& value);
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -414,7 +380,7 @@
* @returns False if the table key exists with a different type
*/
static bool SetDefaultValue(std::string_view key,
- std::shared_ptr<nt::Value> defaultValue);
+ const nt::Value& defaultValue);
/**
* Retrieves the complex value (such as an array) in this table into the
@@ -422,7 +388,7 @@
*
* @param keyName the key
*/
- static std::shared_ptr<nt::Value> GetValue(std::string_view keyName);
+ static nt::Value GetValue(std::string_view keyName);
/**
* Posts a task from a listener to the ListenerExecutor, so that it can be run
diff --git a/wpilibc/src/main/native/include/frc/util/Color.h b/wpilibc/src/main/native/include/frc/util/Color.h
index 00bc4af..87d8c12 100644
--- a/wpilibc/src/main/native/include/frc/util/Color.h
+++ b/wpilibc/src/main/native/include/frc/util/Color.h
@@ -5,6 +5,7 @@
#pragma once
#include <algorithm>
+#include <string>
namespace frc {
@@ -741,7 +742,7 @@
constexpr Color() = default;
/**
- * Constructs a Color.
+ * Constructs a Color from doubles (0-1).
*
* @param r Red value (0-1)
* @param g Green value (0-1)
@@ -753,41 +754,70 @@
blue(roundAndClamp(b)) {}
/**
+ * Constructs a Color from ints (0-255).
+ *
+ * @param r Red value (0-255)
+ * @param g Green value (0-255)
+ * @param b Blue value (0-255)
+ */
+ constexpr Color(int r, int g, int b)
+ : Color(r / 255.0, g / 255.0, b / 255.0) {}
+
+ constexpr bool operator==(const Color&) const = default;
+
+ /**
* Creates a Color from HSV values.
*
- * @param h The h value [0-180]
+ * @param h The h value [0-180)
* @param s The s value [0-255]
* @param v The v value [0-255]
* @return The color
*/
static constexpr Color FromHSV(int h, int s, int v) {
- if (s == 0) {
- return {v / 255.0, v / 255.0, v / 255.0};
- }
+ // Loosely based on
+ // https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB
+ // The hue range is split into 60 degree regions where in each region there
+ // is one rgb component at a low value (m), one at a high value (v) and one
+ // that changes (X) from low to high (X+m) or high to low (v-X)
- int region = h / 30;
- int remainder = (h - (region * 30)) * 6;
+ // Difference between highest and lowest value of any rgb component
+ int chroma = (s * v) >> 8;
- int p = (v * (255 - s)) >> 8;
- int q = (v * (255 - ((s * remainder) >> 8))) >> 8;
- int t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
+ // Because hue is 0-180 rather than 0-360 use 30 not 60
+ int region = (h / 30) % 6;
+
+ // Remainder converted from 0-30 to 0-255
+ int remainder = static_cast<int>((h % 30) * (255 / 30.0));
+
+ // Value of the lowest rgb component
+ int m = v - chroma;
+
+ // Goes from 0 to chroma as hue increases
+ int X = (chroma * remainder) >> 8;
switch (region) {
case 0:
- return Color(v / 255.0, t / 255.0, p / 255.0);
+ return Color(v, X + m, m);
case 1:
- return Color(q / 255.0, v / 255.0, p / 255.0);
+ return Color(v - X, v, m);
case 2:
- return Color(p / 255.0, v / 255.0, t / 255.0);
+ return Color(m, v, X + m);
case 3:
- return Color(p / 255.0, q / 255.0, v / 255.0);
+ return Color(m, v - X, v);
case 4:
- return Color(t / 255.0, p / 255.0, v / 255.0);
+ return Color(X + m, m, v);
default:
- return Color(v / 255.0, p / 255.0, q / 255.0);
+ return Color(v, m, v - X);
}
}
+ /**
+ * Return this color represented as a hex string.
+ *
+ * @return a string of the format <tt>\#RRGGBB</tt>
+ */
+ std::string HexString() const;
+
double red = 0.0;
double green = 0.0;
double blue = 0.0;
@@ -802,14 +832,6 @@
}
};
-inline bool operator==(const Color& c1, const Color& c2) {
- return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
-}
-
-inline bool operator!=(const Color& c1, const Color& c2) {
- return !(c1 == c2);
-}
-
/*
* FIRST Colors
*/
diff --git a/wpilibc/src/main/native/include/frc/util/Color8Bit.h b/wpilibc/src/main/native/include/frc/util/Color8Bit.h
index 62cbde9..10afead 100644
--- a/wpilibc/src/main/native/include/frc/util/Color8Bit.h
+++ b/wpilibc/src/main/native/include/frc/util/Color8Bit.h
@@ -5,6 +5,7 @@
#pragma once
#include <algorithm>
+#include <string>
#include "Color.h"
@@ -43,13 +44,18 @@
return Color(red / 255.0, green / 255.0, blue / 255.0);
}
+ constexpr bool operator==(const Color8Bit&) const = default;
+
+ /**
+ * Return this color represented as a hex string.
+ *
+ * @return a string of the format <tt>\#RRGGBB</tt>
+ */
+ std::string HexString() const;
+
int red = 0;
int green = 0;
int blue = 0;
};
-inline bool operator==(const Color8Bit& c1, const Color8Bit& c2) {
- return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
-}
-
} // namespace frc
diff --git a/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp b/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp
deleted file mode 100644
index 38e1592..0000000
--- a/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "frc/motorcontrol/MotorControllerGroup.h" // NOLINT(build/include_order)
-
-#include <memory>
-#include <vector>
-
-#include "MockMotorController.h"
-#include "gtest/gtest.h"
-
-using namespace frc;
-
-enum MotorControllerGroupTestType { TEST_ONE, TEST_TWO, TEST_THREE };
-
-std::ostream& operator<<(std::ostream& os,
- const MotorControllerGroupTestType& type) {
- switch (type) {
- case TEST_ONE:
- os << "MotorControllerGroup with one speed controller";
- break;
- case TEST_TWO:
- os << "MotorControllerGroup with two speed controllers";
- break;
- case TEST_THREE:
- os << "MotorControllerGroup with three speed controllers";
- break;
- }
-
- return os;
-}
-
-/**
- * A fixture used for MotorControllerGroup testing.
- */
-class MotorControllerGroupTest
- : public testing::TestWithParam<MotorControllerGroupTestType> {
- protected:
- std::vector<MockMotorController> m_speedControllers;
- std::unique_ptr<MotorControllerGroup> m_group;
-
- void SetUp() override {
- switch (GetParam()) {
- case TEST_ONE: {
- m_speedControllers.emplace_back();
- m_group = std::make_unique<MotorControllerGroup>(m_speedControllers[0]);
- break;
- }
-
- case TEST_TWO: {
- m_speedControllers.emplace_back();
- m_speedControllers.emplace_back();
- m_group = std::make_unique<MotorControllerGroup>(m_speedControllers[0],
- m_speedControllers[1]);
- break;
- }
-
- case TEST_THREE: {
- m_speedControllers.emplace_back();
- m_speedControllers.emplace_back();
- m_speedControllers.emplace_back();
- m_group = std::make_unique<MotorControllerGroup>(m_speedControllers[0],
- m_speedControllers[1],
- m_speedControllers[2]);
- break;
- }
- }
- }
-};
-
-TEST_P(MotorControllerGroupTest, Set) {
- m_group->Set(1.0);
-
- for (auto& speedController : m_speedControllers) {
- EXPECT_FLOAT_EQ(speedController.Get(), 1.0);
- }
-}
-
-TEST_P(MotorControllerGroupTest, GetInverted) {
- m_group->SetInverted(true);
-
- EXPECT_TRUE(m_group->GetInverted());
-}
-
-TEST_P(MotorControllerGroupTest, SetInvertedDoesNotModifyMotorControllers) {
- for (auto& speedController : m_speedControllers) {
- speedController.SetInverted(false);
- }
- m_group->SetInverted(true);
-
- for (auto& speedController : m_speedControllers) {
- EXPECT_EQ(speedController.GetInverted(), false);
- }
-}
-
-TEST_P(MotorControllerGroupTest, SetInvertedDoesInvert) {
- m_group->SetInverted(true);
- m_group->Set(1.0);
-
- for (auto& speedController : m_speedControllers) {
- EXPECT_FLOAT_EQ(speedController.Get(), -1.0);
- }
-}
-
-TEST_P(MotorControllerGroupTest, Disable) {
- m_group->Set(1.0);
- m_group->Disable();
-
- for (auto& speedController : m_speedControllers) {
- EXPECT_FLOAT_EQ(speedController.Get(), 0.0);
- }
-}
-
-TEST_P(MotorControllerGroupTest, StopMotor) {
- m_group->Set(1.0);
- m_group->StopMotor();
-
- for (auto& speedController : m_speedControllers) {
- EXPECT_FLOAT_EQ(speedController.Get(), 0.0);
- }
-}
-
-INSTANTIATE_TEST_SUITE_P(Tests, MotorControllerGroupTest,
- testing::Values(TEST_ONE, TEST_TWO, TEST_THREE));
diff --git a/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp b/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp
index 12ae5d2..99bd0fd 100644
--- a/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp
+++ b/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp
@@ -14,8 +14,9 @@
throw std::invalid_argument("Null value");
}
if (value->type != HAL_BOOLEAN) {
- throw std::invalid_argument(
- fmt::format("Wrong type '{}' for boolean", value->type).c_str());
+ throw std::invalid_argument(fmt::format("Wrong type '{}' for boolean",
+ static_cast<int>(value->type))
+ .c_str());
}
m_wasTriggered = true;
m_lastValue = value->data.v_boolean;
@@ -28,7 +29,8 @@
}
if (value->type != HAL_ENUM) {
throw std::invalid_argument(
- fmt::format("Wrong type '{}' for enum", value->type).c_str());
+ fmt::format("Wrong type '{}' for enum", static_cast<int>(value->type))
+ .c_str());
}
m_wasTriggered = true;
@@ -41,8 +43,9 @@
throw std::invalid_argument("Null value");
}
if (value->type != HAL_INT) {
- throw std::invalid_argument(
- fmt::format("Wrong type '{}' for integer", value->type).c_str());
+ throw std::invalid_argument(fmt::format("Wrong type '{}' for integer",
+ static_cast<int>(value->type))
+ .c_str());
}
m_wasTriggered = true;
@@ -56,7 +59,8 @@
}
if (value->type != HAL_LONG) {
throw std::invalid_argument(
- fmt::format("Wrong type '{}' for long", value->type).c_str());
+ fmt::format("Wrong type '{}' for long", static_cast<int>(value->type))
+ .c_str());
}
m_wasTriggered = true;
@@ -70,7 +74,8 @@
}
if (value->type != HAL_DOUBLE) {
throw std::invalid_argument(
- fmt::format("Wrong type '{}' for double", value->type).c_str());
+ fmt::format("Wrong type '{}' for double", static_cast<int>(value->type))
+ .c_str());
}
m_wasTriggered = true;
diff --git a/wpilibc/src/test/native/cpp/TimedRobotTest.cpp b/wpilibc/src/test/native/cpp/TimedRobotTest.cpp
index ea9656b..08c262b 100644
--- a/wpilibc/src/test/native/cpp/TimedRobotTest.cpp
+++ b/wpilibc/src/test/native/cpp/TimedRobotTest.cpp
@@ -9,6 +9,7 @@
#include <atomic>
#include <thread>
+#include "frc/livewindow/LiveWindow.h"
#include "frc/simulation/DriverStationSim.h"
#include "frc/simulation/SimHooks.h"
#include "gtest/gtest.h"
@@ -16,7 +17,7 @@
using namespace frc;
namespace {
-class TimedRobotTest : public ::testing::Test {
+class TimedRobotTest : public ::testing::TestWithParam<bool> {
protected:
void SetUp() override { frc::sim::PauseTiming(); }
@@ -304,8 +305,11 @@
robotThread.join();
}
-TEST_F(TimedRobotTest, TestMode) {
+TEST_P(TimedRobotTest, TestMode) {
+ bool isTestLW = GetParam();
+
MockRobot robot;
+ robot.EnableLiveWindowInTest(isTestLW);
std::thread robotThread{[&] { robot.StartCompetition(); }};
@@ -321,6 +325,7 @@
EXPECT_EQ(0u, robot.m_autonomousInitCount);
EXPECT_EQ(0u, robot.m_teleopInitCount);
EXPECT_EQ(0u, robot.m_testInitCount);
+ EXPECT_FALSE(frc::LiveWindow::IsEnabled());
EXPECT_EQ(0u, robot.m_robotPeriodicCount);
EXPECT_EQ(0u, robot.m_simulationPeriodicCount);
@@ -342,6 +347,9 @@
EXPECT_EQ(0u, robot.m_autonomousInitCount);
EXPECT_EQ(0u, robot.m_teleopInitCount);
EXPECT_EQ(1u, robot.m_testInitCount);
+ EXPECT_EQ(isTestLW, frc::LiveWindow::IsEnabled());
+
+ EXPECT_THROW(robot.EnableLiveWindowInTest(isTestLW), std::runtime_error);
EXPECT_EQ(1u, robot.m_robotPeriodicCount);
EXPECT_EQ(1u, robot.m_simulationPeriodicCount);
@@ -376,6 +384,32 @@
EXPECT_EQ(0u, robot.m_teleopExitCount);
EXPECT_EQ(0u, robot.m_testExitCount);
+ frc::sim::DriverStationSim::SetEnabled(false);
+ frc::sim::DriverStationSim::SetAutonomous(false);
+ frc::sim::DriverStationSim::SetTest(false);
+ frc::sim::DriverStationSim::NotifyNewData();
+ frc::sim::StepTiming(20_ms); // Wait for Notifiers
+
+ EXPECT_EQ(1u, robot.m_robotInitCount);
+ EXPECT_EQ(1u, robot.m_simulationInitCount);
+ EXPECT_EQ(1u, robot.m_disabledInitCount);
+ EXPECT_EQ(0u, robot.m_autonomousInitCount);
+ EXPECT_EQ(0u, robot.m_teleopInitCount);
+ EXPECT_EQ(1u, robot.m_testInitCount);
+ EXPECT_FALSE(frc::LiveWindow::IsEnabled());
+
+ EXPECT_EQ(3u, robot.m_robotPeriodicCount);
+ EXPECT_EQ(3u, robot.m_simulationPeriodicCount);
+ EXPECT_EQ(1u, robot.m_disabledPeriodicCount);
+ EXPECT_EQ(0u, robot.m_autonomousPeriodicCount);
+ EXPECT_EQ(0u, robot.m_teleopPeriodicCount);
+ EXPECT_EQ(2u, robot.m_testPeriodicCount);
+
+ EXPECT_EQ(0u, robot.m_disabledExitCount);
+ EXPECT_EQ(0u, robot.m_autonomousExitCount);
+ EXPECT_EQ(0u, robot.m_teleopExitCount);
+ EXPECT_EQ(1u, robot.m_testExitCount);
+
robot.EndCompetition();
robotThread.join();
}
@@ -418,6 +452,7 @@
frc::sim::DriverStationSim::SetEnabled(true);
frc::sim::DriverStationSim::SetAutonomous(true);
frc::sim::DriverStationSim::SetTest(false);
+ frc::sim::DriverStationSim::NotifyNewData();
frc::sim::StepTiming(20_ms);
@@ -435,6 +470,7 @@
frc::sim::DriverStationSim::SetEnabled(true);
frc::sim::DriverStationSim::SetAutonomous(false);
frc::sim::DriverStationSim::SetTest(false);
+ frc::sim::DriverStationSim::NotifyNewData();
frc::sim::StepTiming(20_ms);
@@ -452,6 +488,7 @@
frc::sim::DriverStationSim::SetEnabled(true);
frc::sim::DriverStationSim::SetAutonomous(false);
frc::sim::DriverStationSim::SetTest(true);
+ frc::sim::DriverStationSim::NotifyNewData();
frc::sim::StepTiming(20_ms);
@@ -469,6 +506,7 @@
frc::sim::DriverStationSim::SetEnabled(false);
frc::sim::DriverStationSim::SetAutonomous(false);
frc::sim::DriverStationSim::SetTest(false);
+ frc::sim::DriverStationSim::NotifyNewData();
frc::sim::StepTiming(20_ms);
@@ -568,3 +606,5 @@
robot.EndCompetition();
robotThread.join();
}
+
+INSTANTIATE_TEST_SUITE_P(TimedRobotTests, TimedRobotTest, testing::Bool());
diff --git a/wpilibc/src/test/native/cpp/UnitNetworkTablesTest.cpp b/wpilibc/src/test/native/cpp/UnitNetworkTablesTest.cpp
new file mode 100644
index 0000000..505f906
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/UnitNetworkTablesTest.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include <networktables/DoubleTopic.h>
+#include <networktables/NetworkTableInstance.h>
+#include <networktables/UnitTopic.h>
+#include <units/length.h>
+
+#include "gtest/gtest.h"
+
+class UnitNetworkTablesTest : public ::testing::Test {
+ public:
+ UnitNetworkTablesTest() : inst{nt::NetworkTableInstance::Create()} {}
+ ~UnitNetworkTablesTest() override { nt::NetworkTableInstance::Destroy(inst); }
+ nt::NetworkTableInstance inst;
+};
+
+TEST_F(UnitNetworkTablesTest, Publish) {
+ auto topic = nt::UnitTopic<units::meter_t>{inst.GetTopic("meterTest")};
+ auto pub = topic.Publish();
+ pub.Set(2_m);
+ ASSERT_EQ(topic.GetProperty("unit"), "meter");
+ ASSERT_TRUE(topic.IsMatchingUnit());
+}
+
+TEST_F(UnitNetworkTablesTest, SubscribeDouble) {
+ auto topic = nt::UnitTopic<units::meter_t>{inst.GetTopic("meterTest")};
+ auto pub = topic.Publish();
+ auto sub = inst.GetDoubleTopic("meterTest").Subscribe(0);
+ ASSERT_EQ(sub.Get(), 0);
+ ASSERT_EQ(sub.Get(3), 3);
+ pub.Set(2_m);
+ ASSERT_EQ(sub.Get(), 2);
+}
+
+TEST_F(UnitNetworkTablesTest, SubscribeUnit) {
+ auto topic = nt::UnitTopic<units::meter_t>{inst.GetTopic("meterTest")};
+ auto pub = topic.Publish();
+ auto sub = topic.Subscribe(0_m);
+ ASSERT_EQ(sub.Get(), 0_m);
+ ASSERT_EQ(sub.Get(3_m), 3_m);
+ pub.Set(2_m);
+ ASSERT_EQ(sub.Get(), 2_m);
+}
diff --git a/wpilibc/src/test/native/cpp/drive/DifferentialDriveTest.cpp b/wpilibc/src/test/native/cpp/drive/DifferentialDriveTest.cpp
index b930346..1f542be 100644
--- a/wpilibc/src/test/native/cpp/drive/DifferentialDriveTest.cpp
+++ b/wpilibc/src/test/native/cpp/drive/DifferentialDriveTest.cpp
@@ -2,9 +2,9 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
-#include "MockMotorController.h"
#include "frc/drive/DifferentialDrive.h"
#include "gtest/gtest.h"
+#include "motorcontrol/MockMotorController.h"
TEST(DifferentialDriveTest, ArcadeDriveIK) {
// Forward
@@ -13,12 +13,12 @@
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Forward left turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, -0.5, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, 0.5, false);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(0.5, speeds.right);
// Forward right turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, 0.5, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.5, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
@@ -28,32 +28,32 @@
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Backward left turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, -0.5, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, 0.5, false);
EXPECT_DOUBLE_EQ(-0.5, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
// Backward right turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, 0.5, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(-0.5, speeds.right);
// Left turn (xSpeed with negative sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, -1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, 1.0, false);
EXPECT_DOUBLE_EQ(-1.0, speeds.left);
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Left turn (xSpeed with positive sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, -1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, 1.0, false);
EXPECT_DOUBLE_EQ(-1.0, speeds.left);
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Right turn (xSpeed with negative sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, 1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, -1.0, false);
EXPECT_DOUBLE_EQ(1.0, speeds.left);
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Right turn (xSpeed with positive sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, 1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, -1.0, false);
EXPECT_DOUBLE_EQ(1.0, speeds.left);
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
}
@@ -65,12 +65,12 @@
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Forward left turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, -0.5, true);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, 0.5, true);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(0.25, speeds.right);
// Forward right turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, 0.5, true);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.25, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
@@ -80,32 +80,32 @@
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Backward left turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, -0.5, true);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, 0.5, true);
EXPECT_DOUBLE_EQ(-0.25, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
// Backward right turn
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, 0.5, true);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(-0.25, speeds.right);
// Left turn (xSpeed with negative sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, -1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, 1.0, false);
EXPECT_DOUBLE_EQ(-1.0, speeds.left);
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Left turn (xSpeed with positive sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, -1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, 1.0, false);
EXPECT_DOUBLE_EQ(-1.0, speeds.left);
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Right turn (xSpeed with negative sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, 1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(-0.0, -1.0, false);
EXPECT_DOUBLE_EQ(1.0, speeds.left);
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Right turn (xSpeed with positive sign)
- speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, 1.0, false);
+ speeds = frc::DifferentialDrive::ArcadeDriveIK(0.0, -1.0, false);
EXPECT_DOUBLE_EQ(1.0, speeds.left);
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
}
@@ -117,12 +117,12 @@
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Forward left turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, -0.5, false);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, 0.5, false);
EXPECT_DOUBLE_EQ(0.25, speeds.left);
EXPECT_DOUBLE_EQ(0.75, speeds.right);
// Forward right turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, 0.5, false);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.75, speeds.left);
EXPECT_DOUBLE_EQ(0.25, speeds.right);
@@ -132,12 +132,12 @@
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Backward left turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, -0.5, false);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, 0.5, false);
EXPECT_DOUBLE_EQ(-0.75, speeds.left);
EXPECT_DOUBLE_EQ(-0.25, speeds.right);
// Backward right turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, 0.5, false);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, -0.5, false);
EXPECT_DOUBLE_EQ(-0.25, speeds.left);
EXPECT_DOUBLE_EQ(-0.75, speeds.right);
}
@@ -149,12 +149,12 @@
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Forward left turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, -0.5, true);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, 0.5, true);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(1.0, speeds.right);
// Forward right turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, 0.5, true);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(0.5, -0.5, true);
EXPECT_DOUBLE_EQ(1.0, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
@@ -164,12 +164,12 @@
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
// Backward left turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, -0.5, true);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, 0.5, true);
EXPECT_DOUBLE_EQ(-1.0, speeds.left);
EXPECT_DOUBLE_EQ(0.0, speeds.right);
// Backward right turn
- speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, 0.5, true);
+ speeds = frc::DifferentialDrive::CurvatureDriveIK(-0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.0, speeds.left);
EXPECT_DOUBLE_EQ(-1.0, speeds.right);
}
@@ -250,12 +250,12 @@
EXPECT_DOUBLE_EQ(1.0, right.Get());
// Forward left turn
- drive.ArcadeDrive(0.5, -0.5, false);
+ drive.ArcadeDrive(0.5, 0.5, false);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(0.5, right.Get());
// Forward right turn
- drive.ArcadeDrive(0.5, 0.5, false);
+ drive.ArcadeDrive(0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.5, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
@@ -265,12 +265,12 @@
EXPECT_DOUBLE_EQ(-1.0, right.Get());
// Backward left turn
- drive.ArcadeDrive(-0.5, -0.5, false);
+ drive.ArcadeDrive(-0.5, 0.5, false);
EXPECT_DOUBLE_EQ(-0.5, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
// Backward right turn
- drive.ArcadeDrive(-0.5, 0.5, false);
+ drive.ArcadeDrive(-0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(-0.5, right.Get());
}
@@ -287,12 +287,12 @@
EXPECT_DOUBLE_EQ(1.0, right.Get());
// Forward left turn
- drive.ArcadeDrive(0.5, -0.5, true);
+ drive.ArcadeDrive(0.5, 0.5, true);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(0.25, right.Get());
// Forward right turn
- drive.ArcadeDrive(0.5, 0.5, true);
+ drive.ArcadeDrive(0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.25, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
@@ -302,12 +302,12 @@
EXPECT_DOUBLE_EQ(-1.0, right.Get());
// Backward left turn
- drive.ArcadeDrive(-0.5, -0.5, true);
+ drive.ArcadeDrive(-0.5, 0.5, true);
EXPECT_DOUBLE_EQ(-0.25, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
// Backward right turn
- drive.ArcadeDrive(-0.5, 0.5, true);
+ drive.ArcadeDrive(-0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(-0.25, right.Get());
}
@@ -324,12 +324,12 @@
EXPECT_DOUBLE_EQ(1.0, right.Get());
// Forward left turn
- drive.CurvatureDrive(0.5, -0.5, false);
+ drive.CurvatureDrive(0.5, 0.5, false);
EXPECT_DOUBLE_EQ(0.25, left.Get());
EXPECT_DOUBLE_EQ(0.75, right.Get());
// Forward right turn
- drive.CurvatureDrive(0.5, 0.5, false);
+ drive.CurvatureDrive(0.5, -0.5, false);
EXPECT_DOUBLE_EQ(0.75, left.Get());
EXPECT_DOUBLE_EQ(0.25, right.Get());
@@ -339,12 +339,12 @@
EXPECT_DOUBLE_EQ(-1.0, right.Get());
// Backward left turn
- drive.CurvatureDrive(-0.5, -0.5, false);
+ drive.CurvatureDrive(-0.5, 0.5, false);
EXPECT_DOUBLE_EQ(-0.75, left.Get());
EXPECT_DOUBLE_EQ(-0.25, right.Get());
// Backward right turn
- drive.CurvatureDrive(-0.5, 0.5, false);
+ drive.CurvatureDrive(-0.5, -0.5, false);
EXPECT_DOUBLE_EQ(-0.25, left.Get());
EXPECT_DOUBLE_EQ(-0.75, right.Get());
}
@@ -361,12 +361,12 @@
EXPECT_DOUBLE_EQ(1.0, right.Get());
// Forward left turn
- drive.CurvatureDrive(0.5, -0.5, true);
+ drive.CurvatureDrive(0.5, 0.5, true);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(1.0, right.Get());
// Forward right turn
- drive.CurvatureDrive(0.5, 0.5, true);
+ drive.CurvatureDrive(0.5, -0.5, true);
EXPECT_DOUBLE_EQ(1.0, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
@@ -376,12 +376,12 @@
EXPECT_DOUBLE_EQ(-1.0, right.Get());
// Backward left turn
- drive.CurvatureDrive(-0.5, -0.5, true);
+ drive.CurvatureDrive(-0.5, 0.5, true);
EXPECT_DOUBLE_EQ(-1.0, left.Get());
EXPECT_DOUBLE_EQ(0.0, right.Get());
// Backward right turn
- drive.CurvatureDrive(-0.5, 0.5, true);
+ drive.CurvatureDrive(-0.5, -0.5, true);
EXPECT_DOUBLE_EQ(0.0, left.Get());
EXPECT_DOUBLE_EQ(-1.0, right.Get());
}
diff --git a/wpilibc/src/test/native/cpp/drive/KilloughDriveTest.cpp b/wpilibc/src/test/native/cpp/drive/KilloughDriveTest.cpp
deleted file mode 100644
index c23c7b0..0000000
--- a/wpilibc/src/test/native/cpp/drive/KilloughDriveTest.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include <cmath>
-
-#include "MockMotorController.h"
-#include "frc/drive/KilloughDrive.h"
-#include "gtest/gtest.h"
-
-TEST(KilloughDriveTest, CartesianIK) {
- frc::MockMotorController left;
- frc::MockMotorController right;
- frc::MockMotorController back;
- frc::KilloughDrive drive{left, right, back};
-
- // Forward
- auto speeds = drive.DriveCartesianIK(1.0, 0.0, 0.0);
- EXPECT_DOUBLE_EQ(0.5, speeds.left);
- EXPECT_DOUBLE_EQ(-0.5, speeds.right);
- EXPECT_NEAR(0.0, speeds.back, 1e-9);
-
- // Left
- speeds = drive.DriveCartesianIK(0.0, -1.0, 0.0);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, speeds.left);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, speeds.right);
- EXPECT_DOUBLE_EQ(1.0, speeds.back);
-
- // Right
- speeds = drive.DriveCartesianIK(0.0, 1.0, 0.0);
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, speeds.left);
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, speeds.right);
- EXPECT_DOUBLE_EQ(-1.0, speeds.back);
-
- // Rotate CCW
- speeds = drive.DriveCartesianIK(0.0, 0.0, -1.0);
- EXPECT_DOUBLE_EQ(-1.0, speeds.left);
- EXPECT_DOUBLE_EQ(-1.0, speeds.right);
- EXPECT_DOUBLE_EQ(-1.0, speeds.back);
-
- // Rotate CW
- speeds = drive.DriveCartesianIK(0.0, 0.0, 1.0);
- EXPECT_DOUBLE_EQ(1.0, speeds.left);
- EXPECT_DOUBLE_EQ(1.0, speeds.right);
- EXPECT_DOUBLE_EQ(1.0, speeds.back);
-}
-
-TEST(KilloughDriveTest, CartesianIKGyro90CW) {
- frc::MockMotorController left;
- frc::MockMotorController right;
- frc::MockMotorController back;
- frc::KilloughDrive drive{left, right, back};
-
- // Forward in global frame; left in robot frame
- auto speeds = drive.DriveCartesianIK(1.0, 0.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, speeds.left);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, speeds.right);
- EXPECT_DOUBLE_EQ(1.0, speeds.back);
-
- // Left in global frame; backward in robot frame
- speeds = drive.DriveCartesianIK(0.0, -1.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(-0.5, speeds.left);
- EXPECT_NEAR(0.5, speeds.right, 1e-9);
- EXPECT_NEAR(0.0, speeds.back, 1e-9);
-
- // Right in global frame; forward in robot frame
- speeds = drive.DriveCartesianIK(0.0, 1.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(0.5, speeds.left);
- EXPECT_NEAR(-0.5, speeds.right, 1e-9);
- EXPECT_NEAR(0.0, speeds.back, 1e-9);
-
- // Rotate CCW
- speeds = drive.DriveCartesianIK(0.0, 0.0, -1.0, 90.0);
- EXPECT_DOUBLE_EQ(-1.0, speeds.left);
- EXPECT_DOUBLE_EQ(-1.0, speeds.right);
- EXPECT_DOUBLE_EQ(-1.0, speeds.back);
-
- // Rotate CW
- speeds = drive.DriveCartesianIK(0.0, 0.0, 1.0, 90.0);
- EXPECT_DOUBLE_EQ(1.0, speeds.left);
- EXPECT_DOUBLE_EQ(1.0, speeds.right);
- EXPECT_DOUBLE_EQ(1.0, speeds.back);
-}
-
-TEST(KilloughDriveTest, Cartesian) {
- frc::MockMotorController left;
- frc::MockMotorController right;
- frc::MockMotorController back;
- frc::KilloughDrive drive{left, right, back};
- drive.SetDeadband(0.0);
-
- // Forward
- drive.DriveCartesian(1.0, 0.0, 0.0);
- EXPECT_DOUBLE_EQ(0.5, left.Get());
- EXPECT_DOUBLE_EQ(-0.5, right.Get());
- EXPECT_NEAR(0.0, back.Get(), 1e-9);
-
- // Left
- drive.DriveCartesian(0.0, -1.0, 0.0);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, left.Get());
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, right.Get());
- EXPECT_DOUBLE_EQ(1.0, back.Get());
-
- // Right
- drive.DriveCartesian(0.0, 1.0, 0.0);
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, left.Get());
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, right.Get());
- EXPECT_DOUBLE_EQ(-1.0, back.Get());
-
- // Rotate CCW
- drive.DriveCartesian(0.0, 0.0, -1.0);
- EXPECT_DOUBLE_EQ(-1.0, left.Get());
- EXPECT_DOUBLE_EQ(-1.0, right.Get());
- EXPECT_DOUBLE_EQ(-1.0, back.Get());
-
- // Rotate CW
- drive.DriveCartesian(0.0, 0.0, 1.0);
- EXPECT_DOUBLE_EQ(1.0, left.Get());
- EXPECT_DOUBLE_EQ(1.0, right.Get());
- EXPECT_DOUBLE_EQ(1.0, back.Get());
-}
-
-TEST(KilloughDriveTest, CartesianGyro90CW) {
- frc::MockMotorController left;
- frc::MockMotorController right;
- frc::MockMotorController back;
- frc::KilloughDrive drive{left, right, back};
- drive.SetDeadband(0.0);
-
- // Forward in global frame; left in robot frame
- drive.DriveCartesian(1.0, 0.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, left.Get());
- EXPECT_DOUBLE_EQ(-std::sqrt(3) / 2, right.Get());
- EXPECT_DOUBLE_EQ(1.0, back.Get());
-
- // Left in global frame; backward in robot frame
- drive.DriveCartesian(0.0, -1.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(-0.5, left.Get());
- EXPECT_NEAR(0.5, right.Get(), 1e-9);
- EXPECT_NEAR(0.0, back.Get(), 1e-9);
-
- // Right in global frame; forward in robot frame
- drive.DriveCartesian(0.0, 1.0, 0.0, 90.0);
- EXPECT_DOUBLE_EQ(0.5, left.Get());
- EXPECT_NEAR(-0.5, right.Get(), 1e-9);
- EXPECT_NEAR(0.0, back.Get(), 1e-9);
-
- // Rotate CCW
- drive.DriveCartesian(0.0, 0.0, -1.0, 90.0);
- EXPECT_DOUBLE_EQ(-1.0, left.Get());
- EXPECT_DOUBLE_EQ(-1.0, right.Get());
- EXPECT_DOUBLE_EQ(-1.0, back.Get());
-
- // Rotate CW
- drive.DriveCartesian(0.0, 0.0, 1.0, 90.0);
- EXPECT_DOUBLE_EQ(1.0, left.Get());
- EXPECT_DOUBLE_EQ(1.0, right.Get());
- EXPECT_DOUBLE_EQ(1.0, back.Get());
-}
-
-TEST(KilloughDriveTest, Polar) {
- frc::MockMotorController left;
- frc::MockMotorController right;
- frc::MockMotorController back;
- frc::KilloughDrive drive{left, right, back};
- drive.SetDeadband(0.0);
-
- // Forward
- drive.DrivePolar(1.0, 0.0, 0.0);
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, left.Get());
- EXPECT_DOUBLE_EQ(std::sqrt(3) / 2, right.Get());
- EXPECT_DOUBLE_EQ(-1.0, back.Get());
-
- // Left
- drive.DrivePolar(1.0, -90.0, 0.0);
- EXPECT_DOUBLE_EQ(-0.5, left.Get());
- EXPECT_DOUBLE_EQ(0.5, right.Get());
- EXPECT_NEAR(0.0, back.Get(), 1e-9);
-
- // Right
- drive.DrivePolar(1.0, 90.0, 0.0);
- EXPECT_DOUBLE_EQ(0.5, left.Get());
- EXPECT_NEAR(-0.5, right.Get(), 1e-9);
- EXPECT_NEAR(0.0, back.Get(), 1e-9);
-
- // Rotate CCW
- drive.DrivePolar(0.0, 0.0, -1.0);
- EXPECT_DOUBLE_EQ(-1.0, left.Get());
- EXPECT_DOUBLE_EQ(-1.0, right.Get());
- EXPECT_DOUBLE_EQ(-1.0, back.Get());
-
- // Rotate CW
- drive.DrivePolar(0.0, 0.0, 1.0);
- EXPECT_DOUBLE_EQ(1.0, left.Get());
- EXPECT_DOUBLE_EQ(1.0, right.Get());
- EXPECT_DOUBLE_EQ(1.0, back.Get());
-}
diff --git a/wpilibc/src/test/native/cpp/drive/MecanumDriveTest.cpp b/wpilibc/src/test/native/cpp/drive/MecanumDriveTest.cpp
index 2990848..de55462 100644
--- a/wpilibc/src/test/native/cpp/drive/MecanumDriveTest.cpp
+++ b/wpilibc/src/test/native/cpp/drive/MecanumDriveTest.cpp
@@ -2,9 +2,9 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
-#include "MockMotorController.h"
#include "frc/drive/MecanumDrive.h"
#include "gtest/gtest.h"
+#include "motorcontrol/MockMotorController.h"
TEST(MecanumDriveTest, CartesianIK) {
// Forward
@@ -45,35 +45,35 @@
TEST(MecanumDriveTest, CartesianIKGyro90CW) {
// Forward in global frame; left in robot frame
- auto speeds = frc::MecanumDrive::DriveCartesianIK(1.0, 0.0, 0.0, 90.0);
+ auto speeds = frc::MecanumDrive::DriveCartesianIK(1.0, 0.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, speeds.frontLeft);
EXPECT_DOUBLE_EQ(1.0, speeds.frontRight);
EXPECT_DOUBLE_EQ(1.0, speeds.rearLeft);
EXPECT_DOUBLE_EQ(-1.0, speeds.rearRight);
// Left in global frame; backward in robot frame
- speeds = frc::MecanumDrive::DriveCartesianIK(0.0, -1.0, 0.0, 90.0);
+ speeds = frc::MecanumDrive::DriveCartesianIK(0.0, -1.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, speeds.frontLeft);
EXPECT_DOUBLE_EQ(-1.0, speeds.frontRight);
EXPECT_DOUBLE_EQ(-1.0, speeds.rearLeft);
EXPECT_DOUBLE_EQ(-1.0, speeds.rearRight);
// Right in global frame; forward in robot frame
- speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 1.0, 0.0, 90.0);
+ speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 1.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(1.0, speeds.frontLeft);
EXPECT_DOUBLE_EQ(1.0, speeds.frontRight);
EXPECT_DOUBLE_EQ(1.0, speeds.rearLeft);
EXPECT_DOUBLE_EQ(1.0, speeds.rearRight);
// Rotate CCW
- speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 0.0, -1.0, 90.0);
+ speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 0.0, -1.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, speeds.frontLeft);
EXPECT_DOUBLE_EQ(1.0, speeds.frontRight);
EXPECT_DOUBLE_EQ(-1.0, speeds.rearLeft);
EXPECT_DOUBLE_EQ(1.0, speeds.rearRight);
// Rotate CW
- speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 0.0, 1.0, 90.0);
+ speeds = frc::MecanumDrive::DriveCartesianIK(0.0, 0.0, 1.0, 90_deg);
EXPECT_DOUBLE_EQ(1.0, speeds.frontLeft);
EXPECT_DOUBLE_EQ(-1.0, speeds.frontRight);
EXPECT_DOUBLE_EQ(1.0, speeds.rearLeft);
@@ -133,35 +133,35 @@
drive.SetDeadband(0.0);
// Forward in global frame; left in robot frame
- drive.DriveCartesian(1.0, 0.0, 0.0, 90.0);
+ drive.DriveCartesian(1.0, 0.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
EXPECT_DOUBLE_EQ(-1.0, rr.Get());
// Left in global frame; backward in robot frame
- drive.DriveCartesian(0.0, -1.0, 0.0, 90.0);
+ drive.DriveCartesian(0.0, -1.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, fl.Get());
EXPECT_DOUBLE_EQ(-1.0, fr.Get());
EXPECT_DOUBLE_EQ(-1.0, rl.Get());
EXPECT_DOUBLE_EQ(-1.0, rr.Get());
// Right in global frame; forward in robot frame
- drive.DriveCartesian(0.0, 1.0, 0.0, 90.0);
+ drive.DriveCartesian(0.0, 1.0, 0.0, 90_deg);
EXPECT_DOUBLE_EQ(1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
EXPECT_DOUBLE_EQ(1.0, rr.Get());
// Rotate CCW
- drive.DriveCartesian(0.0, 0.0, -1.0, 90.0);
+ drive.DriveCartesian(0.0, 0.0, -1.0, 90_deg);
EXPECT_DOUBLE_EQ(-1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(-1.0, rl.Get());
EXPECT_DOUBLE_EQ(1.0, rr.Get());
// Rotate CW
- drive.DriveCartesian(0.0, 0.0, 1.0, 90.0);
+ drive.DriveCartesian(0.0, 0.0, 1.0, 90_deg);
EXPECT_DOUBLE_EQ(1.0, fl.Get());
EXPECT_DOUBLE_EQ(-1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
@@ -177,35 +177,35 @@
drive.SetDeadband(0.0);
// Forward
- drive.DrivePolar(1.0, 0.0, 0.0);
+ drive.DrivePolar(1.0, 0_deg, 0.0);
EXPECT_DOUBLE_EQ(1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
EXPECT_DOUBLE_EQ(1.0, rr.Get());
// Left
- drive.DrivePolar(1.0, -90.0, 0.0);
+ drive.DrivePolar(1.0, -90_deg, 0.0);
EXPECT_DOUBLE_EQ(-1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
EXPECT_DOUBLE_EQ(-1.0, rr.Get());
// Right
- drive.DrivePolar(1.0, 90.0, 0.0);
+ drive.DrivePolar(1.0, 90_deg, 0.0);
EXPECT_DOUBLE_EQ(1.0, fl.Get());
EXPECT_DOUBLE_EQ(-1.0, fr.Get());
EXPECT_DOUBLE_EQ(-1.0, rl.Get());
EXPECT_DOUBLE_EQ(1.0, rr.Get());
// Rotate CCW
- drive.DrivePolar(0.0, 0.0, -1.0);
+ drive.DrivePolar(0.0, 0_deg, -1.0);
EXPECT_DOUBLE_EQ(-1.0, fl.Get());
EXPECT_DOUBLE_EQ(1.0, fr.Get());
EXPECT_DOUBLE_EQ(-1.0, rl.Get());
EXPECT_DOUBLE_EQ(1.0, rr.Get());
// Rotate CW
- drive.DrivePolar(0.0, 0.0, 1.0);
+ drive.DrivePolar(0.0, 0_deg, 1.0);
EXPECT_DOUBLE_EQ(1.0, fl.Get());
EXPECT_DOUBLE_EQ(-1.0, fr.Get());
EXPECT_DOUBLE_EQ(1.0, rl.Get());
diff --git a/wpilibc/src/test/native/cpp/event/NetworkBooleanEventTest.cpp b/wpilibc/src/test/native/cpp/event/NetworkBooleanEventTest.cpp
new file mode 100644
index 0000000..d2ac7c4
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/event/NetworkBooleanEventTest.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include <networktables/BooleanTopic.h>
+#include <networktables/NetworkTableInstance.h>
+
+#include "frc/event/EventLoop.h"
+#include "frc/event/NetworkBooleanEvent.h"
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+class NetworkBooleanEventTest : public ::testing::Test {
+ public:
+ NetworkBooleanEventTest() {
+ m_inst = nt::NetworkTableInstance::Create();
+ m_inst.StartLocal();
+ }
+
+ ~NetworkBooleanEventTest() override {
+ nt::NetworkTableInstance::Destroy(m_inst);
+ }
+
+ nt::NetworkTableInstance m_inst;
+};
+
+TEST_F(NetworkBooleanEventTest, Set) {
+ EventLoop loop;
+ int counter = 0;
+
+ auto pub = m_inst.GetTable("TestTable")->GetBooleanTopic("Test").Publish();
+
+ NetworkBooleanEvent(&loop, m_inst, "TestTable", "Test").IfHigh([&] {
+ ++counter;
+ });
+ pub.Set(false);
+ loop.Poll();
+ EXPECT_EQ(0, counter);
+ pub.Set(true);
+ loop.Poll();
+ EXPECT_EQ(1, counter);
+ pub.Set(false);
+ loop.Poll();
+ EXPECT_EQ(1, counter);
+}
diff --git a/wpilibc/src/test/native/cpp/main.cpp b/wpilibc/src/test/native/cpp/main.cpp
index 6aea19a..ba29975 100644
--- a/wpilibc/src/test/native/cpp/main.cpp
+++ b/wpilibc/src/test/native/cpp/main.cpp
@@ -6,9 +6,18 @@
#include "gtest/gtest.h"
+#ifndef __FRC_ROBORIO__
+namespace frc::impl {
+void ResetMotorSafety();
+}
+#endif
+
int main(int argc, char** argv) {
HAL_Initialize(500, 0);
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
+#ifndef __FRC_ROBORIO__
+ frc::impl::ResetMotorSafety();
+#endif
return ret;
}
diff --git a/wpilibc/src/test/native/cpp/MockMotorController.cpp b/wpilibc/src/test/native/cpp/motorcontrol/MockMotorController.cpp
similarity index 93%
rename from wpilibc/src/test/native/cpp/MockMotorController.cpp
rename to wpilibc/src/test/native/cpp/motorcontrol/MockMotorController.cpp
index 62fd54a..e0c9ee9 100644
--- a/wpilibc/src/test/native/cpp/MockMotorController.cpp
+++ b/wpilibc/src/test/native/cpp/motorcontrol/MockMotorController.cpp
@@ -2,7 +2,7 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
-#include "MockMotorController.h"
+#include "motorcontrol/MockMotorController.h"
using namespace frc;
diff --git a/wpilibc/src/test/native/cpp/motorcontrol/MotorControllerGroupTest.cpp b/wpilibc/src/test/native/cpp/motorcontrol/MotorControllerGroupTest.cpp
new file mode 100644
index 0000000..48cf700
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/motorcontrol/MotorControllerGroupTest.cpp
@@ -0,0 +1,125 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc/motorcontrol/MotorControllerGroup.h" // NOLINT(build/include_order)
+
+#include <memory>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "motorcontrol/MockMotorController.h"
+
+using namespace frc;
+
+enum MotorControllerGroupTestType { TEST_ONE, TEST_TWO, TEST_THREE };
+
+std::ostream& operator<<(std::ostream& os,
+ const MotorControllerGroupTestType& type) {
+ switch (type) {
+ case TEST_ONE:
+ os << "MotorControllerGroup with one motor controller";
+ break;
+ case TEST_TWO:
+ os << "MotorControllerGroup with two motor controllers";
+ break;
+ case TEST_THREE:
+ os << "MotorControllerGroup with three motor controllers";
+ break;
+ }
+
+ return os;
+}
+
+/**
+ * A fixture used for MotorControllerGroup testing.
+ */
+class MotorControllerGroupTest
+ : public testing::TestWithParam<MotorControllerGroupTestType> {
+ protected:
+ std::vector<MockMotorController> m_motorControllers;
+ std::unique_ptr<MotorControllerGroup> m_group;
+
+ void SetUp() override {
+ switch (GetParam()) {
+ case TEST_ONE: {
+ m_motorControllers.emplace_back();
+ m_group = std::make_unique<MotorControllerGroup>(m_motorControllers[0]);
+ break;
+ }
+
+ case TEST_TWO: {
+ m_motorControllers.emplace_back();
+ m_motorControllers.emplace_back();
+ m_group = std::make_unique<MotorControllerGroup>(m_motorControllers[0],
+ m_motorControllers[1]);
+ break;
+ }
+
+ case TEST_THREE: {
+ m_motorControllers.emplace_back();
+ m_motorControllers.emplace_back();
+ m_motorControllers.emplace_back();
+ m_group = std::make_unique<MotorControllerGroup>(m_motorControllers[0],
+ m_motorControllers[1],
+ m_motorControllers[2]);
+ break;
+ }
+ }
+ }
+};
+
+TEST_P(MotorControllerGroupTest, Set) {
+ m_group->Set(1.0);
+
+ for (auto& motorController : m_motorControllers) {
+ EXPECT_FLOAT_EQ(motorController.Get(), 1.0);
+ }
+}
+
+TEST_P(MotorControllerGroupTest, GetInverted) {
+ m_group->SetInverted(true);
+
+ EXPECT_TRUE(m_group->GetInverted());
+}
+
+TEST_P(MotorControllerGroupTest, SetInvertedDoesNotModifyMotorControllers) {
+ for (auto& motorController : m_motorControllers) {
+ motorController.SetInverted(false);
+ }
+ m_group->SetInverted(true);
+
+ for (auto& motorController : m_motorControllers) {
+ EXPECT_EQ(motorController.GetInverted(), false);
+ }
+}
+
+TEST_P(MotorControllerGroupTest, SetInvertedDoesInvert) {
+ m_group->SetInverted(true);
+ m_group->Set(1.0);
+
+ for (auto& motorController : m_motorControllers) {
+ EXPECT_FLOAT_EQ(motorController.Get(), -1.0);
+ }
+}
+
+TEST_P(MotorControllerGroupTest, Disable) {
+ m_group->Set(1.0);
+ m_group->Disable();
+
+ for (auto& motorController : m_motorControllers) {
+ EXPECT_FLOAT_EQ(motorController.Get(), 0.0);
+ }
+}
+
+TEST_P(MotorControllerGroupTest, StopMotor) {
+ m_group->Set(1.0);
+ m_group->StopMotor();
+
+ for (auto& motorController : m_motorControllers) {
+ EXPECT_FLOAT_EQ(motorController.Get(), 0.0);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(Tests, MotorControllerGroupTest,
+ testing::Values(TEST_ONE, TEST_TWO, TEST_THREE));
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp
index d370a2d..0b0c8df 100644
--- a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp
+++ b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp
@@ -31,8 +31,8 @@
.WithWidget("Text View")
.GetEntry();
- EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
- EXPECT_EQ("/Shuffleboard/Tab Title/List/Data", entry.GetName())
+ EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
+ EXPECT_EQ("/Shuffleboard/Tab Title/List/Data", entry->GetTopic().GetName())
<< "Entry path generated incorrectly";
}
@@ -48,9 +48,9 @@
.Add("Value", "string")
.GetEntry();
- EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
+ EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
- entry.GetName())
+ entry->GetTopic().GetName())
<< "Entry path generated incorrectly";
}
@@ -66,9 +66,9 @@
frc::SimpleWidget& widget = fourth.Add("Value", "string");
auto entry = widget.GetEntry();
- EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
+ EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
- entry.GetName())
+ entry->GetTopic().GetName())
<< "Entry path generated incorrectly";
}
@@ -97,12 +97,12 @@
// Note: we use the unsafe `GetBoolean()` method because if the value is NOT
// a boolean, or if it is not present, then something has clearly gone very,
// very wrong
- bool controllable = controllableEntry.GetValue()->GetBoolean();
+ bool controllable = controllableEntry.GetValue().GetBoolean();
// Sanity check
EXPECT_TRUE(controllable)
<< "The nested actuator widget should be enabled by default";
shuffleboardInst.DisableActuatorWidgets();
- controllable = controllableEntry.GetValue()->GetBoolean();
+ controllable = controllableEntry.GetValue().GetBoolean();
EXPECT_FALSE(controllable)
<< "The nested actuator widget should have been disabled";
}
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp
index c8449e5..d964639 100644
--- a/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp
+++ b/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp
@@ -33,7 +33,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/String");
m_shuffleboardInst.Update();
- EXPECT_EQ("foo", entry.GetValue()->GetString());
+ EXPECT_EQ("foo", entry.GetValue().GetString());
}
TEST_F(SuppliedValueWidgetTest, AddNumber) {
@@ -42,7 +42,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Num");
m_shuffleboardInst.Update();
- EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
+ EXPECT_FLOAT_EQ(1.0, entry.GetValue().GetDouble());
}
TEST_F(SuppliedValueWidgetTest, AddBoolean) {
@@ -51,7 +51,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Bool");
m_shuffleboardInst.Update();
- EXPECT_EQ(true, entry.GetValue()->GetBoolean());
+ EXPECT_EQ(true, entry.GetValue().GetBoolean());
}
TEST_F(SuppliedValueWidgetTest, AddStringArray) {
@@ -60,7 +60,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Strings");
m_shuffleboardInst.Update();
- auto actual = entry.GetValue()->GetStringArray();
+ auto actual = entry.GetValue().GetStringArray();
EXPECT_EQ(strings.size(), actual.size());
for (size_t i = 0; i < strings.size(); i++) {
@@ -74,7 +74,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Numbers");
m_shuffleboardInst.Update();
- auto actual = entry.GetValue()->GetDoubleArray();
+ auto actual = entry.GetValue().GetDoubleArray();
EXPECT_EQ(nums.size(), actual.size());
for (size_t i = 0; i < nums.size(); i++) {
@@ -88,7 +88,7 @@
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Booleans");
m_shuffleboardInst.Update();
- auto actual = entry.GetValue()->GetBooleanArray();
+ auto actual = entry.GetValue().GetBooleanArray();
EXPECT_EQ(bools.size(), actual.size());
for (size_t i = 0; i < bools.size(); i++) {
@@ -97,11 +97,11 @@
}
TEST_F(SuppliedValueWidgetTest, AddRaw) {
- std::string_view bytes = "\1\2\3";
+ std::vector<uint8_t> bytes = {1, 2, 3};
m_tab->AddRaw("Raw", [&bytes]() { return bytes; });
auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Raw");
m_shuffleboardInst.Update();
- auto actual = entry.GetValue()->GetRaw();
- EXPECT_EQ(bytes, actual);
+ auto actual = entry.GetValue().GetRaw();
+ EXPECT_EQ(bytes, std::vector<uint8_t>(actual.begin(), actual.end()));
}
diff --git a/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp
index ad4452e..e450477 100644
--- a/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp
@@ -4,6 +4,8 @@
#include "frc/simulation/AddressableLEDSim.h" // NOLINT(build/include_order)
+#include <array>
+
#include <hal/HAL.h>
#include "callback_helpers/TestCallbackHelpers.h"
diff --git a/wpilibc/src/test/native/cpp/simulation/AnalogEncoderSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AnalogEncoderSimTest.cpp
index 375e21a..0a1b687 100644
--- a/wpilibc/src/test/native/cpp/simulation/AnalogEncoderSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/AnalogEncoderSimTest.cpp
@@ -2,9 +2,10 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
+#include <numbers>
+
#include <hal/HAL.h>
#include <units/math.h>
-#include <wpi/numbers>
#include "frc/AnalogEncoder.h"
#include "frc/AnalogInput.h"
@@ -22,6 +23,6 @@
encoderSim.SetPosition(180_deg);
EXPECT_NEAR(encoder.Get().value(), 0.5, 1E-8);
EXPECT_NEAR(encoderSim.GetTurns().value(), 0.5, 1E-8);
- EXPECT_NEAR(encoderSim.GetPosition().Radians().value(), wpi::numbers::pi,
+ EXPECT_NEAR(encoderSim.GetPosition().Radians().value(), std::numbers::pi,
1E-8);
}
diff --git a/wpilibc/src/test/native/cpp/simulation/DifferentialDrivetrainSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DifferentialDrivetrainSimTest.cpp
index 8ccfcd6..6edfde0 100644
--- a/wpilibc/src/test/native/cpp/simulation/DifferentialDrivetrainSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/DifferentialDrivetrainSimTest.cpp
@@ -30,17 +30,17 @@
frc::LinearPlantInversionFeedforward feedforward{plant, 20_ms};
frc::RamseteController ramsete;
- feedforward.Reset(Eigen::Vector<double, 2>{0.0, 0.0});
+ feedforward.Reset(frc::Vectord<2>{0.0, 0.0});
// Ground truth.
- Eigen::Vector<double, 7> groundTruthX = Eigen::Vector<double, 7>::Zero();
+ frc::Vectord<7> groundTruthX = frc::Vectord<7>::Zero();
frc::TrajectoryConfig config{1_mps, 1_mps_sq};
config.AddConstraint(
frc::DifferentialDriveKinematicsConstraint(kinematics, 1_mps));
auto trajectory = frc::TrajectoryGenerator::GenerateTrajectory(
- frc::Pose2d(), {}, frc::Pose2d(2_m, 2_m, 0_rad), config);
+ frc::Pose2d{}, {}, frc::Pose2d{2_m, 2_m, 0_rad}, config);
for (auto t = 0_s; t < trajectory.TotalTime(); t += 20_ms) {
auto state = trajectory.Sample(t);
@@ -48,15 +48,15 @@
auto [l, r] = kinematics.ToWheelSpeeds(ramseteOut);
auto voltages =
- feedforward.Calculate(Eigen::Vector<double, 2>{l.value(), r.value()});
+ feedforward.Calculate(frc::Vectord<2>{l.value(), r.value()});
// Sim periodic code.
- sim.SetInputs(units::volt_t(voltages(0, 0)), units::volt_t(voltages(1, 0)));
+ sim.SetInputs(units::volt_t{voltages(0, 0)}, units::volt_t{voltages(1, 0)});
sim.Update(20_ms);
// Update ground truth.
groundTruthX = frc::RK4(
- [&sim](const auto& x, const auto& u) -> Eigen::Vector<double, 7> {
+ [&sim](const auto& x, const auto& u) -> frc::Vectord<7> {
return sim.Dynamics(x, u);
},
groundTruthX, voltages, 20_ms);
diff --git a/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp
index d01ca27..6aa31c6 100644
--- a/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp
@@ -132,6 +132,7 @@
// B1
allianceStation = HAL_AllianceStationID_kBlue1;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance());
EXPECT_EQ(1, DriverStation::GetLocation());
@@ -141,6 +142,7 @@
// B2
allianceStation = HAL_AllianceStationID_kBlue2;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance());
EXPECT_EQ(2, DriverStation::GetLocation());
@@ -150,6 +152,7 @@
// B3
allianceStation = HAL_AllianceStationID_kBlue3;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance());
EXPECT_EQ(3, DriverStation::GetLocation());
@@ -159,6 +162,7 @@
// R1
allianceStation = HAL_AllianceStationID_kRed1;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance());
EXPECT_EQ(1, DriverStation::GetLocation());
@@ -168,6 +172,7 @@
// R2
allianceStation = HAL_AllianceStationID_kRed2;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance());
EXPECT_EQ(2, DriverStation::GetLocation());
@@ -177,6 +182,7 @@
// R3
allianceStation = HAL_AllianceStationID_kRed3;
DriverStationSim::SetAllianceStationId(allianceStation);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId());
EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance());
EXPECT_EQ(3, DriverStation::GetLocation());
@@ -211,6 +217,7 @@
false);
constexpr double kTestTime = 19.174;
DriverStationSim::SetMatchTime(kTestTime);
+ frc::sim::DriverStationSim::NotifyNewData();
EXPECT_EQ(kTestTime, DriverStationSim::GetMatchTime());
EXPECT_EQ(kTestTime, DriverStation::GetMatchTime());
EXPECT_TRUE(callback.WasTriggered());
diff --git a/wpilibc/src/test/native/cpp/simulation/ElevatorSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/ElevatorSimTest.cpp
index 03022ab..3c647e6 100644
--- a/wpilibc/src/test/native/cpp/simulation/ElevatorSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/ElevatorSimTest.cpp
@@ -2,6 +2,7 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
+#include <units/math.h>
#include <units/time.h>
#include "frc/Encoder.h"
@@ -15,10 +16,12 @@
#include "frc/system/plant/LinearSystemId.h"
#include "gtest/gtest.h"
+#define EXPECT_NEAR_UNITS(val1, val2, eps) \
+ EXPECT_LE(units::math::abs(val1 - val2), eps)
+
TEST(ElevatorSimTest, StateSpaceSim) {
- frc::sim::ElevatorSim sim(frc::DCMotor::Vex775Pro(4), 14.67, 8_kg,
- units::meter_t(0.75 * 25.4 / 1000.0), 0_m, 3_m,
- {0.01});
+ frc::sim::ElevatorSim sim(frc::DCMotor::Vex775Pro(4), 14.67, 8_kg, 0.75_in,
+ 0_m, 3_m, true, {0.01});
frc2::PIDController controller(10, 0.0, 0.0);
frc::PWMVictorSPX motor(0);
@@ -30,8 +33,7 @@
auto nextVoltage = controller.Calculate(encoderSim.GetDistance());
motor.Set(nextVoltage / frc::RobotController::GetInputVoltage());
- Eigen::Vector<double, 1> u{motor.Get() *
- frc::RobotController::GetInputVoltage()};
+ frc::Vectord<1> u{motor.Get() * frc::RobotController::GetInputVoltage()};
sim.SetInput(u);
sim.Update(20_ms);
@@ -43,11 +45,10 @@
}
TEST(ElevatorSimTest, MinMax) {
- frc::sim::ElevatorSim sim(frc::DCMotor::Vex775Pro(4), 14.67, 8_kg,
- units::meter_t(0.75 * 25.4 / 1000.0), 0_m, 1_m,
- {0.01});
+ frc::sim::ElevatorSim sim(frc::DCMotor::Vex775Pro(4), 14.67, 8_kg, 0.75_in,
+ 0_m, 1_m, true, {0.01});
for (size_t i = 0; i < 100; ++i) {
- sim.SetInput(Eigen::Vector<double, 1>{0.0});
+ sim.SetInput(frc::Vectord<1>{0.0});
sim.Update(20_ms);
auto height = sim.GetPosition();
@@ -55,7 +56,7 @@
}
for (size_t i = 0; i < 100; ++i) {
- sim.SetInput(Eigen::Vector<double, 1>{12.0});
+ sim.SetInput(frc::Vectord<1>{12.0});
sim.Update(20_ms);
auto height = sim.GetPosition();
@@ -64,26 +65,19 @@
}
TEST(ElevatorSimTest, Stability) {
- static constexpr double kElevatorGearing = 100.0;
- static constexpr units::meter_t kElevatorDrumRadius = 0.5_in;
- static constexpr units::kilogram_t kCarriageMass = 4.0_kg;
- frc::DCMotor m_elevatorGearbox = frc::DCMotor::Vex775Pro(4);
+ frc::sim::ElevatorSim sim{
+ frc::DCMotor::Vex775Pro(4), 100, 4_kg, 0.5_in, 0_m, 10_m, true};
- frc::LinearSystem<2, 1, 1> system = frc::LinearSystemId::ElevatorSystem(
- m_elevatorGearbox, kCarriageMass, kElevatorDrumRadius, kElevatorGearing);
-
- Eigen::Vector<double, 2> x0{0.0, 0.0};
- Eigen::Vector<double, 1> u0{12.0};
-
- Eigen::Vector<double, 2> x1{0.0, 0.0};
- for (size_t i = 0; i < 50; i++) {
- x1 = frc::RKDP(
- [&](const Eigen::Vector<double, 2>& x,
- const Eigen::Vector<double, 1>& u) -> Eigen::Vector<double, 2> {
- return system.A() * x + system.B() * u;
- },
- x1, u0, 0.020_s);
+ sim.SetState(frc::Vectord<2>{0.0, 0.0});
+ sim.SetInput(frc::Vectord<1>{12.0});
+ for (int i = 0; i < 50; ++i) {
+ sim.Update(20_ms);
}
- EXPECT_NEAR(x1(0), system.CalculateX(x0, u0, 1_s)(0), 0.1);
+ frc::LinearSystem<2, 1, 1> system = frc::LinearSystemId::ElevatorSystem(
+ frc::DCMotor::Vex775Pro(4), 4_kg, 0.5_in, 100);
+ EXPECT_NEAR_UNITS(
+ units::meter_t{system.CalculateX(frc::Vectord<2>{0.0, 0.0},
+ frc::Vectord<1>{12.0}, 20_ms * 50)(0)},
+ sim.GetPosition(), 1_cm);
}
diff --git a/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp
index be13ca5..7722ccc 100644
--- a/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp
@@ -91,7 +91,9 @@
auto cb = sim.RegisterPeriodCallback(callback.GetCallback(), false);
sim.SetPeriod(123.456);
EXPECT_EQ(123.456, sim.GetPeriod());
+ WPI_IGNORE_DEPRECATED
EXPECT_EQ(123.456, encoder.GetPeriod().value());
+ WPI_UNIGNORE_DEPRECATED
EXPECT_EQ(kDefaultDistancePerPulse / 123.456, encoder.GetRate());
EXPECT_TRUE(callback.WasTriggered());
@@ -110,7 +112,9 @@
DoubleCallback callback;
auto cb = sim.RegisterMaxPeriodCallback(callback.GetCallback(), false);
+ WPI_IGNORE_DEPRECATED
encoder.SetMaxPeriod(units::second_t{123.456});
+ WPI_UNIGNORE_DEPRECATED
EXPECT_EQ(123.456, sim.GetMaxPeriod());
EXPECT_TRUE(callback.WasTriggered());
diff --git a/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp
index c6e93d4..98d4620 100644
--- a/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp
@@ -207,4 +207,41 @@
EXPECT_EQ(kTestFaults, RobotController::GetFaultCount3V3());
}
+TEST(RoboRioSimTest, SetSerialNumber) {
+ const std::string kSerialNum = "Hello";
+
+ RoboRioSim::ResetData();
+
+ RoboRioSim::SetSerialNumber(kSerialNum);
+ EXPECT_EQ(kSerialNum, RoboRioSim::GetSerialNumber());
+ EXPECT_EQ(kSerialNum, RobotController::GetSerialNumber());
+
+ const std::string kSerialNumberOverflow = "SerialNumber";
+ const std::string kSerialNumberTruncated = kSerialNumberOverflow.substr(0, 8);
+
+ RoboRioSim::SetSerialNumber(kSerialNumberOverflow);
+ EXPECT_EQ(kSerialNumberTruncated, RoboRioSim::GetSerialNumber());
+ EXPECT_EQ(kSerialNumberTruncated, RobotController::GetSerialNumber());
+}
+
+TEST(RoboRioSimTest, SetComments) {
+ const std::string kComments =
+ "Hello! These are comments in the roboRIO web interface!";
+
+ RoboRioSim::ResetData();
+
+ RoboRioSim::SetComments(kComments);
+ EXPECT_EQ(kComments, RoboRioSim::GetComments());
+ EXPECT_EQ(kComments, RobotController::GetComments());
+
+ const std::string kCommentsOverflow =
+ "Hello! These are comments in the roboRIO web interface! This comment "
+ "exceeds 64 characters!";
+ const std::string kCommentsTruncated = kCommentsOverflow.substr(0, 64);
+
+ RoboRioSim::SetComments(kCommentsOverflow);
+ EXPECT_EQ(kCommentsTruncated, RoboRioSim::GetComments());
+ EXPECT_EQ(kCommentsTruncated, RobotController::GetComments());
+}
+
} // namespace frc::sim
diff --git a/wpilibc/src/test/native/cpp/simulation/SingleJointedArmSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/SingleJointedArmSimTest.cpp
index 03df12b..2e4c793 100644
--- a/wpilibc/src/test/native/cpp/simulation/SingleJointedArmSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/SingleJointedArmSimTest.cpp
@@ -2,7 +2,7 @@
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
-#include <wpi/numbers>
+#include <numbers>
#include "frc/simulation/SingleJointedArmSim.h"
#include "gtest/gtest.h"
@@ -10,13 +10,13 @@
TEST(SingleJointedArmTest, Disabled) {
frc::sim::SingleJointedArmSim sim(frc::DCMotor::Vex775Pro(2), 100, 3_kg_sq_m,
9.5_in, -180_deg, 0_deg, 10_lb, true);
- sim.SetState(Eigen::Vector<double, 2>{0.0, 0.0});
+ sim.SetState(frc::Vectord<2>{0.0, 0.0});
for (size_t i = 0; i < 12 / 0.02; ++i) {
- sim.SetInput(Eigen::Vector<double, 1>{0.0});
+ sim.SetInput(frc::Vectord<1>{0.0});
sim.Update(20_ms);
}
// The arm should swing down.
- EXPECT_NEAR(sim.GetAngle().value(), -wpi::numbers::pi / 2, 0.01);
+ EXPECT_NEAR(sim.GetAngle().value(), -std::numbers::pi / 2, 0.01);
}
diff --git a/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp
index 23af83d..7456adb 100644
--- a/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp
+++ b/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp
@@ -40,14 +40,14 @@
for (int i = 0; i < 100; i++) {
// RobotPeriodic runs first
auto voltageOut = controller.Calculate(encoder.GetRate(), 200.0);
- motor.SetVoltage(units::volt_t(voltageOut) +
+ motor.SetVoltage(units::volt_t{voltageOut} +
feedforward.Calculate(200_rad_per_s));
// Then, SimulationPeriodic runs
frc::sim::RoboRioSim::SetVInVoltage(
frc::sim::BatterySim::Calculate({sim.GetCurrentDraw()}));
- sim.SetInput(Eigen::Vector<double, 1>{
- motor.Get() * frc::RobotController::GetInputVoltage()});
+ sim.SetInput(
+ frc::Vectord<1>{motor.Get() * frc::RobotController::GetInputVoltage()});
sim.Update(20_ms);
encoderSim.SetRate(sim.GetAngularVelocity().value());
}
diff --git a/wpilibc/src/test/native/include/MockMotorController.h b/wpilibc/src/test/native/include/motorcontrol/MockMotorController.h
similarity index 100%
rename from wpilibc/src/test/native/include/MockMotorController.h
rename to wpilibc/src/test/native/include/motorcontrol/MockMotorController.h