pose.Translation().X() and pose.Translation.Y() are common operations,
so shortening them to pose.X() and pose.Y() would be convenient.
Java uses the getX() convention so that is used instead of X() for Java.
Also move some things in HAL for consistency.
WAS:
C++:
- C APIs: #include "mockdata/AccelerometerData.h"
- User side class: #include "simulation/AccelerometerSim.h"
Java:
- JNI APIs: hal.sim.mockdata.AccelerometerData (and a few classes in hal.sim)
- User side classes: hal.sim.AccelerometerSim
IS:
C++:
- C APIs: #include "hal/simulation/AccelerometerData.h"
- C++ class: #include "frc/simulation/AccelerometerSim.h"
Java:
- JNI APIs: hal.simulation.AccelerometerData
- User side class: wpilibj.simulation.AccelerometerSim
Previously, it could take the long way around. This recomputes the
profile goal with the shortest error, thus taking the shortest path.
Also removed the setpoint clamping from PIDController::SetSetpoint()
because it's unnecessary to make PIDController behave correctly for
a modular arithmetic input, and it breaks the setpoint calculation in
ProfiledPIDController otherwise.
Fixes#2277.
This is useful for undoing transformations. One application my FRC team
found was converting perspective n-point data from a "camera to target"
coordinate frame transformation to a "target to camera" coordinate frame
transformation.
This PR changes the spline parameterizer to use an explicit stack instead of recursion. This is motivated by the fact that splines with adjacent waypoints with approximately opposite headings will never parameterize. In this case the parameterizer subdivides these malformed splines fine for a while, and then gets stuck parameterizing infinitely on some interval. In the recursive approach, this would lead to a stack overflow. We could implement a recursion depth counter (this is what my team did on our similar trajectory code last season), but it's hard to choose a good number for max depth because the initial amount of stack used varies based on how the user calls Parameterize.
A good solution for this is converting the recursion to an "explicit stack," which basically simulates recursion, but allows us to have a much larger maximum stack size. Because we avoid the stack overflow, we can instead throws a more informative MalformedSplineException. If the user is using the TrajectoryGenerator instead of the SplineParameterizer directly then the TrajectoryGenerator will go ahead and catch the exception, return a harmless empty trajectory, and report and error to the driver station.
This is extremely useful for implementing various "ramping" functions
(such as voltage ramps, setpoint ramps, etc). Usage is straightforward;
it behaves like all of our other filter classes. C++ version is unit-safe.
It doesn't make sense to continue to provide a less accurate method of performing odometry
when a more accurate method using distances exists.
This also removes the need to pass DifferentialDriveKinematics to the constructor.
This kind of filter is extremely useful for signals that are susceptible to sudden
outliers - ultrasonics, 1-D LIDAR, and results from vision processing are all
good use-cases.
This also modifies the existing ultrasonic examples accordingly.
The odometry classes previously took in the robot angle as an argument, meaning that users had to take care of offsetting the gyro themselves to accurately report the robot angle. This change will make it so that users will not have to worry about resetting gyros and adding offsets themselves, as this will be handled by the odometry classes.
The current index would be set to -1 by the execute method of ParallelRaceGroup,
and then an index out of bounds exception would be thrown by the end() method of
SequentialCommandGroup. This change bound checks the current command index as well
as only calls end at the end of parallel race group rather than during execute.
This removes the name and subsystem from individual objects, and instead
puts this data into a new singleton class, SendableRegistry. Much of
LiveWindow has been refactored into SendableRegistry.
In C++, a new CRTP helper class, SendableHelper, has been added to provide
move and destruction functionality.
Shims for GetName, SetName, GetSubsystem, and SetSubsystem have been added
to Command and Subsystem (both old and new), and also to SendableHelper to
prevent code breakage.
This deprecates SendableBase in preparation for future removal.
If users are attempting to use the output range to limit the controller
action, they should use ProfiledPIDController instead. If they actually
intended to clamp the output, they should use std::clamp().
It breaks the unit system badly; the tolerance member variable has
different units depending on percent vs absolute. Absolute tolerance is
a lot more natural than percent tolerance anyway.
This is the C++ version of #1682.
The old command framework is still available, but will be deprecated.
Due to name conflicts, the new framework is in the frc2 namespace.
Eventually (after the old command framework is removed in a future year)
it will be moved into the main frc namespace.
Add unit-taking overloads to the following classes:
- IterativeRobotBase
- LinearFilter
- Notifier
- TimedRobot
- Timer (HasPeriodPassed only)
- frc2::PIDController
The corresponding non-units-taking functions have been deprecated.
The return value of TimedRobot::GetPeriod() was updated.
This is a breaking change, users should use to<double> to get the value in seconds.
Other return values, e.g. Timer::Get(), have NOT been updated due to much wider use.
Teams that wish to use it asynchronously may still do so - they simply need to handle the thread safety themselves (it is not that difficult, and can be done more cleanly in the calling code anyway).
These classes introduce ways to represent poses and provide easy ways to transform, rotate, and translate poses across 2d space. This classes will be especially useful for a planned odometry and kinematics suite.
Furthermore, these classes can also be used to simply represent waypoints on a field, do superstructure motion planning, etc.
Originally, PIDController used PIDSource with its "PIDSourceType" to
determine whether a class should return position or velocity to the
controller. However, the supported languages have changed a lot over 10
years and now support lambdas. Instead of using PIDSource and PIDOutput,
users can pass in doubles to the Calculate() function synchronously.
This makes the controller much more flexible for team's needs as they no
longer have to make a separate PIDSource-inheriting class just to
provide a custom input.
The built-in feedforward was removed. Since PIDController is synchronous
now, they can add their own feedforward on top of what Calculate()
returns.
To facilitate running the controller asynchronously, there is a
PIDControllerRunner class that handles that. By separating the loop from
the control law, PIDController can now be composed with others and be
used to control a drivetrain (a multiple input, multiple output system
that requires summing the results from two controllers) much easier.
Also, motion profiling can be used to set the reference over time.
All the classes related to the old PIDController are now deprecated. The
new classes are in an experimental namespace to avoid name conflicts.
While this is a large change, I think it is a necessary one for growth.
The old PIDController design was created in a time when languages only
supported OOP, and we have more tools at our disposal now to solve
problems. This more versatile implementation can be used in more places
like as a replacement for Pathfinder's "EncoderFollower" class.
There has been hesitation to add lambda support to WPILib for a while
now out of concerns for requiring teams to learn more features of C++ or
Java. In my opinion, this change makes PIDController easier to use, not
harder. The concept of a function is a building block of OOP and should
be learned before classes. The ability to store functions as first-class
objects and invoke them just like variables is rather natural.
Note that PID constants for the new controller will be different from
the old one. The original controller didn't take the discretization
period into account. To fix this, teams should just have to divide their
Ki gain by 0.05 and multiply their Kd gain by 0.05 where 0.05 is the
original default period.