BunyipsLib releases are made whenever a snapshot of the repository is taken following new features/patches that are confirmed to work.
All archived (removed) BunyipsLib code can be found here.
Preselection hooks and parsing improvements.
- Moved the
@Hookannotation from the root BunyipsLib package to theannotationspackage
ActionTasknow more intelligently parses built inActiontypes to convert them to BunyipsLib equivalents- This includes the
SleepAction,InstantAction, andNullAction
- This includes the
- Some internal data structures replaced with data classes for improved readability
- Add missing
Refclass for MeepMeep - Improve catching
InterruptedExceptionforThread.sleepcalls in embedded hooks
- New
@PreselectBehaviourannotation for Autonmous OpModes- Allows TeleOp preselections to be automatically initialised and/or started at the end of the auto period
- Serves as an extension to the
preselectTeleOpparameter in@Autonomous
Geometry mapping and Hardware Tester improvements.
- Remove
StartingConfiguration.Positioninvert()method in favour ofmirror()androtate()which perform functionality akin to the Mirrored and Symmetric pose maps
- Improve the Hardware Tester
- Move default non-interactable information to the bottom to speed up power access
- Unwrap menu items with only 1 mapping to reduce redundant navigation
- Update
MirroredPoseMapdocs - Use default two decimal place rounding for Unit
toString, adjustable with the argument totoShortString()
- Fix missing API docs for some new methods
- Add
Geometry.maputil to allow mappingPose2dinstances with aPoseMapeasily
API maturations.
BunyipsOpModeonInitandAutonomousBunyipsOpModeonInitialiseare now abstract- Previously, these methods were optional overrides between BunyipsLib v7.0.0-8.0.0
- However, this choice to use overrides increased footguns as initialisation code is required in the operation of
ABOM and to use
Schedulerbinds - The original removal of the mandatory abstraction was for AutoInit instances but received limited use and hence has been returned
- Improves programmer workflow as manual implementation of the init method is not needed anymore/is expected for an init->loop standard OpMode lifecycle
TaskGroupimplementations have removedgetGroupedTasksin favour of the public finaltasksfield- Exposes a direct list of tasks rather than copying a new group on calling the getter
- Remove
Voltageutility class- Removes conflict with the unit
Voltageclass - Migrated the functionality of the old
VoltagetoVoltage.getCurrentRobotVoltage()
- Removes conflict with the unit
AutonomousBunyipsOpModenow callsreset()on Task instances before execution- This is to allow tasks to be reused as they are finished
- May break some niche uses that rely on the old behaviour of never resetting
MecanumDriveandTankDriveinstances no longer need theVoltageSensormapping argument- It is now auto-inferred from the OpMode rather than needing to be passed in manually
- The legacy constructor remains for old code, but new references do not include the mapping argument
AutonomousBunyipsOpModenow attempts to unwrapSequentialTaskGroupinstances added- ABOM now individually adds the contents of a sequential group, if possible, as individual tasks in the run queue
- This change does not affect functionality, only visual effects with the running queue in telemetry
- Various language level upgrades
ServoExnow attempts more intelligently to initialise servos on first call- Previously, servos would spam
setPwmEnable()which could fail and spam the logs with errors
- Previously, servos would spam
UserSelectionconstructor overloads forcallback- Mandatory callback is now optional and no-ops by default
- Use static constants for ABOM's user selection thread name
- Fix
ForwardPushTestnot resetting ticks when tuning a goBILDA Pinpoint Computer - Patch
OTOSLocalizerfrom failing to initialise on init- This was caused by a serialisation bug in the parameters object
- Fix
Threads.isRunningfrom being inverted when using theObjectoverload - Update
WaitTaskandMessageTaskto use correct timeouts when updated - Update inconcise labelling of X and Y encoders in the Pinpoint Hardware Tester
- Perform 1st decimal place rounding to Pinpoint values in Hardware Tester to allow the operator to read the outputs coherently
- Perform rounding for
LocalizationTestpose velocity that was not implemented RefCell.empty()now infers type properly
- Add automated telemetry to the
Actuatorsubsystem- This was forgotten to be implemented previously akin to its
HoldableActuatorcounterpart
- This was forgotten to be implemented previously akin to its
- Added
UserSelectionasAsyncTask()method to convert the runtime of the user selection as a task- This task will execute as a new thread on the initialisation of the task and end otherwise
- Allows common TeleOp user selections to not require a lot of boilerplate for waiting OpModes and instead call
setInitTask(selection.asAsyncTask())
MeepMeepRunnernow can construct implicit start pose trajectories that properly transform over thePoseMapthroughuseImplicitStartPose()- Allows the next constructor call to double-map properly when using a pose mapping, ensuring that the start pose is interpreted as absolute
- Added the
BlinkinLightssetPatterntask, which is syntactic sugar forsetPatternFor(INFINITE_TIMEOUT, ...) ActionTasknow exposes the wrapped action through the public finalparentTaskfield- Added the
StartingConfiguration.Position.save()utility method to save the position to memory Motornow allows a directVoltageSensorto use forsetNominalVoltageSensor- Add
loopingtoTaskto alias toloopto avoid clashes in theOpModeloopmethod with static imports
Logging robustness and API refurbishing.
- Task and Scheduler overhaul
- Removal of several task methods, simplifying the API
- All task behaviours now match WPILib expected behaviour with a few exceptions
- For example,
finishNow()has been replaced withfinish()andfinish()does not wait for the polling loop to call the finisher methods - The polling loop in
run()handles the isFinished condition,poll()has been removed and implementations can idempotently pollisFinished() - Task childing is also more easily accomplished with the new
sync(Task)method - Task
deltaTimerenamed toelapsedTimeto avoid confusion - Task
isRunningrenamed toisActivefor similar reason ensureInit()method to pre-initalise tasks matching WPILib scheduling- Improved task and scheduler robustness by unit testing
- Reimplementation of Scheduler as a static singleton
- The
Schedulernow follows the WPILib trigger bindings such asonTrue,whileTrue, etc.- Bindings are now also made using
Scheduler.Triggerinstances, with gamepad utilities aliased onScheduler.gamepad1().button(...)or.axisGreaterThan(...)etc. andControllerinstance aliases
- Bindings are now also made using
- Review the new API docs and wiki for more information
- Removed
CommandBasedBunyipsOpMode- New implementations must migrate to a
BunyipsOpModeand callScheduler.update()in the active loop. Bindings occur inonInit().
- New implementations must migrate to a
- Removed
Tasksutility class, useScheduler
- Removal of several task methods, simplifying the API
- Update to SDK v11.0
- Other dependencies include MeepMeep v0.1.7, Sloth remains on the old version
- Note: FtcDashboard remains out of date and hence the field image is outdated, see this class for a workaround using a resource image. This is not included in the library as it is a workaround.
- The wiki has been updated accordingly with these versions
- Other dependencies include MeepMeep v0.1.7, Sloth remains on the old version
- MeepMeepRunner has been updated to update the current game
- Git ignored copies of this file will need to run
git update-index --no-skip-worktree MeepMeepRunner.java - The current game has been lifted to the MeepMeepInternal class, so no further changes should occur to this file
- Git ignored copies of this file will need to run
- Reimplemented the Feedforward gains system
- The previous implementation of feedforward attempting to mirror WPILib had fatal flaws in assuming the use of system state
- The new feedforward gains system now comes with many smaller, separate feedforward gains **applied to the setpoint ** rather than the state
- The wiki has been updated with information in the IO section
- This new implementation makes better use of the composition API, greatly increasing flexibility
- Reimplemented the Kalman filter
- Now uses an appropriate dynamic gain rather than pre-computing to achieve higher accuracy akin to the conceptual filter
PinpointLocalizer.Paramsno longer extendsTwoWheelLocalizer.Params- Reduce footguns and allow the builder to function normally
- Fix inaccuracies with
Motorgain scheduling- Gain scheduling always assumed that it would be based on the current position of the motor
- This makes gain scheduling not useful for velocity controllers
- The new implementation now renames
atPositiontoatStateand instead assumes velocity for RUE gains, and position as before for RTP gains
- Ported missing MeepMeep internal shims
BunyipsSubsystem.delegateis now a vararg method- Simplified the
Threadsresult API, supportinggetResult()to handle checked exceptions AprilTagRelocalizingAccumulatornow accepts the closest pose to the camera rather than an average- Taking an average was not correct behaviour to do and may have been the cause of previous bugs with the system
- Update
Accumulatorinstances to use the pose convention for AdvantageScope MecanumDriveinstances now record to theMECANUM_COMMANDchannel every loop, not just in a trajectory- Remove some unnecessary uses of
@Nullable ActionTasknow recursively unwrapsRaceActioninstances toRaceTaskGroup- Condition now uses self-typing to allow for extension classes that compose
HoldableActuatornow has more flexibility in tasks and does not mandate the default tasks for power capturingBunyipsSubsysteminstances no longer spam Logcat when a task change is ignoredDualTelemetry.smartAddnow uses a more sensible OpMode runtime caption as a fallback- New
ConditionalTaskconstructors for Runnable names and improved naming BunyipsSubsysteminstances will now no longer accept default tasks that havedisableSubsystemAttachmentenabled
- Fix the
PinpointLocalizer- No longer crashes on initialisation
- Params object can now be constructed without casting
- Directions are applied properly instead of on the same wheel
- Millimeter conversion adapted to provide accurate odometry readings
- Refine various inaccurate or outdated docs and wiki information
- Fix erroneous double-rotation of
AprilTagRelocalizingAccumulatorposes - The
MecanumDrivepose holding setting is now only applied for autonomous OpModes- Conflicts with non-command-based applications where the default task should be Idle
- It also does not make sense to use in TeleOp and instead a
HolonomicVectorDriveTaskis preferred
- Fix recursive error in
Motorif a RTP or RUE controller is not specified - Velocity controllers now get appropriately updated in Motor when the power is 0
- WaitTasks no longer call
onInterruptwhen they finish naturally ServoExinstances now callsetPwmEnableonsetPositioncalls- Fixes the problem of servos not responding on init as their cached position has not reactivated the PWM
- The default IdleTask on subsystems now depends on the subsystem
- Additional DynamicTask fixes for dashboard packets
- Packets can now be accessed by the task lambdas
- Default use of the
FlightRecorderhas been vastly improved across the library- All
Localizerinstances now report more information on status and state- This includes the Pinpoint recording the reported status and raw inputs in the event of a failure
- Reformatted naming scheme for specific logging events
- All integrated
BunyipsSubsysteminstances now opt to supplying aLogSchema- This schema is attached internally via
attachLogSchema, and automatically logged at a 10ms interval to theFlightRecorder - These subsystems are logged under the channels
SUBSYSTEM_{NAME} - Log schemas include all relevant information to the subsystem, such as the current position/stall time/power
of a
HoldableActuator - These logs are fully automated and no user intervention is required
- Viewing subsystem log schemas live on the dashboard is accomplishable via
Dashboard.logLiveSchema
- This schema is attached internally via
- Additional logging is also done in the
Motor.debugand the newServoEx.debugmethods gamepad1andgamepad2inputs are automatically logged through theControllerclass- The log schema used is compatible with the AdvantageScope Joysticks replay tab, by mimicking a WPILog
- RoadRunner trajectories are logged on construction to further aid debugging
- BunyipsLib metadata (build time, commit) is also recorded on initialisation through the BunyipsLib Hook system
- These
FlightRecorderimprovements greatly improve the support for AdvantageScope reviewing capabilities
- All
- Extracted the
TelemetryPacketmerging implementation fromDualTelemetrytoDashboard.mergePackets(a, b) - Add DECODE field to
Fieldclass - New
Motifenum Motor.debugnow specifies aMotor.Scopevararg to log/telemetry only certain events- New
MotifFinderasync task to run viaThreads- Continuously scans for the Motif AprilTag to return as a result of the task
- New
GreenArtifactandPurpleArtifactColourThresholdprocessors - New
RetryTaskfrom Marrow lib- Allows a Task to be retried while a specific condition is not met, useful for re-running tasks that may fail
- Add the Pinpoint to HardwareTester
- More unit tests (up to 295 now)
PIDFControllernow has agetCurrentProcess()method for polling the state of the controller- AlignToPointDriveTask now has a
withAlignmentOffsetto add an additional robot-centric offset to the alignment - Logging calls across BunyipsLib can now be inhibited with the static variables on DualTelemetry, Dashboard, and Dbg
Task.onlyWhile,.onlyIf,.unlessand other new composition aliases on Task
SDK + dependency updates and reorganising.
- Various dependency updates
- FTC SDK updated to v10.3
- Sloth updated to v0.2.4
- FtcDashboard updated to v0.4.17
- These dependency versions have been updated in the wiki
- Removed the
GoBildaPinpointDriveras this now exists in the SDK- RoadRunner support has subsequently been changed, note now the directions of the Pinpoint wheels are defined in the Params object, not directly to the device
- The corresponding JavaDoc and wiki section has been updated accordingly to accommodate this change
- Filtering
ColourBlobsare no longer done with thefilterByXstatic methods- Following the SDK's change to filtering the
filterByCriteriaandsortByCriteriamethods are used instead to * in-place* filter and sort lists - These changes follow the SDK's choice of an enum to determine criteria, as well as using in-place operations to save memory use
- Following the SDK's change to filtering the
- The
ColourSampleconstructor now takes in three colour spaces throughIntArrays to expose them as separate components- This also means
ColourSampledata instances now store colour information in three colour spaces (RGB, HSV, YCrCb) instead of one (RGB)
- This also means
- Added missing
ofMaxVelMeasureoverloads forTurnclass - The
Encoderinstance used by theHoldableActuatoris now exposed as a public final field, allowing users to access the encoder through the subsystem without needing to grab it directly from hardware- This mirrors the
Motorclass but for the subsystem where it would be most likely used
- This mirrors the
- Various linting and docs improvements
- The new
blackboardmember of SDK v10.3 is now used as the backing array forStorage.memory().getVolatile()andsetVolatile()- Since the functionality overlaps, this change allows the OpMode to also access any volatile information through
the
blackboardfield
- Since the functionality overlaps, this change allows the OpMode to also access any volatile information through
the
- Added
arcLength,circularity, andcircleto theColourBlobvision data class to mirror the SDK - Upstream SDK updates including controller edge detections are now part of BunyipsLib
- Exposes methods on the Gamepad such as
wasPressedandwasReleasedfor built-in support for debouncing - Ties hand-in-hand with the
Controller.getDebouncedmethod, and can be used in place of any regular controller operation
- Exposes methods on the Gamepad such as
Drive task patches.
- Patch a bug where drive tasks were not being set to zero power on completion, affecting:
AlignToAprilTagTaskAlignToContourTaskAlignToPointDriveTaskMoveToAprilTagTaskMoveToContourTaskTurnTask
- Heuristic value
Lambda.EPSILON_MSis now mutable for Runnables that take a long time that should block the task queue
Stability improvements and dependency updates.
- Update RoadRunner FTC to
v0.1.23- Upstream changes integrated, no user-facing breaking changes
- The wiki has been updated with the version bump
DynamicTasknow exposes a final field of typeLateInitCellcalledsharedRefwhich can be accessed to handle simple state- This is designed to be used for tasks that need to share state between execution branches, but is otherwise too simple to put into a conventional anonymous task
- This field is accessible only on the
DynamicTaskdesigned for simple cross-branch state
- Improved stability of
HoldableActuatorgoTotasks- Automatic checks for
isBusy()state capturing has been added to prevent pre-finishing tasks - A timeout and same-position check have been added to ensure this safety feature does not harm operation
- Automatic checks for
QoL and critical robot operation improvements.
Controllerhas been rewritten to use an injection-based pattern- When constructing, the only parameter required is to fill the desiredUser field as per previous implementation, but these instances no longer wrap the SDK gamepad
- Controllers must be injected into the event loop via
Controller.inject(gamepad1, gamepad2)BunyipsOpModeautomatically handles injection and no modification to user code is required- This change fixes a bug where
BunyipsLib.getOpMode().gamepad1or 2 kept getting overwritten, breaking new functionality that depends onControllerbeing in the superclassed OpMode - An update has previously attempted to do this but did not account for the reassignment, causing undefined behaviour
- The new injection scheme also removes the need to call
.update(), since the SDK will directly update the Gamepad object throughfromByteArray, fully replicating the event loop gamepads and causing less erratic behaviour - This change removes methods such as
get(Controls)andupdate()from the Controller instance since the Controller instance will expose the direct fields as the modified values - Methods such as
get(Controls)can be instead found in theControls.isPressedand analog.get(Controls.Analog)equivalent
Encodernow defines a newsetResetOperationinfrastructure to handle encoder homing and reset operations- Allows a more flexible way to manage what happens when the
Encoderobject resets, as motor objects will switch toSTOP_AND_RESET_ENCODER, whereas other inputs may just need to accumulate an offset - The default behaviour for
Encoderinstances is to accumulate an offset namedresetValwhich is subtracted from the total accumulation - An
IntBinaryOperatoris supplied to the user to define a new reset operation, which provides you with the current position of the motor and the current offset, to return a new offset to use - Motor objects return
0for offset and simply reset the motor using the motor modes, described in the bug fixes below and fixing a critical operation bug withMotorinstances
- Allows a more flexible way to manage what happens when the
UnaryFunctionnow extendsDoubleUnaryOperator
- Motor encoder resets through
Motor(andEncoder) now write to the motor mode- Previously, current position was stored locally and discarded after each OpMode, which causes the motor to spontaneously report in another position even after homing
- This bug is a major oversight that required the rewriting of the
Encoderclass reset operations - New
MotorandHoldableActuatorimplementations that depend onEncodernow define their reset operation to only impact the motor, leaving legacy behaviour for non-motor encoders for a resetVal offset
HoldableActuatornow resets the encoder only on ahometask, not on aceiltask as it previously wasHoldableActuatortasks are now cancelled if autonomous limit protections are calledHoldableActuatortarget positions are now clamped to theminLimitandmaxLimit, preventing windupEncoderresets now grab a fresh value of the current value for the reset operation when using cachingHoldableActuatorhome tasks now restore the old motor mode when completing, instead of relying on other tasks
Task.asPriority()added to promote the task to a priority status for subsystem conflicts- Equivalent to setting the second argument of
on()to true, but allows dynamically setting it
- Equivalent to setting the second argument of
ScheduledTask.finishIfButtonRetriggered()added as an automagic method for toggles in Command Based- This is equivalent to the pattern of calling
.getDebouncedon a Controller instance to "toggle" a task, but has improved operation in resetting this debounce if the scheduled task ends prematurely - This method should handle the case when a task needs to be "toggled twice" to be reactivated if the task ends on
its own instead of via the
finishIftrigger
- This is equivalent to the pattern of calling
HoldableActuatorhas new tasksgoToProfiledanddeltaProfiled- These tasks will use the User Setpoint Control as defined by
withUserSetpointControlto gradually move the setpoint from the current target to the new target - This emulates the standard user setpoint control mode maximum constraints, similar to when a
ProfiledPIDControlleris being used; this is useful for cases where tuning one is not desired/inconvenient - These tasks allow the target position to not jump to the new position immediately and cause extremely fast or dangerous actuator movements, and allows more control for fragile components
- User setpoint control must be defined for these tasks to work. Note the functionality of
goToanddeltaremain the same.
- These tasks will use the User Setpoint Control as defined by
Non-breaking library operation refinements.
- General wiki and documentation updates
- Highlighted that the use of
@Configand@RobotConfig.AutoInittogether on the same class is not allowed (see the amendment to the bottom of this wiki section)
- Highlighted that the use of
Motor.encoderis now exposed at mutable- Allows users to overwrite the
Encoderobject used on aMotorobject - Useful for analog or external encoders while still being able to use the
DcMotorinterface
- Allows users to overwrite the
ManualFeedforwardTunerhas reduced the default distance from 96 to 72 inches
- Fix a critical bug where
ManualFeedbackTunerwould crash on tank drive robots if lateral movement was attempted in override mode
- New
Actuatorstandard subsystem- Wraps a
DcMotorSimpleto provide simple motor power controls - Supports CRServos and motors that don't have encoders on them
- API is very similar to the
HoldableActuatorwithout many of the features - Useful for intakes or other mechanisms that only need to rotate
- Wraps a
- Actuator subsystems now have an
actuator.tasks.run(power)task convenience method- This task is syntactic sugar for
tasks.control(() -> power)for tasks that continuously set the power of the actuator - Useful for the new
Actuatorsubsystem when paired with an active intake, without the drawbacks ofsetPowerorrunFor
- This task is syntactic sugar for
Quality of life changes.
Storage.memory().lastKnownAlliancehas been replaced withStorage.memory().lastKnownStartingConfiguration- This removes the narrowing of
StartingConfiguration.PositionbyUserSelectionand opens the rest of the object for the user to use - Functionally,
Storage.memory().lastKnownAllianceis the same now asStorage.memory().lastKnownStartingConfiguration.alliance - Note this field is still only auto-updated by a
UserSelection, it simply removes the unnecessary narrowing
- This removes the narrowing of
StartingConfiguration.Positionexposes all data class fields via@JvmField- This means getters for any StartingConfiguration object will no longer work in Java, and need to be replaced (e.g.
.getAlliance()is now just.alliance) - This change was made for conciseness and since these fields are final
- This means getters for any StartingConfiguration object will no longer work in Java, and need to be replaced (e.g.
StartingConfiguration.Position.toVerboseString()now calls.toUserString()on the field Pose2d for better readability- General reformatting
- Fix a bug where calling
invert()on aStartingConfiguration.Positionwould silently drop all user-attachedflags
- UserSelection now has a new feature
assignButtonto assign a desired button for each selection- This opens flexibility for which specific button a particular selection should use
- An assigned button applies to the whole layer - if an assigned button is not mentioned the default enum ordering ( previous behaviour) is used
- To use this feature, call
.assignButton(int, int, Controls), where you can pass in the layer index, item index in the layer, and desired button - Review the API docs for more information
Dependency updates.
- Updated
Slothto version0.2.1- New installation configuration is available on the installation page of the wiki
- Alternatively, bumping all Sloth-related libs from 0.2.0 to 0.2.1 with a find and replace also works
- Updated the
GoBildaPinpointDriverfrom GoBilda to the latest version- Includes new features for bad read detection, and unit-friendly getters/setters
- Some old properties (such as
readDatanowReadData, etc.) have been renamed
Simple drive accumulator and localizer patches.
SimpleMecanumDriveandSimpleTankDrivenow applyAccumulatorandLocalizers on initialisation to match the otherRoadRunnerDrivevariants- This fixes tasks that run early that try to access a manually set localizer for pose information and corrects the
initial behaviour of nullability for
setPoseandgetPose - Note that now the initial pose of the Accumulator is now
Storage.memory().lastKnownPositionas defined at subsystem construction, matching the other subsystem behaviour- Before, the initial pose from the Accumulator was captured at runtime on the first run of the localizer, but has been changed to capturing on construction
- This fixes tasks that run early that try to access a manually set localizer for pose information and corrects the
initial behaviour of nullability for
Minor telemetry and logging bugfixes.
Exceptions.THROWN_EXCEPTIONSset now runs an additional string equality check to determine if a new exception should be added to the set- Previously, this is how deduping on the Driver Station and dashboard was accomplished, but has been expanded to the stored set of exceptions
- This reduces the chance of a memory leak due to an infinitely expanding list in the event of a repeated exception
Exceptions.handleis now fixed so exceptions show up in the Telemetry log on dashboard and the Driver Station, rather than just Logcat- This bug was introduced in v7.0.3
SimpleMecanumDriveperiodic telemetry is no longer formatted incorrectly, attempting to format with a straythiscall
Critical refactors and bugfixes for general library operation.
- Refactor and rewrite
HoldableActuator- Removes unstable and dodgy patterns by the state machine in
periodic(), following a cleaner code standard which may reduce the number of task-based bugs - The task-based paradigm continues to be the recommended way to control actuators, so
HoldableActuatorhas been updated to follow this system with improved task interactions - This removes the hotfix made in v7.0.2 for a minimum execution duration
- Some redundant methods and functionalities have been upgraded or removed
withTolerance(double, boolean)removed as target position tolerances will now always be applied to the motor objectwithHomingZeroHitsanddisableHomingZeroHitsreplaced withwithHomingZeroVelocityDurationanddisableHomingZeroVelocityDuration- This homing threshold now takes in a
Measure<Time>and uses a timer to determine how long of a zero velocity should be accepted as homed - This functionality is effectively the same as the homing hits but no longer relies on loop time but instead real time
- New safety checks have been added to check if the actuator has initially moved before triggering the zero velocity condition, improving homing operations
- The now-default zero velocity duration is 700 milliseconds
- This homing threshold now takes in a
- Default homing timeout reduced from 5 seconds to 4 seconds
- Removes unstable and dodgy patterns by the state machine in
- Updated
Slothdependency to0.2.0- Resolves a bug where the conventional app hooks were not being executed
- This caused RoadRunner tuning to be broken with no workaround as the HTML pages were not being registered
- Review the wiki for updated Gradle configurations, or simply bump the Sloth version
- Removed
ResetRobotControllerLightsOpMode- It was found that this OpMode isn't even required and since the command is not dangerous, it can be executed at any time
- Robot controller light reset operations are now executed as a POST_STOP
@Hook, which are substantially faster and will no longer breakpreSelectTeleOpor uninitialisation - Functionality from the reset lights OpMode is now fully located in the
OpModesobject
HardwareTestermotor and servo dashboard controls have been greatly improved- Motors and servos are now grouped in the Configuration tab and are correlated with the name of the motor or servo
- These controls dynamically update, so by enabling or disabling dashboard controls for a motor or servo it will be reflected live without needing to transcribe an array
AutonomousBunyipsOpModenow handlessetOpModesthread callback better by halting theBunyipsOpModeinstance until the threads have joined, rather than an empty while loopBunyipsOpModeinstances now try to scan forEmergencyStopinstances proactively to rethrow them if one is found viaExceptions- This change was made as
Threadswas running on a ThreadPool which swallows all Throwables, thereby ignoring EmergencyStop instances
- This change was made as
- Fix Driver Station subsystem disabled warnings to display the elected name of the subsystem instead of just the ID
- Improved idempotency for
setDefaultTaskonBunyipsSubsystem DualTelemetrynow increases the default transmission rate to 100ms by default- This default can be changed through the public static field
DEFAULT_TRANSMISSION_INTERVAL_MS
- This default can be changed through the public static field
- Undeprecated
getTargetPositionToleranceandsetTargetPositionToleranceforMotor- These tolerances are now reflected at the motor object level and attempted to be copied into the current system controller if possible (to align with old behaviour)
Encoderinstances now support caching values- Through
setCachingandclearCachethe last position and velocity readings will be cached, not calling another invocation of the hardware methods until after cache is cleared - This serves as a way to cache reused calls to getPosition or getVelocity without needing the guarantee that bulk reads are enabled
- Caching options are used (and cleared on update) by default with
HoldableActuatoras it composes or hooks into an internalEncoder, so be aware of this behaviour when the actuator is active
- Through
- Improved exception causes for reflection access failures
Taskinstances that are dependent on a disabled subsystem and try to run now internally auto-complete viafinishNow()Threadsduplicate task detection has been adjusted to allow completed tasks with the same ID to start and override the finished one- This will now allow tasks that have the same name but are overriding a finished task to run, instead of forcing the task to use a new name
- Fixed a critical bug where tasks that were created with
.mutate()(DynamicTask) did not have a properstartTime, which led to the task always being "inactive" and delta time returning 0 permanently- This notably causes tasks that rely on delta time and are mutated to never end
ignoreOpModeTypeon the@Hooknow also ignores the double-stop firing protection- This means a user OpMode does not need to have run in order to fire the hook when this mode is active, allowing full hooking capabilities for idle and stop OpModes
- Fixed a bug where
Exceptions.runUserMethodwould ignoreThrowableinstances, silently swallowingErrorinstances for logging - Fix override statuses for
BunyipsOpModenot being respected followingonStart()
IMUEx angular velocity and task hotfixes.
- Resolve a critical bug where
IMUExinstances did not respect theangleUnitparameter ofgetRobotAngularVelocity, always returning in degrees- This led to radians being interpreted as degrees, causing unexpected behaviour for localizers that access the IMU
- Add a minimum execution time for
HoldableActuator'sgoToandhometasks- This ensures actuator tasks do not end prematurely as they must wait a minimum duration of 700 milliseconds to ensure the internal state has been updated
Minor subsystem default task QoL changes.
Taskexposes a newsetAsDefaultTask(), which will internally access itsdependencyto assign the task as the default task to that subsystem- This method is designed to reduce the repetitive pattern of calling
robot.subsystem.setDefaultTask(robot.subsystem.tasks.etc()) - By using this method, it reduces the probability of bugs as it is technically unnecessary to do a dual reference
when all BunyipsLib-integrated tasks set the dependency internally via
on
- This method is designed to reduce the repetitive pattern of calling
- Resolve a bug where the required
ResetRobotControllerLightssystem OpMode was not registered if integrated OpModes were suppressed MecanumDrive.HoldLastPoseTasknow assigns itself to the drive subsystem on construction- Technically unnecessary since
setDefaultTaskwill auto-assign a task to the subsystem, but added for consistency and to supportsetAsDefaultTask()
- Technically unnecessary since
- Fixed an oversight where assigned default task task groups are assigned with
on(), raising a warning
Offseason major library operation and behaviour revamp.
- BunyipsLib has been updated to SDK v10.2
- General package and class restructure
- New packages
executablesandlogicwhich move more classes out of the primary root package for better organisation - All class movements that were made include:
- Merging
EmergencyStopandExceptionsclasses. To access EmergencyStop, it can be accessed throughExceptions.EmergencyStop - Moving
Condition,Encoder,Rampingto newlogicpackage - Moving
Dbg,EncoderTicks,Exceptionstoutilpackage - Moving
DebugMode,IndexedTable,MovingAverageTimer,Periodic,Sound,UserSelectionto newexecutablespackage
- Merging
- New packages
- RoadRunner has been updated to RR FTC v0.1.21
- BunyipsLib now supports tuning goBILDA® Pinpoint Computers and SparkFun OTOS devices through new upstream features
- New localizers to accommodate include the
PinpointLocalizerandOTOSLocalizer, with similar parameter paradigms to the other localizers already in BunyipsLib - WARNING: Upstream & BunyipsLib support for the Pinpoint and OTOS in RoadRunner is incubating. Bugs may exist that may cause the tuning process or localization to not work properly in this specific release.
- Add the
GoBildaPinpointDriversource file underexternal- Some minor documented changes have been made to the file but does not break the public API surface
- Note that BunyipsLib continues to use the "old" localizer definition where localizers do not store the pose
- This step happens in the
Accumulator, and continues to function this way with the old delta-based localizers
- This step happens in the
- New localizers to accommodate include the
RoadRunnerTuningOpModehas been optimised for brevity, better functionality and to support the new tuners- This includes setting the Robot Controller LED blink pattern, which will be the same as the one for Hardware Tester
- The Wiki has been updated accordingly with the new tuning instructions from the upstream RoadRunner documentation
- Includes the removal of
LazyImurepresenting a class but is now an interface- Since
LazyImuis an interface, theMecanumDriveandTankDriveconstructors have been modified to simply take inIMU- This removes the
getLazyImu()fromRobotConfigas well, as it is redundant and no longer necessary - All instances where
LazyImuis expected can be replaced withLazyImu, as it is shimmed internally where required - To use lazy initialisation of an IMU, consult the newly merged
IMUExclass, the RoadRunner IMU shims are considered obsolete in BunyipsLib
- This removes the
- Since
- BunyipsLib now supports tuning goBILDA® Pinpoint Computers and SparkFun OTOS devices through new upstream features
- Removed the
DynIMUclass and merge the dynamic initialisation and null IMU features toIMUEx- All the previous
DynIMUfeatures are now located onIMUEx - To lazy initialise, simply pass your
initializeparameters tolazyInitialize, which will lazy-init your IMU when a field is requested or theLazyImuinterface accessor is touched
- All the previous
- New dependencies to BunyipsLib have been added and removed
- Apache Commons Math has been removed and BunyipsLib no longer references it
- RoadRunner has been updated to v1.0.1
- The
Slothlibrary, a new FTC library, from the Dairy Foundation has been added- Sloth provides classpath scanning, fast loading, and cell utilities through Dairy Util
- Sloth may also referred to as Sinister, as it is the implementation of the Dairy Sinister specification
- RR FTC dependency updated as mentioned previously
- Review the wiki installation instructions again to update the correct dependencies, compilation will fail until this is correct
Scheduler.always()andCommandBasedBunyipsOpMode.always()task bindings have been renamed toimmediately()- The previous name,
always()was misleading as it led programmers to think it would "always execute" a task, rather the actual behaviour is to "immediately allow scheduling" for the given task to therunmethod
- The previous name,
- The
Taskexecution cycle has been revamped to properly run tasks with the context they were designed for- Previously,
Task.run()would run the task wherever it was called, forcing implementations to schedule subsystem tasks - This behaviour introduced uncertainty to whether tasks were executed on subsystems, as calling
onfor a task did not guarantee it would run on the subsystem - Implementations such as the
Schedulerdid respect subsystem tasks, however,AutonomousBunyipsOpModedid not - This implementation ambiguity caused default tasks in Autonomous to not work properly, always causing conflicts with default tasks
- Several task wrappers also did not respect subsystem attachment, causing similar issues
- The new implementation keeps the original
Task.run()method, which is required, but introduces a newTask.execute()method which is preferred - The
executemethod will run the task on the subsystem it was scheduled on, automatically delegating therunmethod to the subsystem if required - The task will also be auto-cancelled from the subsystem if the task is finished
- Internal uses of
Task.run()have been updated toTask.execute() - It is now recommended to use
Task.execute()when running tasks yourself as it will handle subsystems automatically - Tasks that do not want to be scheduled on a subsystem at any time, such as the task composition classes can elect
to enable the protected
disableSubsystemAttachmentfield- This behaviour allows the
onmethod to be final again
- This behaviour allows the
- Previously,
Referencehas been removed and replaced with theRefCellclass from the Util library- This change was made to reduce conflicting dependencies and allows for more flexible reference handling
RefCellhas similar functionality toReference, but has a more flexible API- New utility methods for constructing
RefCellinstances are a part of the newRefutility class, including Kotlin extension functions- A note is that since cells override
toString(),Ref.stringify()exists to only stringify the cell value - Additional functions include familiar methods such as
Ref.of,Ref.empty, and a newRef.lazy
- A note is that since cells override
AutonomousBunyipsOpModeonReadyparameters have been updatedonReadyno longer takes aReference<?>, but instead aRefCell<?>following theReferenceremovalonReadyalso no longer takes aControlsparameter for selected button, which has been removedselectedButtoncan be accessed via a static utilityUserSelection.getLastSelectedButtons()which returns the last series of selected buttons in order from the start of the OpMode- This method can be used for any running
UserSelection, which auto-resets on a new OpMode init
- This method can be used for any running
- This change was made as the
selectedButtonparameter was not used in every observed implementation ofonReady, increasing boilerplate - Following the chaining of
UserSelection, it did also not make sense to have aControlsparameter as it would be ambiguous
- Several
Taskfields have been updatedisPriority()is now a fieldisPrioritywhich can be updatedTaskno longer exposespandfieldOverlay, but instead a singledashboardpacket- To add information to the dashboard or field overlay, use
dashboardanddashboard.fieldOverlay()
- To add information to the dashboard or field overlay, use
BunyipsComponenthas been removed- Accessors for the current OpMode should be done statically via
BunyipsLiborBunyipsOpModedirectly - This improves flexibility and removes the absolute need for OpModes to be
BunyipsOpModeinstances - Several instances where
BunyipsOpModeis required have been updated to use an internal static reference toBunyipsLib- This includes
Exceptions.runUserMethodandSchedulertask scheduling requiring aController
- This includes
- Review the new
DualTelemetrymethods in the Additions section
- Accessors for the current OpMode should be done statically via
Threadshas been completely rewritten to use a thread pool in Kotlin- Thread tasks must now have a name, and the
Threadsclass will schedule these tasks on the default SDK thread pool - Results and computations are processed through the
Threads.Resultclass, in the same way as the JavaExecutorServiceas it is an extension of Java'sFuture- This extended interface gives access to some additional utilities, such as being able to ignore the
stopAll()request which is now automated via a@Hook, and accessing the originalCallablefunction
- This extended interface gives access to some additional utilities, such as being able to ignore the
- Threads continue to have
Exceptionscatch-all handling and will log exceptions in the same way as any standard exception - The documentation for
Threadshas also been updated to reflect these changes and provide warnings on the dangers of threading in FTC
- Thread tasks must now have a name, and the
AutonomousBunyipsOpModehas updated on finish behaviours- The previous
disableHardwareStopOnFinish()method has been removed - Instead, the
setCompletionBehaviourmethod has been added to specify finish behaviour via an enum - The enum has options for finishing the OpMode (default), finishing with no halt, and continuing exeuction
- The new continuing execution behaviour is used to allow default tasks on subsystems to continue after Autonomous is finished
- The previous
UserSelectionnow is aCallable<T>to be supported byThreads, where the result from the selection is returned via theFuture<T>- This means the
resultfield has been removed in favour of theFutureresult, or via the callback
- This means the
SwitchableVisionSenderis no longer blocking, and is designed to be a Runnable to be polled byThreadsor an active loop- Refactored holonomic drive tasks to use the new
FieldOrientableDriveTaskinterface- This interface is a common interface used between all drive tasks capable of field-centric driving
- Methods including
resetFieldCentricOriginand other methods that were originally implemented independently are now part of this interface - Enabling field-centric controls is now done BunyipsLib-style via a builder-like
withFieldCentric(BooleanSupplier)method- The old method of enabling field-centric with a parameter to the constructor has been removed
- This approach allows a common interface between various drive tasks that may use field-centric as a common base
- Protected method
soutfromBunyipsSubsystemis now final Controllerinstances now require a second parameter to indicate which gamepad user the controller is associated with- It was discovered the conventional
getUser()on theGamepadobject was not reliable - A field
designatedUserwas added toControllerto store the user, which is exposed through a try-getterController.tryGetUser - For more information to this change, read issue #101
- It was discovered the conventional
DualTelemetrytakes in an instance ofTelemetryinstead ofOpMode, using static references internally where required- This also fixes the stack overflow issue where the SDK telemetry used to be passed to
DualTelemetryinadvertently, but a field update made it soDualTelemetrywas passed into itself
- This also fixes the stack overflow issue where the SDK telemetry used to be passed to
AutonomousBunyipsOpModesetOpModes(List<Object>)method has been removed- Use
<T> setOpModes(T...)instead, or by converting your list viatoArray() - Varargs are preferred way to use
setOpModesand there was compatibility issues when reintroducing generics for lists
- Use
BunyipsOpModeand variants no longer forces theonInit()(or related) method to be implementedUserSelectionnow listens to bothgamepad1andgamepad2simultaneously when a selection is being made- The
ResetRobotControllerLightsOpMode no longer can be manually started, being removed from the TeleOp list- This OpMode, with the assistance of the new
Hooksystem, activates automagically at the end of any OpMode - RC lights will auto-reset when OpModes naturally stop, solving the problem which caused
ResetRobotControllerLightsto be publicly exposed - This makes lighting patterns a source of truth regarding the robot's state, vastly improving safety like the Robot Signal Light in FRC
- This OpMode, with the assistance of the new
- Improved Kotlin compatibility for
RoadRunnerDrivewithsetAccumulator - Binding logs have been improved for
SchedulerandBunyipsSubsystemtasks - Telemetry message on
UserSelectioninstances has been updated to provide more information on what to do Schedulermuting viamute()andunmute()applies to all active schedulers for the rest of the OpMode (static method)RoadRunnerTuningOpModedefault values have been reduced to 0.2POWER_PER_SECfor rampers and 96 inches forManualFeedforwardTuner.DISTANCE- Usage of
Dbg.login BunyipsLib internal structures have been removed- Replaced with other
Dbgfunctions to not polluteDbg.logfor user code
- Replaced with other
- Dashboard pose colours updated to be more consistent across tasks
- Task names are now spliced per word for better readability
- Task names will be spliced with spaces and Task removed, such that a task with the name MoveToPosTask will have the name "Move To Pos"
- Task naming for tasks such as the composition utilities, (
until,forAtLeastetc) have been updated to assist readability in composition- Tasks such as
WaitTaskhave a name that is simply the number of seconds to wait (e.g.5.0s)
- Tasks such as
TaskBuilder.addTask()now returns the result offresh()to assist in chainingDualTelemetryoverrides the new SDK v10.0setNumDecimalPlacesmethod- It no-ops but now shows deprecation notices and to instead use
Mathf.round
- It no-ops but now shows deprecation notices and to instead use
- Add more Kotlin operator overloads for WPIUnits
BunyipsOpModenow raises an official init-error if the gamepads are not at rest on init- FtcDashboard fields are auto re-initialised whenever the event loop is reattached to avoid stale values
- Improved dynamic localizer switching capabilities
- General JavaDoc updates to remove legacy behaviours and improve clarity in function descriptions
DynamicTaskandLambdanow have alternative constructors/methods which take inConsumer<Task>instead of justRunnable- This allows control over the task that is being run, such as setting a timeout or task name without needing a full instance
- Do note for Kotlin type erasure compatibility there is an extra dummy parameter
ktCompatUnusedIgnorein the oldRunnablevariants, which is hidden via@JvmOverloads- This is to ensure the correct method is called in Kotlin
- The existence of this parameter does not impact the operation of the method, so you can ignore it
- WPIUnits system has been cleaned up and the MeepMeep classes have been rearranged to be updated and easier to port
- This includes adding Dairy Util for references to the library
- Do note since BunyipsLib is an Android library it does not work well with MeepMeep, hence a manual copy of the
util classes is still required
- This continuing doubling up of code is not ideal but is necessary for the time being
- Task naming conventions on subsystems has been formalised into the
forThisSubsystemmethodA - General Kotlin styling updates to increase readability
Task.toVerboseStringno longer has confusing formatting when mixed withTaskGroupinstances- Some task name defaults have been updated, including
Lambda, and the task composition accomplished bythen/after - New unit tests added to test new features and ensure compatibility
- Improved debug logging for
UserSelection - Flags on
StartingConfigurationobjects will now be stringified and appended to the end oftoString()- For example, having two flags "a", "b" will display as
On X, Y from Z [a, b] - This is to assist in differentiating between otherwise similar looking
StartingConfigurationobjects
- For example, having two flags "a", "b" will display as
UserSelectionnow updates telemetry automatically if it is not running on a thread- BunyipsLib integrated OpModes now use Sinister/Sloth for registration, for consistency
- These OpModes have also been given more Logcat logging on execution to assist programmers
Periodiccan now have the interval changed dynamically viasetInterval- Improved RoadRunner channel logging
- Improved documentation and removal of inconsistencies/misleading statements
RoadRunnerDriveinstances that use trajectories optimised to use the built-in delta-time functions- Telemetry for all standard
Moveableinstances whenAccumulatorinstances are present has been updated for clarity- The reference frame for velocity used to be robot-centric, but has now been rotated to be field-centric to match the bracketing on telemetry
EmergencyStophas been updated to allow a cause to be passed into the constructor/set viainitCause, removing the previous always-cause of aForceStopException- The exception from attempting to access the
instancefromBunyipsOpModewhen it is not initialised is now anEmergencyStopwith causeUninitializedPropertyAccessException
- Fixed a critical bug where the SDK fields from BunyipsOpMode were not being updated properly
- This meant that while BunyipsOpMode was running, the backing SDK fields were still the default instances
- Accessing the gamepads or telemetry through the upper OpModeInternal instance would be incorrect as a result
- This also inadvertently raised a bug where
DualTelemetrywas avoiding a stack overflow through this bug
- Fixed a critical bug where
DynamicTask.onReset()calls were not being fired properly - Exception messages on the DS and Logcat no longer hide useful information
- This includes the "caused by" messages being suppressed when
Exceptionswas handling an exception - General improvements to the exception handling behaviour makes it clearer about what went wrong
Exceptionsalso no longer swallowsErrorinstances, which was a design error
- This includes the "caused by" messages being suppressed when
- Fixed a bug where the derivative term of the
PIDFControllerand variants could be NaN if the period was too short- Although this may have been expected behaviour in the previous version of the library and the original source, it causes substantial issues with the new v6.1.1 derivative smoothing filter
- Unit tests have been updated to expect 0 derivative error if the period is too short
DynamicTaskodd/missing inherited behaviour when usingTask.mutatehas been fixed- All drive instances now reset internal power fields when they are disabled
- Task composite naming operations are no longer inconsistent
BunyipsSubsystemstring representations are no longer inaccurate or inconsistent- Fixed faulty idle check for subsystems
SelectTaskhas been fixed to work properly with subsystem integrationRunnablecallback tasks for task group composition utilities now work properly with naming and are no longer inconsistent- Subtask heuristic debugging updated for more clarity
- Fix up WPIUnits JavaDoc formatting
- Fix a NPE thrown when some Vision instances are initialised
- Naming conventions for the HolonomicDriveTasks have been updated to specify the normalisation of the velocity vector
- Internal changes to AutonomousBunyipsOpMode and UserSelection interaction, including misleading docs updates and a missing call to stringify the reference properly
- Patch false nullability warnings for text formatting
Cannonproperly clamps servo open/close position valuesStartingPositions.use()now returnsArray<StartingPositions>instead ofArray<Any>- Fix
UserSelectiontypeTbounds and annotate constructor with@SafeVarargs - Fix
HardwareTesternot displaying some information for certain devices - Fix a bug with
Encodersharing the last timestamp for velocity calculations with acceleration BoundedAccumulatorrestricted areas now behave properly around corners using a vector-based approach
- Through Sinister/Sloth, BunyipsLib now performs classpath scanning
- This exposes the
BunyipsLibstatic class, which regulates static, global library functions - Cleanup of static resources is now handled by OpModeNotifications hooks through the help of Sinister
- This allows for flexible behaviours, where
BunyipsOpModeis no longer an absolute necessity to use the library - The
BunyipsLibclass also exposes agetOpModemethod to retrieve the current OpMode, among other utilities- If possible,
BunyipsLib.getOpMode()will try to return fromBunyipsOpMode, otherwise it will return from the SDK event loop
- If possible,
- This exposes the
- Sloth Load, which is an integrated way of hot-reloading your TeamCode module, is now available as an integrated
feature
- To use it, review the bottom of the Installation section of the BunyipsLib wiki, or review the official docs
- The
@Hookannotation has been added to perform injection on any running OpMode- This leverages the power of classpath scanning mentioned above
- A
@Hookannotated method will inject itself to run before a specific operation in any OpMode that executes - This is useful for operations that need to run before or after the OpMode, such as cleanup or setup
- The
@Hookannotation can be used on any method, and the method must be static and take no parameters - A target must also be provided to the
@Hookannotation to specify the operation to hook into (pre-init, pre-start, post-stop) - Hooks have user exception protection through
Exceptions.runUserMethod, and can have a "priority" to run in order - Internally, several static cleanups use a post-stop hook and
BunyipsOpModeuses a pre-init hook to initialise gamepads and telemetry
- RobotConfig now supports auto-initialisation
- Leveraging a
@Hookon pre-init, RobotConfig instances can be initialised fully automatically before an OpMode starts - This greatly reduces boilerplate in OpModes and removes the need to manually instantiate RobotConfig
- To use auto-initialisation, annotate your RobotConfig with
@RobotConfig.AutoInitand expose a public static final field of which the instance will be stored in - In OpModes, you will be able to access your fully initialised RobotConfig instance via the public static final field
- For OpModes you don't want auto initialisation for, you can annotate the OpMode with
@RobotConfig.InhibitAutoInit, which will cancel auto initialisation for that OpMode - Review the extensive API documentation and wiki for more information on this utility feature
- Leveraging a
UserSelectioncan now be chained, if aT[]orCollection<T>is passed in, the selection will be chained- This is useful for composing multiple selections together, returning the result as an array of selected items
- If you don't want array or list chaining and to keep legacy behaviour, simply call
.disableChaining()on theUserSelection/setOpModesobject - This comes with new features, including setting layering messages to have OpMode permutations via
captionLayers - See
UserSelectiondocumentation and the wiki for more information
DualTelemetrynow exposes the methodssmartAddandsmartLog- These methods add telemetry data to telemetry from a fully static context while respecting
DualTelemetryand forwarding to the dashboard smartAddwill add telemetry data to the telemetry instance, andsmartLogwill add telemetry data to the telemetry log- Subsystems that need compatibility between both OpMode types can use these methods to ensure consistent telemetry behaviour
smartAddalso performs caching of telemetry items when auto-clear is disabled, allowing periodic data to be updated without "spamming" telemetry by adding new objects or having to store aTelemetry.Item- Review the API documentation for more information
- These methods add telemetry data to telemetry from a fully static context while respecting
MecanumDrivehas a default task option to schedule aHoldLastPoseTask- This task will automatically hold the last pose even if no trajectory is running
- It can be enabled via the
MecanumGainsobject - Review the API documentation in
MecanumGainsfor more information
Schedulertasks can now be unbinded byScheduledTaskinstance or creation index viaunbind- A new final field,
idis now affixed to eachScheduledTaskto assist in indexing
- A new final field,
DynamicTasknow hasaddmethods to append to the current task phase code- The
DynamicTaskis also referred to as a mutable task, and can be created by using the.mutate()method on aTask - A manual constructor still exists for convenience and compatibility
- The
- New
IncrementingTaskGroup, which serves as aSequentialTaskGroupbut only cycles on initialisation- This task group is useful for toggles
HardwareTesternow supports FtcDashboard controls- Hardware devices can be "activated" for power/position controls, and allows multiple devices to be controlled on the dashboard
- The OpMode now uses a DualTelemetry instance interally to support the dashboard
DeferredTaskhas agetTask()method to retrieve the internal task- Added additional Kotlin extension functions for
Gamepad Task.castmethod which can perform null assertions as well as casting in one convenience method- This is useful for reducing boilerplate when calling
subsystem.getCurrentTask()(where something likeObjects.requireNonNull((DriveTask) drive.getCurrentTask())is required)
- This is useful for reducing boilerplate when calling
- RoadRunner data classes, including
DriveModel,MotionProfile, expose a newcopyTomethod- This is to allow different drive models to work in tandem, as different localizer implementations need different drive model data
- New
Scopeclass which allows Java users to perform Kotlin-like scope function operations- Includes
let,run, andapply, as well as null-safeletSafeandapplySafe
- Includes
Tasksnow has a getter by string- New group utilities for
TaskGroupsviaTaskTask.nextallows construction of anIncrementingTaskGroupfrom an existing task- New shorthand utilities for static construction of task groups, which include:
Task.seqforSequentialTaskGroupTask.parforParallelTaskGroupTask.rceforRaceTaskGroupTask.ddlforDeadlineTaskGroupTask.incforIncrementingTaskGroup- These utilities construct the respective task group with the given tasks
- Static imports can be used to reduce boilerplate (e.g.
seq(par(task1, task2, task3), task4))
Taskalso adds reimplemented equivalents for the oldRunForTask,ContinuousTask, andWaitForTask- These can be accessed with
Task.runFor,Task.loop, andTask.waitFor, which construct a utilityDynamicTaskfor you - This is useful as it brings back the handiness of the previously removed task compositions without impacting permutations
- These can be accessed with
ServoExnow has an end-to-end-time setting, which is a heuristic used by tasks to mock a servo encoder- This time is measured from servo position 0 to 1 or vice versa, after scaleRange.
- This is useful for tasks that need to wait for servo movement to complete
- By default, the end to end time is 0.5 seconds, and can be adjusted via the
setEndToEndTimemethod - A try-getter
tryGetEndToEndTimeis used in servo tasks to determine the end-to-end time then rescales it depending on the range needed to travel
Rampingnow includes a zero input ramping cutoff option, which can bypass the ramping function if 0 is passed as an input- This option is disabled by default to preserve old behaviour
Geometryadds atoUserString()forPoseVelocity2d, much like thePose2dclassIMUExcan now set a refresh rate to set the minimum interval the IMU can perform a hardware read- This can be done via the new
setRefreshRatemethod
- This can be done via the new
- New
Diffclass, which can be used to perform numerical differentiation with respect to time- This class is used internally for the
Encoderand can be used for any purpose - The differentiator is also equipped with a low-pass filter to smoothen out results, with a default gain of 0.95
- This class is used internally for the
PID systems refactoring and improvements.
ProfiledPIDControllernow extendsPIDController, delegating a lot of its methods over to thePIDFController- Renamed
getPositionError()togetError()onPIDFController - Renamed
getVelocityError()togetErrorDerivative()onPIDFController - For consistency, the
setSetPointandgetSetPointmethods that spannedProfiledPIDControllerandPIDFControllerare now simplysetSetpointandgetSetpoint- To differentiate the
doublesetpoint from the TrapezoidalProfile setpoint, thegetSetPointmethod still exists onProfiledPIDController
- To differentiate the
PIDFControllernew methods and functionalitysetClearIntegralOnNewSetpoint, which will erase the integration accumulation whenever the setpoint is changedsetIntegrationZone, also known as the IZone from WPILib, which sets a region around the error such that integration is enabledenableContinuousInput, also from WPILib, which allows wrapping of PID outputs for continuous systems like angles- See the BunyipsLib wiki (IO section) for more information
PIDFControllernow uses a low-pass filter to smooth derivative readings- Comes with the
setDerivativeSmoothingGainmethod, allowing you to set a low-pass gain (0<g<1) - Designed to reduce noise and oscillation caused by too noisy of data to get a derivative that can be used effectively
- Default value of 0.8 in place for all
PIDFControllerinstances - set toDouble.MIN_VALUEto disable or access/set theDEFAULT_DERIVATIVE_LP_GAINfield
- Comes with the
- New
PIDFControllergetTotalError()method to accompanygetError()andgetErrorDerivative()
- New unit tests for the new refactored PID and features
- These tests are ported from WPILib
- Some tests, like ones that test derivatives have not been integrated as the controllers do not have constant period
- Various docs improvements and corrections
PIDFControllernow exposes the fields:clearIOnNewSetpointminIClampmaxIClampiZonelowerClamp- and
upperClamp
- Various internal restructurings of
PIDFController reset()ofPIDFControllerresets all errors now- The
Filter.LowPassnow exposes as apublic finalfield the gain in use - Implementations of
Filter.LowPassnow have checks to stop reassignment on continuous set calls
Various major bug fixes and API usability improvements.
SemVer note: BunyipsLib will now start to follow a partial SemVer pattern, breaking changes may occur in any version iteration, however, the significance of changes and features will determine how significant the version jump should be ( as there are many underused features in BunyipsLib that are being rearranged but does change some small methods which technically constitutes as a major version).
- The
Tasksystem has been altered to provide a richer API surface- Some task implementations, such as
RunForTask,ContinuousTask,WaitUntilTask, andStartEndTaskhave been removed - The
RunTaskhas been renamed to theLambda, and theOnceTaskhas been merged intoLambda - The
ForeverTaskbase has been removed, and instead allTaskinstances by default run forever (the requirement to overrideisTaskFinishedandperiodicis now optional) - The
DynamicTaskof old BunyipsLib was renamed to theDeferredTask - Several task bases, such as
ActionTask,ConditionalTask,RepeatTask,SelectTask, are now elements of thebasespackage - To account for the missing classes, the new
DynamicTaskclass is used- This new class allows a builder-like composition of tasks, such as a ContinuousTask of old BunyipsLib now
being implemented like:
Task.task().loop(() -> {}). - This allows permutations of classes, such as ones found in
RunForTaskpreviously to be accomplished without limiting what was available - For instance, a task that will wait until a boolean condition is complete can be accomplished via
Task.task().isFinished(() -> bool), and adding extra construction to this is a simple process
- This new class allows a builder-like composition of tasks, such as a ContinuousTask of old BunyipsLib now
being implemented like:
- This new approach also allows some tasks to not have to use a full instance extension, and can be accomplished with the simple builder pattern
- Kotlin users are able to use a DSL pattern for pseudocode like construction of tasks
- For more advanced lambda-based tasks that also track state, a conventional Task extension may still need to be used, however, all methods are optional overrides which reduces code bloatedness
- Some task implementations, such as
- Additional changes were also made to methods such as
pollFinished(now simplypoll), and cleaning up constructors and methods to be more consistent- The
withXmethods (withName,withTimeout,onSubsystemetc) were removed in favour of the simpler versions such asnamed,timeout,onas it was confused with thewithmethod which composes into a group and these methods were inconsistently named/had too many overloads - The timeout constructor has been removed and instead
timeoutcan be accessed and set as a field on the task hasDependency()replaced with simply using the Optional instance fromgetDependency().isPresent()(note: dependency is a field for Kotlin)- The ability to "mute" tasks from Scheduler can now only be done from the Scheduler
- BunyipsSubsystem tasks also no longer use
Scheduler.addTaskReport, which is a now removed method
- BunyipsSubsystem tasks also no longer use
- The
Exceptions.runUserMethodhas flipped arguments from (Runnable, OpMode) to (OpMode, Runnable)ProfiledServohas been renamed toServoEx- API surface of
MoveToContourTaskhas been updated to provide alternative sources of error to calculate forward distance- This allows PnP matrices, area, and other ContourData attributes rather than just pitch to be used for alignment, due to camera configurations
- A
Function<ContourData, Double>is used to return the system's current error (target - current), where the X controller will try to converge these two values - By default, a pitch of 0.0 is used, this can be changed to whatever you'd like using the
withForwardErrorSuppliermethod (while removingwithPitchTarget)
IndexedTableis no longer a BunyipsSubsystem and is instead a Runnable component- It does not make sense for an indexed table to be a subsystem so it has been demoted
- The
BunyipsOpModeinitTasknow only supports supersets of theActioninterface, instead ofRunnable- This is to prevent accidentally placing forever running tasks in the init-task where it should instead be an
action, which is similar to how
onInitLoop()functions to begin with. - The functional pattern of init tasks can still be replicated via an
Action, which is why that was used as opposed to a fullTask(Task implements Action internally so no changes are needed for already task-based init actions)
- This is to prevent accidentally placing forever running tasks in the init-task where it should instead be an
action, which is similar to how
- Subsystem infrastructure has been reworked for task interop
- Names of subsystems are now indexed by default, such as HoldableActuator0, HoldableActuator1, etc.
- This comes with the change that tasks now report the subsystem name on them as well, to assist in telemetry
- Removal of the
NullSafetyutil class- Null safety is now performed at the class level for component assertions
Switchprimary constructor has been updated for consistency- For all servo instances by default, 0 represents Closed, and 1 represents Open (applies to
DualServosand nowSwitch) - The constructor used to be (Servo, openPosition, closePosition), now it is (Servo, closePosition, openPosition) to
match constructors with
DualServos - Be sure to adjust any constructors of Switch to be correct
- For all servo instances by default, 0 represents Closed, and 1 represents Open (applies to
TaskBuilderfor RoadRunner no longer takes in a parameter for calling subsystem on construction as it is handled at the task levelDualTelemetrynow uses@JvmFieldfor several properties, including:opModeStatusoverrideStatusoverheadSubtitledashboardCaptionValueAutoSeparatorlogBracketColorloopSpeedSlowAlert
- The
ActionTask(used internally by theTaskBuilderwhen making RoadRunner trajectories) now properly checks for an infinite timeout task for grouping- This would cause Mecanum Path Following trajectories in combination with TurnTasks (which are time-based) to end early, as the infinite timeout of the path trajectory was interpreted at face value rather than infinite
- Task timeouts are now properly set as if it were a normal task group (such that if one of them are infinite timeout, the whole group is)
TaskBuildermethod.fresh()now internally calls.endTrajectory()to avoid odd unspliced behaviour usingfresh()(upstream RR change)IndexedTablesetmethod now clamps bounds instead of throwing an exception- FtcDashboard telemetry should now reflect Driver Station telemetry logs
- Before, the logs were getting overwritten with each other but now they should persist as entries
- This was achieved by modifying the internal structures of DualTelemetry and the object that stores these items
Storage.memory().unusableComponentshas been removed as a result
- Patch
SplineTestandManualFeedbackTunerfrom doing nothing- The subsystem was not being updated internally causing the drive to do nothing in these tuners
- Fix
ProfiledServoinstances with position caching not responding if the initial position was 0- This was caused by missing a field initialiser for the last known position, defaulting to 0
- This bug caused servos to do nothing (no PWM power) until they were commanded away from their position and back
HoldableActuatorsubsystems now continuously resets the internal encoder instance while the limit switch is being pressed- This makes it so that holding down a limit switch does not leave some random steady-state error
- Resolve concurrency issues with FtcDashboard packets in use with
DualTelemetry- A single packet is now actually sent to the dashboard every update cycle, avoiding conflicts
- Resolve a major recursion bug where using
addFirstinAutonomousBunyipsOpModewould cause a stack overflow- This was due to a boolean flag representing an acknowledged callback being set too late, causing the internal call
to
addFirstto infinitely delegate the queue
- This was due to a boolean flag representing an acknowledged callback being set too late, causing the internal call
to
- Resolve concurrency problems with
AutonomousBunyipsOpMode- Related to the pre and post-queues as they were not using thread-safe instances
- The
UserSelectionfield that shows on FtcDashboard is no longer small CustomAccumulatorregister()method no longer throws an exception due to unsupported operations on an immutable list- Telemetry is no longer cleared when using a
UserSelectionon init, such as usingsetOpModeswithAutonomousBunyipsOpMode - Patched
UserSelectionclearing telemetry on init when it shouldn't beUserSelectionnow also no longer updates telemetry internally, as it should be handled by the main loop
build()andaddTask()ofTaskBuildercan now optionally take in a parameter ofReference<Pose2d>to set the reference to the last spliced pose- This is useful if using
.fresh()is not plausible but the end (unmapped) pose is needed to be extracted to improve code maintainability (similar to.end()of RoadRunner v0.5)
- This is useful if using
- BunyipsSubsystem now exposes static methods
disableAll()andenableAll()to accompanyupdateAll()and theSchedulermethods of managing all subsystems - Adding of
Measureoverloads forVelandAccelutil classes - Added units
FieldTilesPerSecondandFieldTilesPerSecondPerSecondto accompanyFieldTiles - Various linting and improper docs updated
- HoldableActuator
withTolerancemethod now has an overload that invokesapplyToMotorto true by default with one argument SimpleRotatornow exposes the underlying motor object under theactuatorfield- Subtasks of task groups are now reported to Logcat on completion
- Exceptions nullability are now performed at a stacktrace level following the removal of the
NullSafetyclass- Exceptions that have been thrown more than once will not appear on the DS telemetry, but will in Logcat
- This is to avoid spamming up the telemetry on an error that has already been reported
- A string match is used to determine if an exception has been thrown previously
- Optimise what fields are exposed to FtcDashboard
- This removes some classes that always show up, such as DualTelemetry and Vision. These fields are auto-shown when they are used, and in the case of some are completely removed as they don't need to be dynamically tuneable.
AprilTagRelocalizingAccumulatornow has asetKfboolean configuration option- This allows the built-in Kalman filter to be disabled and raw readings to be respected as the new pose instantly
- The Kalman filter is enabled by default
- New
Periodicclass for scheduling generic callbacks at arbitrary intervals, allowing functions to be invoked periodically ColourTunerOpModenow runs in initialisation too to provide the Camera Stream of the DS- Operation of this class is the same as before but actually starting the OpMode is not required
- Visual changes to some telemetry and visual output
HardwareTesternow has a special blink pattern when it is running- Localizer information from the Moveable instances is now smaller on the telemetry to fit in one line
- CLOSE and OPEN positions for
SwitchandDualServosis now green for closed, yellow for open - Telemetry for RobotConfig init updated to "Hardware initialised with X errors" to avoid confusion with the BOM init complete message
- The
ActionTasknow tries to extract more information about an underlyingActionto best convert it into aTask, auto-converting Parallel and Sequential Actions into Task Groups - Internal
BunyipsSubsystemimplementations now can use thesout()method to log to Logcat while including class name and subsystem name without having to splice manually - Default task finishing exception modified to include subsystem name
isRunningDefaultTaskonBunyipsSubsystemto allow checking if the subsystem is running the default taskSchedulernow exposes aliases fordriver()andoperator(), which aregp1()andgp2()- New
Soundclass, which can be used to broadcast sound files on the Driver Station with ease (internally uses the SoundPlayer class) - Several English grammar and spelling fixes in docs
HoldableActuatortelemetry has been updated to be not so confusing when using user setpoint control- IdleTask is no longer checked by name but rather by class instance
Major library rewrites integrating RoadRunner v1.0 and project restructure.
These changelog notes do not cover all BunyipsLib changes due to the size! For further information, see the API docs and view the Wiki when constructed. The Wiki, when ready, will cover all operations only following BunyipsLib >= v6.0.0.
BunyipsLib v6.0.0 is fully backwards-incompatible with earlier versions of BunyipsLib, with over 230 commits being made since the last release. All old code using BunyipsLib must be migrated with the new namespace, classes, and operations.
- FTC SDK v10.1.1 integration
- BunyipsLib now uses Java 17 under the hood due to the SDK upgrades
- Android Studio Ladybug and supported Gradle must be used in order to use BunyipsLib (SDK v10.1.1)
- Namespace updated from
org.murraybridgebunyips.bunyipslibtoau.edu.sa.mbhs.studentrobotics.bunyipslib- This includes the moving of several files into easier, modular directories
- It is recommended to simply delete all BunyipsLib + RoadRunner related imports and reimport them
- Migration of RoadRunner v0.5.6 to RoadRunner v1.0.0
- All previous implementations of RoadRunner have been rewritten to use the new RoadRunner v1.0 ecosystem
- API surface has been reworked, a system of abstractions now represents pose estimation through the
Localizer,AccumulatorandMoveableinterfaces - Drive instances have been simplified down to only use one for different localizers (two types, two simple versions equaling 4 classes)
- Tuning process has been kept similar to how it was done before (through a single OpMode), but now uses the RoadRunner v1.0 tuning process
- RoadRunner processes such as the static constants has been revamped into their respective data classes (similar to how it was done in BunyipsLib 5)
- Trajectories are now created from the drive instances, rather than using an external interface (previously
RoadRunner), with full WPIUnit support baked in through theTaskBuilder - The drive subsystems now fully follow BunyipsLib convention for
Tasksystems, where the RoadRunnerActionis now just a superclass ofTask - Some removed functionality for geometry classes in RoadRunner v1.0.0 is available as part of the
Geometryutil class - Several other breaking changes have been made through the integration of RoadRunner v1.0.0
- Further information will be maintained on the Wiki when it is written regarding RoadRunner, as there are many more changes not specified here
PurePursuithas been removed- The RoadRunner utilities and new path following mode work equivalently to the old "Pure Pursuit" of BunyipsLib, so it has been removed
- See the Mecanum path-following mode (on the
MecanumGainsobject) to activate a displacement trajectory mode
- Several methods have been renamed and appended for brevity and clarity
- Some of these changes were made for Kotlin interoperability, such as having lambda parameters last to support the SAM interface pattern
- See the relevant API docs of the classes to assist in migration
Schedulerhas had a general rewrite to reduce code complexity and resolve some operational bugs- Several Cartesian conversion methods have been removed in favour of using the Robot Coordinate System with +X forward
- This reduces the confusion between conversions on the various new RoadRunner geometry utilities
SystemControlleris now a functional interface and is used across BunyipsLib as the base controller- This opens the range of system controllers that can be made and used
Motoris now split into aSimpleRotatorextension, to allow for CRServos to support motor caching techniquesaddTask()and variants ofAutonomousBunyipsOpModehas been replaced withadd()- Other alias utilities including
run(),defer(), andwait()(not of Object) now exist to accompany `add()
- Other alias utilities including
- ColourThreshold now supports all the features of the built-in SDK colour processor with PnP support too
- This includes ContourData being changed to support the new data types
- Several other fixes, optimisations, and API surface redesigns!
getHardware()ofRobotConfignow supports getting non-HardwareMap devices (such as theRawEncoderfrom RoadRunner)HoldableActuatornow sets the motor to BRAKE by defaultTask.after()is no longer bugged in execution order (used to act like athen())- Fix a missing
TurnTaskoverload - HoldableActuator no longer auto-resets the encoder on the arm on init as it discards known information
- The target position of
Motoris now stored locally instead of writing to the Lynx firmware BoundedAccumulator(previouslyBoundedLocalization) now clamps velocity when a clamping operation is in progress- The
AprilTagPoseEstimatorhas been reimplemented as theAprilTagRelocalizingAccumulator, with the bugs from the previous version fixed (360s, weird rotations) - The
Filter.Kalmannow exposes more methods to deal with continuous vs discrete inputs - Patch initialisation issue for
MultiColourThreshold - Methods on the
Switchsubsystem have been renamed for consistency with clamping bounds Controlsstring representation no longer breaks the Driver Station telemetryMotorandEncoderreadings no longer are linked- Ensure motors are running and reading the correct directions, as a FORWARD encoder may not mean it is actually moving forward on the motor
- By default this change should not affect most hardware but brings consistency to an unnecessarily linked system
- Fix defective
DifferentialDriveTaskpassing in the wrong vector
- 182+ Unit tests have been integrated into BunyipsLib
- These tests ensure the operations of utilities are working properly, increasing the robustness of the library
- Further unit tests will be created for code that should need such a test
- MeepMeep is now a BunyipsLib-standard application built-in
- To use it, add MeepMeep code in the
MeepMeepRunnerfile, which has full support for the RoadRunnerTaskBuilderand WPIUnits - This integration allows for faster path generation, all built into BunyipsLib without needing to perform any additional installation
- To use it, add MeepMeep code in the
- RobotConfig now has a utility
getLazyImufor getting the RoadRunner LazyImu instance used for the drive subsystems - Scheduler has split the task builder
inTimeandfinishIfconstructors into their own mini-builder, where calling finishIf twice will compose an OR condition HardwareTesterOpMode, which allows the scanning ofHardwareMapto provide simple controls on nearly every hardware device without needing to build code- This is a new built-in OpMode that sits at the bottom of the TeleOp OpMode list, and is useful for rapid testing of actuators/devices
- Several Kotlin integrations, including some classes being rewritten in Kotlin to support useful infix and extension functions
- Nullability throughout BunyipsLib has been considered and all nullable/non-nullable references have been annotated
with
@NonNullor@Nullable Encodernow uses a delta approach to track position, allowing new known encoder positions to be set on the fly- HoldableActuator can now map
TouchSensorinstances to reset the encoder to a specific position when the switch is touched - New
Conditionclass which handles rising and falling edge boolean detection (used internally byScheduler) DynIMUclass to support delegating an IMU instance or using a 'null' IMU- Improvements to the
TelemetryMenuchildren options - RoadRunner packets can now be synchronised to send at a single time using the new
Dashboardutil - New geometry utilities available as extension functions of
Mathf - User setpoint control of
HoldableActuatornow provides delta time automatically through theFunctionprovided HoldableActuatornow has several safety features including steady-state error detection, stall current detection, and improved operator safety- Field-centric origins can now be set on field-centric drive tasks to set a new origin of rotation
- This makes it so you no longer have to reset the odometry to zero in order to zero out the rotation origin
InvertibleTouchSensor, which can invert a touch sensor's readings if they are pressed when not pressed and vice versa- Nominal voltage compensation features for
Motor - Telemetry updates and refinements for Autonomous operations
resetDebounce()method forControllerto reset the initial state for debounce detection- New INTO THE DEEP processors for
NeutralSample,RedSample, andBlueSample - Plus more additional valuable features!
Hotfixes for AprilTagPoseEstimator.
- Kalman filter heading outputs for AprilTagPoseEstimator are being stabilised with a low-pass filter as a hotfix
- This should reduce the random rotation errors when moving while looking at a tag
- In the upcoming v6.0.0 release, details below, ATPE will potentially be upgraded into its own localizer rather
than its own component
- This upgrade is subject to change for the final release
- Fixed broken rotation matrices for AprilTagPoseEstimator
- The yaw of the tag was not being correctly used and only caused localization to be accurate if the robot was square with the tag
- This has been resolved
- AprilTagPoseEstimator now uses an average if multiple tags are detected to improve accuracy
- BunyipsLib v6.0.0
- Major restructure of files, more files will be in appropriate folders and the namespace will be updated
- RoadRunner will be upgraded from v0.5.6 to v1.0.0, with many of the drive classes being refactored and vastly simplified
- Removal of over 30 files (4000 L.O.C)
- Various other features and removals to improve and simplify BunyipsLib development
Several quality-of-life adjustments, bug fixes, and features.
- PhotonFTC has been removed as a default required dependency to BunyipsLib
- Due to the state of Photon in alpha, it has been decided for stability to instead define the Photon annotations at the user OpMode level
- The BunyipsLib documentation still suggests installing Photon in the deps, but has been removed from
BunyipsOpModeas it is the base to all OpModes - Since Photon is a one-line addition, this is more sustainable for the time being while stability of Photon improves
- This reverts the integration of Photon to <5.0.0
- The
Motorclass has been rewritten following a critical bug related toRUN_TO_POSITION - This bug would cause motors to sporadically run away from the setpoint when moving in a backward direction
- The bug has been identified to exist since BunyipsLib v4.0.0
- Previously, the implementation of
Motorwas that it extendedDcMotorImplEx; however, an internal method which is responsible for setting power was callinggetMode(), which related to the overridden version inMotor - Note that
Motorforces the actual motor to always run inRUN_WITHOUT_ENCODERmode as the hub-level PID controllers should always be disabled - This caused all
setPowercalls to be positive whenRUN_TO_POSITIONwas active, as internally the power is taken for an absolute value in the standardRUN_TO_POSITIONmode - Unfortunately, this would cause all system controllers on
RUN_TO_POSITIONto respond as normal, but just before the command was sent to the motors it was taken for an absolute value, making the controller physically incapable of moving the motor backwards - This bug has been fixed by instead implementing the
DcMotorExinterface and handling the motor controller manually - As a side effect, the
Motorclass now supports the usage of allDcMotorExmethods in some proportion
BunyipsComponentno longer needs to be running in the context of aBunyipsOpMode- This makes components that extend
BunyipsComponentsimply a utility instead of a strict requirement - Opens up subsystems, tasks, and all other components to not just
BunyipsOpModecontexts, oftentimes when these components didn't need a reference to the OpMode anyways - Previous implementations of BunyipsComponent are unaffected, however, the
opModefield has been made@Nullablewhich may throw some compiler warnings (as it is now possible for components to exist such thatopModeis going to be null) - The new
BunyipsComponentutilities now provide ways to assert behaviour and run code only onBunyipsOpModecontexts, such asrequire(opMode)andopMode(o -> o)to assert presence and no-op calls - Any custom components may need to be migrated with these new utilities to ensure the compiler does not throw errors
- The integrated subsystems have already been migrated and no changes are needed in user space
- This makes components that extend
BunyipsOpModeactive-loop runnables are now part of aHashSetrather than anArrayListto prevent duplicates- Several components including
DebugMode,AprilTagPoseEstimator, and new runnable components now auto-attach to theBunyipsOpModerunnables list if they can on construction- All runnable components also have the convention of a static method called
enable()for concise construction
- All runnable components also have the convention of a static method called
MathfandEncoderTicksutilities now take in theNumbersupertype when taking in arguments- This removes the dual
double/floatmethods ofMathf, and reduces the number of casts that need to be done when working withEncoderTicksthat are sometimes inintordoubleforms - Internally, these
Numbersupertypes are all converted todoubles
- This removes the dual
- The
Switchclass has been disconnected from theCannonclass- This may cause some unknown method calls if using a
Cannonmethod from a previousSwitchclass on migration
- This may cause some unknown method calls if using a
Taskcomposition has been made simplerAutonomousBunyipsOpModenow returns the added task instance when callingaddTask()RoadRunnerdoes the same foraddTask()
- Tasks can now compose with utility functions attached directly to
Task.untilwhich composes the current task with aRaceTaskGroupand aWaitUntilTask.afterwhich composes a task with the current task in aSequentialTaskGroup.thenwhich composes the current task with a task in aSequentialTaskGroup.withwhich composes aParallelTaskGroupwith all the tasks.racewhich composes aRaceTaskGroupwith all the tasks.duringwhich composes aDeadlineTaskGroupwith the current task being the deadline.repeatedlywhich wraps the current task in aRepeatTask
- These integrations make task construction more concise without having to construct groups manually for small operations
- The
ColourBlobvision data type from theColourLocatorprocessor can now be converted intoContourDatainstances- This allows tasks like
AlignToContourTaskandMoveToContourTaskto be used with the new SDK 10.1 processors - To convert all list processor data into a
ContourDatalist, a simple map operation can be performed as listed in the documentation for this method - The corresponding contour-based tasks now have alternate constructors for taking in instances of
Supplier<List<ContourData>>rather than specifying a strict requirement onProcessor<ContourData>
- This allows tasks like
PIDFControllerchanges- Following conventions throughout BunyipsLib,
PIDFController(and derivatives) now have builder-like patterns to allow for more streamlined construction PIDFControlleralso now has asetOutputClampsmethod to control the maximum and minimum results the controller may output- Variants
ArmControllerandPIDFFControllernow support instances of the basePIDFto be used to allow profiled PID controllers instead of the hardcoded normal PID
- Following conventions throughout BunyipsLib,
Encodernow pipes acceleration estimation data through a built-in low-pass filter that can be modified viasetAccelLowPassGain(double)- All previous tasks and components that relied on instance of
RoadRunnerDrivehave been abstracted via the newMoveableinterface- This changes the abstraction level of various tasks and components to be as minimal as possible - RoadRunner is no longer required to use most of the drivebase features in BunyipsLib
- Some classes that take in instances of
BunyipsSubsystemfor their drive base have been migrated toMoveable, note that auto-attaching the task to a subsystem is still performed internally
Referencenow implementsSupplierandConsumerDualServosandCannonno longer auto-callsupdate()on init- This is to consolidate the idea that no hardware writes will occur outside of the user's command, especially as penalties exist for servo movements during the match init-phase
- If you wish to preserve the old behaviour, simply call
.update()in your init method
- Acceleration information from
Encodercan no longer be stale and is now updated on every loop with epsilon checks RoadRunnerwithTimeoutbuilder parameter now sets the timeout to infinite if a negative timeout is supplied- Various outdated docs updates
addTaskofRoadRunnernow checks for an active instance ofAutonomousBunyipsOpModeto throw an exception early if it is not initialiseddisableHardwareStopOnFinish()ofAutonomousBunyipsOpModeis now a final methodMotornow clamps theRUN_TO_POSITIONsystem controller output to -1 and 1 to allow thesetPowerargument to have a direct proportion over the controllerEncodernow flips the velocity readings depending on the direction, before this would only flip the current positionHoldableActuatoris no longer affected by the user-defined min and max encoder limits when homing- The
BlinkinLightsinternalsetPatterncall is now cached to prevent spamming Logcat or calling unnecessary code- Do be aware of this if you manually call
setPatternon theRevBlinkinLedDriver
- Do be aware of this if you manually call
HoldableActuatorupdate method is now more conservative with hardware calls- Hardware calls are executed at the end of the update method, which prevents multiple calls to
setTargetPosition()andsetMode() - The motor power magnitude has also been updated to the proper sign depending on the signum of error to allow bounds checking to work properly
- Hardware calls are executed at the end of the update method, which prevents multiple calls to
- Various optimisations for
AprilTagPoseEstimatorto reduce jank- The component now does not spam Logcat as much when seeing an AprilTag to adjust pose
- Several modulus operations for heading have been added to reduce problems
- Pure Pursuit implementation using a parametric look-ahead
- Offered as a new component called
PurePursuitwhich can generate paths similar to RoadRunner to follow - Uses a parametric look-ahead based on the supplied path instead of a circle-line intersection for simplicity and more precise cornering
- This algorithm is a step up from PID-To-Point (DriveToPoseTask) and below RoadRunner
- The PurePursuit class has been built around the RoadRunner coordinate systems and should work well with currently implemented tools
- Offered as a new component called
- New HardwareDevice drop-in replacement
ProfiledServoto allow motion-profiled servos- Similar to the
Motorclass wrapping aDcMotor, theProfiledServoclass wraps aServo ProfiledServoexposes a new methodsetConstraintswhich can be used to define aTrapezoidalProfilethat will be used to motion profile the servo- This allows velocity and acceleration control over the servo, while still conforming to the
Servointerface for use in any previous code - Additional features from
Motorincluding position cache tolerance and refresh rate have also been integrated in the methodssetPositionDeltaThresholdandsetPositionRefreshRate - Review the
ProfiledServoclass for more information
- Similar to the
- The
Moveableinterface, which is a common interface for all drive bases- This interface allows drives such as the
CartesianMecanumDriveto be used in place of RoadRunner drives, often when the features of RoadRunner don't need to be used - Exposes two methods,
@Nullable getLocalizer()andsetPower(Pose2d), which respect the Robot Coordinate System and are implemented byRoadRunnerDriveandCartesianMecanumDrive - By moving to these interfaces, component flexibility is improved dramatically where localizers can be used without the need for RoadRunner
CartesianMecanumDrivecan support holding aLocalizerthroughsetLocalizer(), which may be required if a drive instance is passed around as aMoveable
- This interface allows drives such as the
- Ported
MecanumLocalizerandTankLocalizerfrom RoadRunner- These localizers have no dependencies on the RoadRunner drives, which allows pure functional suppliers to be used for localization
- This makes the
Localizerfrom RoadRunner a common interface on all drives
EncoderTicksnow has a utility function to convert ticks directly to inches, which is used in the new ported Localizers- This converts a tick reading, wheel radius in inches, gear ratio, and ticks per revolution into inches for use with the Localizers
- New
TurnTaskwhich is similar toDriveToPoseTaskbut only requires one PID controller for turning, and does not have a strict dependency on aRoadRunnerDrive- Supports either global robot-frame heading targets or heading offsets
- New
Rectclass which represents twoVector2dinstances to create an upright rectangle- Based on RoadRunner geometry classes, which allows more advanced uses of vectors
- New
Fieldutility class for FTC fields- Provides a
Rectwhich defines the maximum boundary of the field Seasonenum that has methodsgetRestrictedAreas()andgetAprilTagLibrary()- The INTO THE DEEP season has been included in this enum and denotes the restrictions of the submersible zone and supporting poles, as well as fetching the relevant AprilTag library from the SDK
- Provides a
- New
BoundedLocalizationrunnable component to provide clamping of pose estimates to within the field- By default, pose estimates can often be in illegal positions, and for odometry that cannot determine these states causes the robot to leave the field
- This component runs in the background and ensures the pose is in legal areas, and can be customised with
Rects to define spaces the robot cannot go in, including utilities fromFieldfor built-in restricted areas
BunyipsOpModenow has a method to remove runnables from the active-loop runnables listdetachActiveLoopRunnablesTankDrive(and the base RoadRunner equivalent) now have agetCoefficients()method forTankCoefficientssimilar toMecanumDriveforMecanumCoefficientsEncodernow can track a motor direction as set by a functional interface, which allows the state of theEncoderto be controlled by an encapsulating componentSwitchsubsystem has been revamped- Disconnected from
Cannon,Switchis now able to represent positions that are not limited to simply two positions - This makes
Switchthe single counterpart toDualServos, but with more control on bounds with utility methods and toggles - Review the new
Switchclass for more information
- Disconnected from
- New
MathfutilitiesapproximatelyEqualswhich uses an epsilon of1e-6to check if two decimals are equallineCircleIntersectionandlineSegmentCircleIntersectionfor calculating these intersection points using the quadratic formula
HoldableActuatornewceil()task, which runs a home task in the opposite directionThreeWheelLocalizerinstances can now opt into using a periodic IMU reset, which will intermittently use the IMU to relocalise the robot heading- This is useful for correcting drift while not impacting loop times significantly due to I2C reads
- To use this feature, an IMU must be passed via
ThreeWheelLocalizer.withRelocalizingIMU(IMU), and theThreeWheelLocalizer.Coefficientsmust define a non-nullsetIMURelocalizationInterval(Measure<Time>) TriDeadwheelMecanumDriveinternally callswithRelocalizingIMU(IMU)with the IMU parameter
HoldableActuatornow has an optional mode where user input modes will instead follow the setpoint instead of feeding raw power- This can be enabled with
enableUserSetpointControl(DoubleSupplier), where the supplier is a multiplicative scale to use in setpoint adjustment (for things such as deltaTime or other math) - This mode will instead adjust the setpoint when a user uses a
setPower()call, allowing the PID controller to do all the work - It is recommended to use this mode only if the motor used in the
HoldableActuatoris aMotorinstance, as the stock motor may react too slow
- This can be enabled with
- New
IMULocalizer, which implementsLocalizerand can be used in place of a Localizer to simply provide heading information- This is useful for new tasks that may only need heading information (e.g.
TurnTask) and a main localizer is not implemented
- This is useful for new tasks that may only need heading information (e.g.
DashboardUtilhas a newuseCanvas(Consumer<Canvas>)method which will attempt to retrieve a reference to the FtcDashboard canvas viaBunyipsOpMode, or by creating a new packet under the hood and sending it on completion- This is useful for components to draw on the dashboard from any static context without having to check OpMode state
AprilTagDatanow exposes atoRect()method to convert the bounding box to aRect- This Rect can be used to construct a
ContourDataor other information as desired
- This Rect can be used to construct a
AprilTagPoseEstimatornow supports filters- Can be added via
addDataFilter(Predicate<AprilTagData>)and will run thePredicateon every detected AprilTag'sAprilTagData - This can be used in combination with
toRect()to filter results, such as filtering by area (for example,.addDataFilter(t -> t.toRect().area() > 1000))
- Can be added via
Integration of SDK v10.1 and season-related features.
- Trajectory mirroring of the
RoadRunnerutility class has been revamped by an enum- Instead of passing a simple boolean state to reflect across the alliance plane, options now exist to mirror symmetrically
- The new
MirrorMaptypes are nowNONE,ALLIANCE_REFLECTION(default), andSYMMETRIC_MIRROR - The symmetric mirror profile was created as the INTO THE DEEP field is symmetric and using global reference frames is important for AprilTag repositioning
- All old instances of pose mirroring contexts have been replaced with taking in a parameter of type
MirrorMap
- PhotonFTC (v3.0.2-ALPHA) by Eeshwar has been integrated as an included library
- Teams may choose not to use Photon by removing the annotation from
BunyipsOpModeand/or not including the library - Reread and follow the wiki installation instructions to bring in the new integrations, as well as making sure the versions match (for other lib. updates)
- Teams may choose not to use Photon by removing the annotation from
Processorinstances no longer take a copy of the frame before sending it to the processing methods- For most cases, this should not change anything; this change was needed to be made for the new SDK v10.1 processors
- There should now be less memory overhead for vision processing as a side effect
- This is listed as a breaking change as it may affect certain processors
- Fixed misnamed processor thresholds for all CENTERSTAGE Pixel colour processors, the thresholds were called YCBCR instead of YCRCB
- Various docs updates and migration to the wiki
DualTelemetrynow displays the appropriate unit ofHzinstead ofl/sonce the loop times are too fast to be represented as milliseconds- The slow loop speed warnings of
DualTelemetrynow don't show up during the init-phase when used in aLinearOpModederivative- The init-phase is the heavy processing of the OpMode and loop times don't matter during init
Processor.getCameraDimensions()is now a public methodRamping.DcMotornow extendsDcMotorImplExinstead ofDcMotorImpl
RoadRunnerDrivewatchdog timeouts no longer log in warnings but instead debug logs- Fixed the separator in
TelemetryMenu, there is now a gray bar at the start of every menu entry for ease of use on FtcDashboard RoadRunnerDriveinstances now cache their run mode during the constantsetMode()calls in the update loop- This reduces redundant invocations of
setMode() - It is important to only dynamically modify the drivetrain run mode manually through the
RoadRunnerDriveinstance instead of the motors themselves, due to the caching
- This reduces redundant invocations of
- Update to SDK v10.1; the new recommended SDK version is now v10.1
- New
ColourLocatorprocessor that wraps aColorBlobLocatorProcessor - New
ColourSensorprocessor that wraps aPredominantColorProcessor - Appropriate data classes with filtering methods are
ColourBlobandColourSample, appropriately - Since these processors are instance-based instead of abstract, their IDs are represented by
coloursensor0,coloursensor1, etc. andcolourlocator0,colourlocator1etc. depending on the number of instances- These IDs are important to know for FtcDashboard switching or processor differentiation
- The BunyipsLib integration of these processors makes constant FtcDashboard viewing available and reduces unnecessary canvas overhead
- These new processors work the same as the pre-existing
ColourThresholdandAprilTagprocessors - The legacy
ColourThresholdandMultiColourThresholdwill not be deprecated
- New
- RoadRunner v1.0.0 is not planned for integration
- This is because of the ties RoadRunner v0.5.6 has with the path generator, visualiser, and utilities that don't bring any significant value to BunyipsLib upon migration
- Command-based features of RoadRunner v1.0.0 are already implemented as part of the
SchedulerandTasksystem - Time is better spent for BunyipsLib development working on the wiki and new features rather than refactoring old but still useful systems
StartingConfigurationsassumes a square field, where the blue alliance is opposite the red alliance- In the event a future season does have a diamond field (it has not been the case for a while), then an integration may be made to support this
- It is not of priority now or for this season, so it is not scheduled for implementation and won't be reconsidered until next season
New features and additions for INTO THE DEEP.
- The
FieldTiles(FieldTile) custom WPIUnits unit has been updated from being defined as 23.6 inches to 24 inches- This change may potentially break previous implementations that relied on the nature of
FieldTilebeing 23.6 inches - This unit was supposed to have a magnitude of 24, where the approximation was used by mistake
- This change may potentially break previous implementations that relied on the nature of
TaskGrouptimeout calculation has been fixed- Previously, task group timeout calculations were done all via the parallel calculation, which takes the highest value and sets it to the group timeout
- However, this was short-sighted as other task groups like the sequential task group instead operate on a sum-of-all-timeouts
- These incorrectly implemented timeouts have been fixed appropriately for all task groups, via a new super argument
for the
TaskGroupabstraction
SchedulerrunOnce()now behaves uniformly between subsystems and independent tasks- Before,
runOnce()would queue once on a subsystem, and execute once independently - This made inconsistent behaviour between the two due to an internal flaw in the
Scheduler - Now,
runOnce()will guarantee one queue of a task from start to finish regardless of environment, putting emphasis onfinishingIf()to end queued execution
- Before,
Exceptionsno longer swallows theForceStopException(oops)
AprilTagPoseEstimatornow internally uses Kalman filters to fuse odometry and AprilTag readings- The Kalman gains are set to sane defaults and can be customised via
setKalmanGains - Note!
setHeadingEstimatenow defaults to true, as the Kalman filter should now filter out the erratic heading readings
- The Kalman gains are set to sane defaults and can be customised via
BunyipsComponentand their derivatives (e.g.BunyipsSubsystem,Task) can now be constructed in the OpMode member fields- A constructor hook now supplies a partially constructed static reference to a BunyipsOpMode to allow instance calls to be made in the member fields
- This partially constructed static instance is reassigned as usual at runtime to preserve normal behaviour
- The
toShortString()(toString()) method attached to WPIUnits has been updated- Previously
Unitinstances that calledtoString()would provide the string with 3 decimal point scientific notation - This has been changed to simply show the magnitude in full for brevity
- Instead of returning
1.234e+04 V/m, this method will now return1234 V/m - This combines
toLongString()without the full unit name - Previous scientific notation behaviour has been preserved in a new
toScientificString()method
- Previously
BunyipsOpModenow exposes the previously protected methodsonActiveLoopandsetInitTaskas public to allow static access- This allows you to add
activeLoopsnippets from anywhere, including theRobotConfig
- This allows you to add
toString()ofStartingPositionsinstances now internally callStartingPositions.getHTMLIfAvailable()to return an HTML-receiver-friendly output without having to callgetHTMLIfAvailable()manually- The built-in
name()method preserves the old behaviour oftoString()
- The built-in
- FtcDashboard now shows more overlay data for certain
AlignTotasks, including vector powers for drive input - Various JavaDoc and debugging statement updates
OnceTaskinternal timeout has been increased to 10ms to allow interpretation of summed timeouts to work properlyBunyipsOpModeonActiveLoopnow runs all Runnables through theExceptionshandler to ensure exceptions do not hamper the rest of the loop- Various uses of
PIDFControllerin constructors have been replaced with the more relaxedPIDFinterface to allow for a wider range of controllers- Note that since the coefficients are no longer constant, dynamically adjustable coefficients that were on the task/class level only apply to the underlying PIDF coefficients as they did previously
- Other dynamically adjusted coefficients will need to be managed by yourself
BlinkinLightsnow has methods for setting the default pattern to other patterns if desired, it is no longer final- To follow subsystem convention,
BlinkinLightsmethods now return their instance for builder-like patterns
- To follow subsystem convention,
Task.reset()now no-ops if the task has already been reset, preventing the multi-fire ofonReset()BunyipsOpModewill now try to reset the RC lights viaexit()if it can, since it still has access to hardware writesTelemetryMenunow spaces options slightly more to allow FtcDashboard users to read the menu easier
- Hardcoded values of
org.murraybridgebunyips.bunyipslibhave been replaced with theBuildConfig.LIBRARY_PACKAGE_NAMEconstant for cleanliness - Modern uses of out-of-range exceptions thrown in BunyipsLib now respect the domain of the bound
- Future bounds-checking now uses Apache Math3 utilities, old checks will be left as-is
- Debugging statement for the
onReady()call inAutonomousBunyipsOpModenow strips HTML from the selected OpMode setDefaultTaskofBunyipsSubsystemnow internally callsonSubsystem(this)to ensure default tasks are assigned to the current subsystem- The
PIDFinterface now extendsSystemControlleras they are always used together BunyipsOpModeno longer initially sleeps before evaluating the init-loop for the first time- Exceptions thrown via
Exceptionsduring init will now be recognised and alerted in theBunyipsOpModeinit-cycle DualTelemetry.addDatanow accepts nullable data parameters to match other instances of adding telemetry data- Fix a missing return from an early return in
UserSelection
- New
StartingConfigurationsystem to assist in robot starting configuration selection- This class has been designed to expand the
StartingPositionsenum following the 2024 season not being limited to simply two tiles per alliance - Instances of a
StartingConfiguration.Positionindicate the exact orientation/rotation/alliance/origin that the programmer has desired, rather than simply being on an alliance and left/right side - Construction of a starting position is done through a builder pattern (e.g.
blueRight().tile(4)) with options for translation offset and rotation - These new configurations are designed to be used seamlessly with an
AutonomousBunyipsOpModethrough thesetOpModes()method- The programmer now has a lot more information regarding the starting configuration of the robot, including a
toFieldPose()method to extract the starting configuration in terms of the FTC Field Coordinate system
- The programmer now has a lot more information regarding the starting configuration of the robot, including a
- Position
toString()method will return a HTML human-friendly output (forUserSelection)Red Alliance, Rightfrom StartingPositions becomesOn Red, Tile #3 from RIGHT wallin a StartingConfiguration
- Documentation and conversion methods have been added to both StartingPositions and the new class
- StartingPositions is not planned to be deprecated to preserve backward compatibility
- See the corresponding JavaDoc for more information
- This class has been designed to expand the
- New
Filterclass, which provides data and sensor filters- The newly added filters available through this class are a
LowPassfilter, 1DKalmanfilter, andWeightedFusionfilter - The
Kalmanfilter is used internally in theAprilTagPoseEstimator
- The newly added filters available through this class are a
- New
AlignToPointDriveTask, which uses a PID controller and feedforward to rotate to a field point as a TeleOp drive task - New
DebugMode, which is a Runnable built via a builder pattern to auto-halt or terminate OpModes based on various conditions- This includes watchdog timeouts, gamepad kill switches, and IMU roll detection
- These features were designed for use in a debugging environment to quickly stop the robot if working with experimental code
Motornow has configuration options for setting a power cache tolerance and power refresh rate- These utilities allow hardware writes to be optimised, but must be used with caution
- See
setPowerDeltaThresholdandsetPowerRefreshRateofMotor
AprilTagDatais now populated with a new fieldrobotPosewhich is new from SDK 10.0- This pose is returned directly from the processor and is calculated via the camera-robot pose provided in the
AprilTagbuilder
- This pose is returned directly from the processor and is calculated via the camera-robot pose provided in the
- All
RoadRunnerDriveinstances now must include asetRotationPriorityWeightedDrivePower()override to run the weighted drive power calculation with rotational priority- Custom implementations of
RoadRunnerDrivewill need to extend this new method and implement it accordingly CartesianMecanumDrivenow exposes an internal static method to calculate rotation priority Mecanum poses
- Custom implementations of
IMUExnow has asetYawMultiplier()method, which can be used to set a multiplicative scale for IMU yaw readings- This is similar to the X and Y multipliers attached to tracking wheel localizers
BunyipsOpModenow has astopMotors()method which serves as a softer alternative tosafeHaltHardware()Exceptionsnow stores a static list of all exceptions that have been thrown- The reset method for this instance has been appended to
Storage.resetAllStaticFieldsForOpMode()
- The reset method for this instance has been appended to
BunyipsOpModenow has a static methodifRunning()which will execute the suppliedConsumer<BunyipsOpMode>ifBunyipsOpMode.isRunning()is trueBunyipsOpModenow has agetInitTask()method to return anOptional<Runnable>of the currently respected init-taskText.removeHtml()created to regex out HTML tags and non-breaking spaces from stringsText.upper()and.lower()created for cross-compatibility reasons in Kotlin, which will uppercase and lowercase strings
Major INTO THE DEEP season release.
Note! BunyipsLib v4.0.0 has many breaking changes that consolidate the codebase; please review every item carefully if migrating.
- SDK v10.0 related deprecations
- The BunyipsLib SDK version has been bumped from v9.2 to v10.0 for usability in the INTO THE DEEP season
- TFOD-related subsystems have been archived following their removal in the SDK
- This includes deprecated in v3.5.0 classes
TFODandTfodData - The SDK no longer offers TFOD; future vision integrations are expected to use OpenCV, which is integrated into
BunyipsLib through the
Processorpipelines.
- This includes deprecated in v3.5.0 classes
- BunyipsLib removal of v3.5.0 deprecations
- Previously deprecated methods have been removed, which include
BunyipsOpModemethods such asaddTelemetry(),log(), and other telemetry-related methods.- To access telemetry, use the standard
telemetryobject which integrates as aDualTelemetryobject. All methods that were removed fromBunyipsOpModeis equivalently available through thetelemetryobject
- To access telemetry, use the standard
DualTelemetry.removeRetained()(alias forremove()) has been removedScheduler.ConditionalTask.runDebounced()(alias forrunOnce()) has been removed
- Previously deprecated methods have been removed, which include
- The subsystem convention for
Taskexposure has been updated- All tasks exposed on
BunyipsSubsystems, including the built-in defaults now expose their tasks as part of an inner class with a public final field calledtasks - This was to separate tasks from standard operations instead of having tasks be intermixed between operations
- An example of the new system is the
HoldableActuator.homeTask()being refactored toHoldableActuator.tasks.home() - Future BunyipsLib subsystems will continue to follow this standard
- All tasks exposed on
- Examples directory removed
- To be replaced by the Wiki at https://github.com/Murray-Bridge-Bunyips/BunyipsLib/wiki
CameraTypeimplementation and classes removed- Camera intrinsics should be defined via the SDK's built-in tools, such as the teamwebcamcalibrations.xml file or by directly injecting camera intrinsics using the new construction patterns
- This extends to the
AprilTagprocessor, which is the primary use case for these intrinsics
RampingValue,RampingFunction,RampingSupplier, andDcMotorRampinghave all been compressed into a single interface for brevity- New interface name is
Ramping, and is the equivalent ofRampingFunctionwith implementations forRamping.Value,Ramping.Supplier, andRamping.DcMotor - The
setMaxDeltamethod has also been renamed tosetMaxRampingDelta Ramping.DcMotornow only extendsDcMotor, instead of extendingDcMotorEx
- New interface name is
- Vision systems updated to support multi-camera configurations
- This includes
Processornow carrying a copy of the camera dimensions, as multiple cameras may use different resolutions - Static camera dimensions now work based on a default value, unless defined by the user on construction of
Vision. These dimensions are carried with the Vision instance for all processors to carry a copy of these dimensions - To access camera dimensions from a processor, instead of accessing the static constant from
Vision, accessgetCameraDimensions(). Note that this will be null if this processor is not attached to a Vision instance (and therefore is not streaming on a camera so we can't get dimensions)
- This includes
addSubsystems()ofCommandBunyipsOpModeandAutonomousBunyipsOpModehas been removed- Subsystems are now implicitly registered through a static array, therefore if you construct a subsystem, it will be added automatically
- If you wish to use a special set of subsystems, you can opt to using the
useSubsystems()method
- Integrated methods for Field-Centric driving have been removed
- These systems were inconsistent between each drive in BunyipsLib, and have been removed
- Drive tasks such as
HolonomicDriveTaskallow for a supplier to indicate when field-centric drive should be enabled, which will continue to work by doing the calculations internally - Other implementations of field-centric drives are left as an exercise for the user
Tasksystem was reorganised for brevity- This includes the removal of abstract extensions of
Tasksuch as theNoTimeoutTask, where this can simply be done now by extendingTaskwith no timeout parameter - The
RobotTaskinterface was removed as this does not have usefulness with the evolvedTasksystem- Frequently this lead to classes that did support
RobotTaskto perform instance checks and cast toTask, where this degraded code cleanliness for no reason - Tasks now extend the built-in
Runnable, so previous implementations that usedRobotTaskonly now are represented by the default type of Runnable BunyipsOpModenow supports taking in aRunnableto use as the init-task which will run indefinitely during init unless it is aTaskthat has reported as finished
- Frequently this lead to classes that did support
- These reorganisations emphasise the idea that a
Taskis simply aRunnablewith a timeout and finish condition
- This includes the removal of abstract extensions of
- Task subsystem dependencies have been reorganised to use a method
onSubsystem()- This replaces the need for tasks to make both non-subsystem and subsystem dependant tasks, and now exists as a builder-like method
- Parameter argument orders remain consistent with the (subsystem, override) signature
- Tasks to run on subsystems should now be constructed like so:
new MyTask(...).onSubsystem(subsystem, false)instead of passing args directly into the constructor - Consequently, all BunyipsLib tasks have been simplified not to have dual (dependant/non-dependant) constructors
AprilTagPoseEstimatornow implementsRunnable, theupdate()method is nowrun()of Runnable- Major refactor of RoadRunner tuning processes
- RoadRunner tuning has been inconsistent since the initial addition of it into BunyipsLib
- This system is mixed with the new
RoadRunnerTuningOpModeclass, see below in Additions - All RoadRunner tuning OpModes themselves are now TriConsumers that can be run on demand, but it is recommended to
use the dynamic
RoadRunnerTuningOpMode - Old code that would extend these OpModes should resort to extending the singular
RoadRunnerTuningOpMode
- Removed
DEFAULT_TIMEOUTfield fromRoadRunnerinterface (UseTask.INFINITE_TIMEOUT)RoadRunnerTaskwill still continue to have a task timeout equal to the trajectory duration by default
- The
RoadRunnerinterface now consolidates mirrored poses when usingmakeTrajectory()- Pose refs that are mirrored now use a parameter on the constructor if this pose should be mirrored in a ref
- This was created as pose refs used in the constructor are often global pose estimates that should not be flipped
- Note that builders will not use a mirrored pose ref for the constructor argument to
makeTrajectory() - Review the documentation regarding these behaviours via the JavaDoc to ensure compatibility
- The
IMUOpsubsystem has been redesigned from the ground-up as aHardwareDevicereplacement- The new replacement is called
IMUEx - The old
IMUOpdid not serve much purpose as it would wrap values that could be obtained easily from the universal IMU - The new class now focuses on implementing the universal
IMUinterface to continually retrieve values and update public volatile fields - This can be integrated with subsystem-like integrations such as multithreading
IMUExnow comes with a Yaw Domain that can be set, to allow readings of heading to be in one of three modes:- Signed (default, -180 degrees to +180 degrees exclusive)
- Unsigned (0 degrees to 360 degrees exclusive)
- Unrestricted (-inf to +inf)
- Note these domains only apply to the public fields, the internal
IMUinterface methods that expect signed values will use signed values
- These field units are supplied as WPIUnits, to simplify unit conversion and to integrate nicely with other BunyipsLib components
IMUExalso implements theIMUUniversal Interface, so it can be used in place of other IMUs and hardware devices at the config level
- The new replacement is called
CartesianFieldCentricMecanumDrivehas been redesigned to not rely on another subsystem (oldIMUOp) and now takes in an instance of the universalIMU- Construction now should be as simple as passing in the IMU from HardwareMap
GetTriPositionContourTaskhas been renamed toGetDualSplitContourTaskwhich fundamentally restructures the idea of the task- Instead of assuming the conditions of where a camera is facing, the new refactored common task will now simply
report on which half of the camera the largest contour is (
Direction.LEFT,Direction.RIGHT, orDirection.ZERO) - A convenience method
getMappedPositionnow exists to provide the legacy functionality by mapping camera position reports to other directions (such as the assumption of position this task originally was for)
- Instead of assuming the conditions of where a camera is facing, the new refactored common task will now simply
report on which half of the camera the largest contour is (
- The RoadRunner localizers and coefficients have been renamed and refactored for brevity
- TwoWheelTrackingLocalizer has been renamed to
TwoWheelLocalizer - TwoWheelTrackingLocalzierCoefficients has been integrated into the inner class
TwoWheelLocalizer.Coefficients - ThreeWheelTrackingLocalizer has been renamed to
ThreeWheelLocalizer - ThreeWheelTrackingLocalzierCoefficients has been integrated into the inner class
ThreeWheelLocalizer.Coefficients
- TwoWheelTrackingLocalizer has been renamed to
HoldableActuator.tasks.runForhas been switched to (timeout, power) from (power, timeout) for consistency between other time-based methods throughout BunyipsLib- Gains for the WPILib-ported feedforward controllers have switched to getters instead of exposing public final fields
setPowers()ofMecanumDrivehas been standardised back tosetMotorPowers()(new override) as found in the wrapped instance and across all RoadRunner drives for consistency- Renamed
EncoderTicks.EncoderTickGeneratortoEncoderTicks.Generatorfor brevity - BunyipsLib RoadRunner drive constructors no longer take in instances of
voltageSensor, as these can be inferred internally like howDualTelemetryis internally injected- These constructors are now more concise than they used to be
- Tank RoadRunner drives now no longer conform to the 4-wheel only specification and now support the intended list of
left and right motors
- This was an oversight that was present in the
SampleTankDriveof the RoadRunner quickstart, but was incorrectly implemented - Any 2+ tank wheel configuration can now be used with these tank drives
- This was an oversight that was present in the
- Removed
GetSignalTaskfor being too specific and useless in the scope of BunyipsLib NullSafety.assertComponentArgs()constructor has changed instead of accepting classes it will accept a component name, a class name to exclude, and the objects to check, which can now distinguish between differently named subsystems (experimental, actual uses of this util are provided by the integrated subsystem assertions on construction)- Switched to using WPIUnits for the
Whileclass timeout - Standardise names for abstract OpMode extensions, renaming the following classes
- ColourTuner to
ColourTunerOpMode - PathRecorder to
PathRecorderOpMode - New
RoadRunnerTuningOpMode - These names match abstract OpMode conventions, such as BunyipsOpMode, AutonomousBunyipsOpMode, CommandBasedBunyipsOpMode, etc.
- ColourTuner to
RoadRunnerbase drives now replace the (optional) instances ofBunyipsOpModeforDualTelemetry- This is still a nullable field, and new constructors exist that omit this term if desired
- The telemetry fields are simply for dashboard reporting of robot position, so the original implementation using
BunyipsOpModewas not required
AprilTagDatahas been updated, usingOptionalinstances for ftcPose, metadata, and rawPose- These fields collapse the previous x, y, and other nullable coordinates for an AprilTag detection, as null checks were tedious
AprilTagDatanow integrates the data classes from the FTC SDK itself as part of this data class, instead of unpacking them as previously done- Utility method
isInLibrary()will check for null against these optional instances now, as they will only be present if they are in the AprilTag library attached to the AprilTag processor
UserSelectionnow is aBunyipsComponent, and therefore no longer needs BunyipsOpMode injection (a legacy BunyipsLib paradigm)- This was a late migration after the static OpMode singleton, and is now reflected in
UserSelectionfor consistency - The constructor parameters have therefore been reduced from 3 to 2, the
thisparameter is not required
- This was a late migration after the static OpMode singleton, and is now reflected in
unitPose,unitVecandmirrorare now static methods of theRoadRunnerinterfaceRoadRunnerDrivenow defines vararg-length getMotorPowers() and setMotorPowers() methods, where previously these overrides would be implemented at a per-class basis- This makes RoadRunner drives more consistent with their interfaces
Storage.memory().unusableComponentsis now aHashSetrather than aList
DualTelemetrynow smartly parses telemetry captions based on the presence of an automatic separator string- Instead of telemetry objects getting stuck as DS001 etc, if the messages are formatted correctly they will be added and updated as their own items
- The default automatic dashboard caption value separator is
: - BunyipsLib telemetry already follows the
Caption: Valueformat, meaning FtcDashboard telemetry should be more organised and should be easier to graph and log - The pre-existing caption value separator methods have been revamped to change and get this separator, as well as the public property
- This separator does not impact the real telemetry caption value separator, which should be an empty string with
DualTelemetry
- Undeprecated
DualTelemetry.addDatamethods to instead work similar toadd()but with using the automatic separator string as mentioned above to ensure separation - Improved
HoldableActuatorhoming task to check for the bottom limit switch before starting the task Processorfor Vision can now be delegated, useful for composite processors that recursively use processors internally- All subsystems now have a
nameproperty, as many subsystems would internally reference a name property- The name property is protected to match the legacy implementations of the name system
- Public access to get the name property is achieved via the
toString()call- The new
toVerboseString()method (similar toTask) will give the legacy extended behaviour when callingtoString()on a subsystem in previous versions
- The new
- Public access to set the name property is achieved via
withName()which will returnthis(matches common legacy implementations) - New method
isDefaultName()for checks between the default name (getClass().getSimpleName()) and a custom name
AprilTagPoseEstimatornow has a heading estimate mode, where heading information from the pose estimator will also be used as part of the pose estimateRoadRunnerTasknow only cancels the current trajectory on task finish if it has been interruptedAutonomousBunyipsOpModeaddTaskAtIndexwill no longer throw an exception if the index is greater than the task list size- The task will be appended to the end of the task list instead
- Negative indices will still throw an exception
AutonomousBunyipsOpModeandSchedulernow updates subsystems before executing tasks, allowing subsystems to have run at least once before accepting tasks- Debugging improvements through telemetry on subsystem disables and Logcat warnings for peculiar states
- The Inertial Measurement Unit is now nullable in all Mecanum RoadRunner drives
- This is because Three Wheel odometry does not rely on the IMU, therefore the proper null safety exists now and you can simply pass null into the parameter
- The Colour Tuner OpMode scalars can now be tuned via FtcDashboard (previously impossible as it would override scalar
values)
- This is accomplished by changing the scalars of the ColourTunerOpMode object in the dashboard
CartesianMecanumDrivenow auto-sets the motors toZeroPowerBehavior.BRAKEon constructionRunForTaskcan now take in an extra argument for a callback to run after the task is completed- Normalised all constructors that take in an instance of
DcMotorExto take inDcMotorinstead and upcast internally ThreeWheelLocalizerconstructor has been given more overloads to be more brief in specifying last known positions- Multi-threading methods exposed in the
Threadsutility have been improved to provide better logging and more method overloads - The formulae used in
EncoderTickshave been optimised to reduce approximation inaccuracy - Exception handling now extends to threads run via the
Threadsutility in the same way main thread exceptions would be logged to the DS and Logcat RobotConfiginit() method will now throw an exception if called more than once, asHardwareMapcalls are expensive and not required more than once- Changed init-phase telemetry fault error messages to be more explanative
- Added improved robot safety features, primarily with RoadRunner drives
- A watchdog now observes all BunyipsLib RoadRunner drive instances and auto-locks them if they have not had a call
to
update()recently - This watchdog timeout is a constant (
RoadRunner.DRIVE_UPDATE_SAFETY_TIMEOUT), set by default to 500ms DualTelemetrynow displays a red timer that overrides the yellow slow loop timer when the safety watchdog is in range of triggering- The drive subsystems are special in the regards that hardware can propagate outside of
update(), mostRoadRunnerDrivemethods propagating instantly on the hardware - This timeout is to ensure the subsystem is actually enabled before allowing calls to these methods, which has not been the case previously (a disabled subsystem should never respond to commands)
- The drive is also the most volatile subsystem, where loop times of >500ms could make the robot dangerously unresponsive
- A watchdog now observes all BunyipsLib RoadRunner drive instances and auto-locks them if they have not had a call
to
- Fixed a buffer parse error in
Controllerrelated to the SDK gamepad; the controller should now natively copy over the gamepad ID and other state without unexpected behaviour - The
RoadRunnerDrivestop()method implementations now cancel trajectories as well AlignToContourTask,MoveToContourTaskandAlignToAprilTagTasknow do not end their Autonomous tasks unless they have seen a contour/AprilTag first- Fixed a rotation matrix flaw in
AprilTagPoseEstimatorwhere tags that were not 90 degrees offset to the field did not rotate the robot with the tag - Fixed a bug where RoadRunner pose data was not being transferred between OpModes due to switching localizers clearing pose data
- Improve race condition telemetry of
UserSelection - Fixed a telemetry bug where the target and current positions of
HoldableActuatorin AUTO mode were flipped - FtcDashboard now uses full size tags for logging improvement
MecanumDrivenow lets you access MecanumCoefficients attached to the drive viagetCoefficients()BunyipsOpModenow early returns if a stop was requested on initialisation- Improve
Cartesianutility class docs from being confusing - RoadRunner drives now properly switch the drive mode when using Velocity PID when it needs it and when it doesn't
- Fixed a bug in
DualTelemetrywheresetValuecalls to aHtmlItemwould not build the reference but the value - Fixed a potential runaway motor when
HoldableActuatorsubsystems were disabled - Fixed a double reference
get()error in theDualTelemetryupdate method for log messages RobotConfignow error handles theonRuntime()method forBunyipsOpMode- Fixed a bug where
NullSafety.assertComponentArgs()would never return false - Fixed a bug where an exception could be thrown during the init-phase although guarded by
assertParamsNotNull()internally
- The
Motorclass, an abstraction around the DC motor that is a drop-in replacement to the SDK approach forRUN_USING_ENCODERandRUN_TO_POSITIONmodes- The
Motorclass extends theDcMotorEximplementation, wrapping a motor entirely and can be obtained directly fromRobotConfig - This wrapper allows you to set your own
SystemControllers to use forRUN_USING_ENCODERandRUN_TO_POSITION, which will be updated and applied on everysetPowercall to your motor - This bypasses the SDK and allows you to run your own custom PID which is orders of magnitude faster to run via this class
- In the SDK, the built-in modes only run at 20Hz, which is a major limitation that makes the controllers sluggish
Motoris designed to be downcasted toDcMotorin any implementation while still providing abstraction over the system controllers- This class functions as close as possible to the original DcMotor, where the operation of this class is the same
as how it would be done with a stock
DcMotor. Migration should be near instant. - These system controllers have built-in gain scheduling support, using an
InterpolatedLookupTableto schedule gains based on internal encoder positions while interpolating between known gain setpoints - The actual commanded mode of motors running in this class is set to
RUN_WITHOUT_ENCODER, but the internal and exposed mode will be managed internally byMotor, allowing maximum speed and accuracy from your system controllers - Additional features allow configurations at the motor level, including max power and faster encoder resets
- Review the new documentation about this wrapper for the full capabilities of what this class can do
- The
- Alongside
Motor, theSystemControllerandPIDFinterfaces has been added to provide common ground for a system control algorithm such as PID or feedforward- This interface is implemented across all system controllers and can be used to manage coefficients without necessarily knowing about the controller underneath
- New
ArmControllersystem controller, which internally composes a PID controller and the WPILibArmFeedforwardto provide robust controls for arms suspended on beams at angles - New
PIDFFControllersystem controller, which internally composes a PID controller and the WPILibSimpleMotorFeedforward - New
HolonomicVectorDriveTask, a variant of theHolonomicDriveTaskthat will use pose locking to improve TeleOp capability- This task will take a snapshot of the current position after a short duration when the user input translation or rotation components are released
- The task will automatically use PID controllers defined by you to hold that current position snapshot and resist forces
- Note that this will not solve issues such as translational drift, there are other solutions to this issue, although it will attempt to tackle rotational drift
- This system can be comparable to one of a drone, where releasing the sticks and allowing it to hover will hold position and resist external forces
- You may also choose to set your own locking positions that will cause the robot to move to that position in
real-time
- This is most useful with heading, for example, allowing you to bind a button to rotate towards the front of the field or to lock rotation forwards
TelemetryMenu, which is a component that allows you to construct gamepad-interactable menus through any telemetry receiver (extracted from SDK v9.2, creator OpenFTC)RoadRunnerTuningOpModeabstract class, which uses aTelemetryMenuto provide dynamic selection of tuning mode at runtimegamepad1will be used to select which tuning routine from the v0.5 RoadRunner tuning process to use- This makes having to rebuild the code not required in order to perform multiple RoadRunner tuning tests, which dramatically decreases tuning time from waiting
- To use this, extend
RoadRunnerTuningOpModeand supply a baseRoadRunnerDrive - Once annotated with
@TeleOpand run, the telemetry will provide a menu to pick a tuning OpMode - FtcDashboard tuning adjustments have been neatly compacted under the
RoadRunnerTuningOpModetab and in their own sub-branches - All RoadRunner tuning OpModes have improved their declaration of units to FtcDashboard
IntrinsicMecanumLocalizerRoadRunner localizer, which is an emergency time-drive equivalent localizer that guesses the position of a Mecanum-drive robot based on the power supplied to the wheels- This is useful for an emergency situation where no other localizers will work (including the default)
- The coefficients for this localizer must be tuned empirically
SwitchableLocalizerRoadRunner localizer, which is a composite localizer that allows for dynamic switching between two localizers via self-test tasks or by the static field attached to the class- This allows for testing of deadwheels to be performed before an OpMode, allowing you to switch to a backup if desired through automatic or manual testing via telemetry
- RoadRunner drive classes now have
useFallbackLocalizermethods for mentioning which fallback localizer should be used with this drive, returning the SwitchableLocalizer instance for you to run a test task - SwitchableLocalizer is not a subsystem, but exposes tasks via the BunyipsSubsystem convention (
taskspublic field)
BlinkinLightssubsystem, which is a subsystem for the REV Blinkin Lights LED driver- Integrates with the
Tasksystem to queue lighting effects for durations
- Integrates with the
Processorhas new virtual methodsonAttach()andonRunning()for processors to hook these Vision eventsSwitchableVisionSendernow supports streaming across cameras, adjustable with the static index to mention which vision instance to use. Note that this index will only work if the instance itself has calledstartPreview(). Methods such assetPreview()will auto-set the index to the current vision instance, therefore not breaking old use cases ofSwitchableVisionSender- The Dokka documentation tool is now used with BunyipsLib. All clones of BunyipsLib can access the HTML docs in the
docs/ directory, or they may be accessed at our link https://murray-bridge-bunyips.github.io/BunyipsLib/
- Alongside Dokka, BunyipsLib has had a documentation update and all JavaDoc/KDoc should be more robust compared to previous versions
- This includes
@sincedeclarations that will exist on all BunyipsLib classes,v1.0.0-preindicating that this class was originally implemented before BunyipsLib had a semver - More debug logging has been added to Logcat for various components throughout BunyipsLib
- A GitHub wiki will contribute to where example code and information will exist for BunyipsLib hereon, alongside JavaDoc
- New
DynamicTask, which is a task wrapper that will construct an inner task when the wrapper begins running (runtime construction)- This is the equivalent of the WPILib
DeferredCommand - Useful for tasks that can only be evaluated when the OpMode starts, such as pre-game vision tracking
- This is the equivalent of the WPILib
- Subsystems are now constructed with implicit registration, you can access all currently constructed subsystems via
static
BunyipsSubsystem.getInstances(), or you can conveniently update all constructed subsystem throughBunyipsSubsystem.updateAll() Storagehas a new memory fieldlastKnownAlliance, which is set either by the user or automatically via aUserSelectioninstance that uses values inStartingPositions- As there are many fields within BunyipsLib that are static,
Storageprovides a static methodresetAllStaticFieldsForOpMode()for non-BunyipsOpModes to reset fields. This is done automatically in BunyipsOpMode. Tasksutility which is a utility to runTaskinstances through a iterative lifecycle- This util was created as many of BunyipsLib core subsystem features are now tasks, and this utility bridges the gap to allow iterative (non-command-based) OpModes to run tasks
- Read the docs for more information on how to use this class
AprilTaghas alternate constructors which allow you to add custom builder instructions from user code, rather than relying on the BunyipsLib defaults onlyAprilTagPoseEstimatorhas asetCameraOffset()method, where you can set a robot-to-camera offset that will be used to further the accuracy of the AprilTag pose estimator- New
Taskvirtual methodonInterrupt()which will be called if the task is finished but the finish condition has not been met (e.g. ended viafinish()orfinishNow()) - New Reset Last Known Positions built-in OpMode that will reset the last known Storage Memory values for last known pose and alliance
RoadRunnertrajectory task buildersetScale()method, which will multiplicatively scale distances in further builder instructionsRoadRunnerunitPoseandunitVecmethods now have scalar multiplier overload parameters to mention a multiplier for the original inches- New
noTimeoutsReference type is exposed on theRoadRunnerinterface to not set the future builtRoadRunnerTasktimeouts to the end of the trajectory time Exceptionsnow has a utility methodrunUserMethodwhich is used internally to execute volatile user methods with exception catchingRoadRunnerhas a new builder parametersetRefMirroring()which can toggle the state of pose ref mirroring (which is similar to the new implementation of how a builder parameter will set mirroring for the constructor parameter)- Two and three-wheel localizers now have an X encoder multiplier and Y encoder multiplier that can be empirically tuned
to increase accuracy
- These multipliers are in the RoadRunner quickstart but didn't make it into BunyipsLib until now
DriveConstantshas a new RoadRunner constant for admissible error and timeout viasetAdmissibleError- This directly connects to the PIDVA controller used when working with trajectory following, and can be adjusted to your liking
- The default parameters are usually sufficient and do not need any method calls to use
- This can be paired with the
noTimeoutsRoadRunnerfield for tasks
- Subsystems can now be run asynchronously via
startThreadandstopThread- These are experimental options that allow you to run this subsystem on another thread, but take due care as hardware calls on other threads are dangerous and looked down upon in FTC
- In any case, if you do choose to multithread, the created threads will be managed by the
Threadsutility
Encoderclass, which can be used to represent an encoder with built-in support for velocity overflow correction and acceleration calculations- This class is used internally by
Motor
- This class is used internally by
TriConsumerinterface, which is theBiConsumerbut with three arguments (used internally for RoadRunner tuning modes)EncoderTicksnow has methods for retrieving motor angular/translational velocity and acceleration (accel inMotorclass only) via theEncoderTicks.GeneratorCartesianutility class now has arotate()method to allow simpler application of rotation matrices- RoadRunner has this built-in to
Vector2dviarotated()
- RoadRunner has this built-in to
Controlsnow allows the creation of robot/Cartesian vectors as well as poses- Tracking wheel localizer coefficients now have a
setOverflowCompensation()method to set whether their encoders should be using velocity overflow correction- This makes overflow compensation options interpret at a config-level instead of needing to define them at the OpMode-level
CartesianMecanumDrivenow has asetMode()method to set the mode of all motors on the driveInterpolatedLookupTablenow has error-safety methods such astestOutOfRangeand clamped outputs withgetMin()andgetMax()- This lookup table will now throw OutOfRangeExceptions if
get()is called with a value outside of the function domain - The lookup table also now has early catches for null references on tables that are not built yet, which will not auto-build but alert the user more elegantly
- This lookup table will now throw OutOfRangeExceptions if
BunyipsSubsystemnow has anisDisabled()boolean check method to allow users to see if a subsystem is currently disabled
Migration to SDK v9.2, integration of new external control systems, some bug fixes and stability improvements.
- New deprecations which will be removed alongside SDK v10.0, including Tensorflow Object Detection
TFODandGetWhitePixelTaskwill be archived in the major release where SDK v10.0 is adopted- As for other CENTERSTAGE-specific tasks, they will remain in BunyipsLib under the
centerstagepackages where appropriate - In the BunyipsLib major release where SDK v10.0 is adopted, all other deprecated features throughout BunyipsLib will also be removed
- For now, these features will continue to work as expected and expected removals have been marked as deprecated
- This may include other changes to the Vision system to adopt full multi-camera support (#29), as it is only partially implemented at the moment
VisionTesthas been removed of TFOD
- Added a Recommended SDK Version to the build process, which will be checked at runtime to ensure the currently used
SDK version is the recommended version
- This is to ensure maximum compatibility with the BunyipsLib codebase, as this version is the one that has been tested and confirmed to work
- This will not prevent the user from running OpModes, but will log a robot warning message to the Driver Station
telemetry and to Logcat at the start of any
BunyipsOpMode - The recommended version has been set to v9.2, which as of this release is the latest SDK version
VisionTesthas changed which processors that can be tested, and now has options ofRAW,APRILTAG, and the four CENTERSTAGE pixels
- Fixed broken implementations throughout
RoadRunnerwhere the method overloads were not being reflected properly- This was due to not implementing correct methods from the
TrajectorySequenceBuilderinterface - waitFor() has been given an additional overload to match the scheme of (magnitude, unit) for RoadRunner task building
- This was due to not implementing correct methods from the
- Fix a misparse of the
Controllergamepad to match what does SDK does- This may have caused issues where unmanaged gamepad inputs did not work as expected as the buffer was not being wrapped properly
- New control system utilities from WPILib have been ported to BunyipsLib
- This includes the
TrapezoidProfile,ArmFeedforward,ElevatorFeedforward,SimpleMotorFeedforward, andProfiledPIDControllerclasses - Documentation on using these utilities can be sourced from WPILib/FTCLib, as these classes are in line with these counterparts
ArmFeedforwardhas been updated to use WPIUnits for the calculation method, to interop with theEncoderTicksclass
- This includes the
Improved exception handling and edge case fixes.
- The
toString()method ofTaskhas been made final and documentation updated appropriately- In order to change the name of a task, the
withName()method should be used - As this is a non-user-facing change, it is not enough to warrant a major version bump
- Users who have overridden the
toString()method in their tasks will need to change this to use thewithName()method
- In order to change the name of a task, the
dynamic_initis now in a while loop as opposed to a do-while loop, ensuring an early exit is respected before running more initialisation code
- Improved error catching with the
initTask, where exceptions during the onFinish() method would cause a full crash BunyipsOpModenow takes in aRobotTaskinstead of aTaskinsetInitTask(...)- This was the intended behaviour, as it supported using a minimal interface to begin with
Minor visual changes.
- Robot Controller blink pattern updated
- Replaced the READY state (solid green) with a blinking green-cyan (similar to
dynamic_init) pattern, this is because the READY state was too similar to the default state of the Robot Controller
- Replaced the READY state (solid green) with a blinking green-cyan (similar to
DualTelemetry'sopModeStatuscan now be set to empty values- The overhead status will now update more uniformly when the status is empty
- Fixed mismatched HTML tags in
BunyipsOpMode
Vision related updates and functionality optimisations.
- Changing
loopSpeedofBunyipsOpModewill now log a warning message to Logcat to inform the user of this change- The display of the loop speed in the Driver Station telemetry will also additionally turn yellow if this target speed cannot be achieved due to too slow of a loop speed
- Removed/fixed/mitigated all TODOs in the BunyipsLib codebase
AutonomousBunyipsOpModenow has thedisableHardwareStopOnFinish()method, which will turn off the automatic hardware halt protection when all tasks are completed- This is useful to disable if you wish to keep a motor running after the BunyipsOpMode activeLoop is finished
- By default, this safety feature is and has been enabled throughout all
AutonomousBunyipsOpModes
- Fixed faulty constructors of
AlignToContourTaskandMoveToContourTaskwhere they were using typeMultiColourThresholdinstead ofProcessor<ContourData- This made it so these tasks could only be used with a MultiColourThreshold, which was not the intended behaviour
- The constructors now take a
Processor<ContourData>instead, which allows for any contour processor to be used - Old implementations will still work as the
MultiColourThresholdis aProcessor<ContourData>
ColourTuner, a utility OpMode that can be extended to tune a variety of colour-based vision processors- This allows the lower and upper bounds of a
ColourThresholdto be tuned in real-time via controller input, and the processed image to be displayed on FtcDashboard - Consequently, the
colourSpaceof allColourThresholdclasses has been exposed as a public final field- A utility attached to the
ColourSpaceis now able to determine the channel name (e.g Red, Green, Blue) of a given scalar - These functions are used in the
ColourTunerto display the channel name of the scalar being tuned
- A utility attached to the
- This allows the lower and upper bounds of a
- A new universal OpMode, "Reset Robot Controller Lights" has been added and inserted next to the FtcDashboard
enable/disable OpMode
- As BunyipsOpMode will change the RC lights and not be able to change them back when the OpMode is stopped (as OpModes cannot access LynxModules when stopped), this OpMode will reset the lights to their default state
- This OpMode is useful for resetting the lights after a BunyipsOpMode has run, as the lights will remain in their last state, therefore resetting will inform others the robot is disabled
- Integrated/test OpModes, including this one, have been moved from the
testpackage to theintegratedpackage
DualTelemetryhas an alias method for adding a newline to telemetry,addNewLine()HtmlItemofDualTelemetrynow has a builder parameter that can take in aBooleanSupplierto determine if the item should have styles applied to it- Note that these styles only apply to the ones attached to the
HtmlItemitself, and not the text inside the item - This is useful for selectors that may want to apply styles to the item based on a condition
- Note that these styles only apply to the ones attached to the
Text.formatStringhas an alias methodText.formatfor convenience
General bug fixes and utility improvements.
- The
OpModeAnnotationProcessorhas been removed, as it does not impact any BunyipsLib code- This processor is used when making OpModes in the BunyipsLib project, however all OpModes that should have this checking enabled shouldn't be in the BunyipsLib project
- The implementation of it in the past for BunyipsLib was also bugged and did not work anyways, and as such has been removed
Referenceis now avolatilefield- Methods that rely on the snapshot of this field will be taken as a read on function call
HoldableActuatornow has a maximum timeout (default 5s enabled) for thehomeTask()- Ensure to call
disableHomingTimeout()or increase the timeout if the actuator takes longer than 5s to home - As such, the
homeTask()now returns an instance of Task rather than NoTimeoutTask
- Ensure to call
AprilTagPoseEstimatornow has asetActive(boolean)method to enable or disable the estimator- By setting this to false, no vision data will be processed and the pose will not be updated
AutonomousBunyipsOpModenow exposes aaddTask(Runnable, String)method to add a task with a custom name- This is useful for adding RunTasks that you want to give a name for, without needing to create a new RunTask explicitly
StartingPositionsexposes new methods for determining information about a certain starting positionisRed()andisBlue()to check if the starting position is on the red or blue allianceisLeft()andisRight()to check if the starting position is on the left or right side of the field- These results are lazy-loaded and cached for future use, as with the
getVector()method
DriveToPoseTasknow haswithMaxForwardSpeed(...),withMaxStrafeSpeed(...), andwithMaxTurnSpeed(...)methods to set the maximum speed ranges for the task- These speeds will be used to clamp the output of the PID controllers to ensure the robot does not exceed these speeds
- This is similar to how
MoveToAprilTagTaskwork, allowing smoother and more controlled motion - By default, these are set to
1.0.
- Fixed a critical
RoadRunnerbug where the implicit drive pose was not discarded properly- This was due to a cached result being used after the pose info was discarded
- Implicit pose construction should now work as expected
- Motor power is explicitly set to zero in the
HoldableActuatordeltaTask(...)andgotoTask(...)when the task is initialised- This seems to fix a bug where the motor controller ignores further power instructions and has the actuator moving at undefined speeds
- The update cycle will set the power to the correct value, as intended to conform to power clamping
RoadRunnerTasknow actually sets the task timeout to the trajectory duration (if not explicitly set) and assigns the task to the subsystem- Previously, this would only work for
Trajectoryobjects, and notTrajectorySequenceobjects due to a missing implementation
- Previously, this would only work for
DualTelemetrymethods for removing objects from telemetry now work to support HtmlItems- Previously, the DS would not be able to find these objects as they were not the appropriates instances
- HtmlItems now expose a
getItem()method to get the actual telemetry item that is wrapped - The remove methods will try to unwrap these items automatically from an HtmlItem, so the user does not need to manually unwrap them
AprilTagPoseEstimatorno longer checks for the processor to be active when instantiated- This was an oversight as the processor should simply not set poses if it is not active, and has been updated accordingly
- This is to allow for the processor to be enabled or disabled at runtime which will impact if the pose estimator is run
- The
update()method of the pose estimator now checks if the processor is active(attached+running) before updating the pose, and no-ops if it is not active (rather than emergency stopping on init and only checking once)
DriveToPoseTasknow calculates twists properly- Before the error was fed twice into the PID controllers, which worked but was not the intended behaviour and could pose some unexpected results
- The new calculation works as expected and should not change any previous implementations
RoadRunner pose interpretation restructuring for improved global pose estimation and trajectory handling.
- While this is a minor version release, it changes how trajectories from the
RoadRunnerinterface are parsed- This was due to a bug where poses would be discarded and global reference frames were impossible, and minor tweaks have been made to the RoadRunner interface
- All RoadRunner trajectories built with
RoadRunnerno longer set the pose estimate to the start pose of the trajectory- This is to allow for global reference frames to be used, and to allow for the pose estimate to be set to the start pose of the trajectory
- This is a breaking change for any code that relied on this pose estimate, and code will likely need to be re-tested
- This change was made to allow for more flexibility in the RoadRunner interface, and to allow for more accurate pose estimates
RoadRunnerno longer discards the last known pose when implicitly making a trajectory in the presence of an existing pose estimate- This allows users to call
.setPose()without having their estimates reset by the implicit discarding rule
- This allows users to call
runSequenceofRoadRunner'smakeTrajectorynow has an optional second parameter if the current pose should be set to the start pose of the trajectory- This is useful for when you want to set the pose estimate to the start pose of the trajectory, but not always
- The reason this is now optional as these pose calls will be called at initialisation, rather than at runtime, and providing the option gives more flexibility
- This will not change any previous
runSequenceimplementations
RoadRunnerTasknow sets the default task name to include the start and end trajectory poses in inch/rad format
RoadRunnernow has new methodssetPose(...)for setting the current pose of the robot in the RoadRunner drive quickly and with custom unitsunitVec(...)andunitPose(...)for creating custom unit vectors and poses (likePose2dandVector2d) with WPIUnits
StartingPositionsnow exposes aposeinstead of avectorfor the starting positions- These poses face inwards to the field, and can be rotated by adding with
.plus()calls - The old
vectorfield is still exposed for continuity, which simply callspose.vec()internally, and will not break any previous code
- These poses face inwards to the field, and can be rotated by adding with
Drive To Pose task and some minor bug fixes.
- Added more try-catch blocks in
AutonomousBunyipsOpModeandCommandBasedBunyipsOpModewhen calling back user functions- Before, if an exception was thrown, additional code that needed to be run as part of the natural lifecycle of these OpMode variants would not be executed
- OpModes should now be more exception resilient
BunyipsOpModenow manually clears bulk cache data from the hardware- Cache is automatically cleared once per activeLoop or initLoop, and the bulk read is called at the start of the loop
- This does not change any functionality, but is a performance improvement where hardware will not call multiple bulk reads in a single loop
- Robot Controller lights in a
BunyipsOpModeflash in accordance with the OpMode state- SOLID CYAN: static_init
- FLASHING CYAN: dynamic_init
- SOLID GREEN: ready with no exceptions thrown
- SOLID YELLOW: an exception was thrown during static_init or dynamic_init, and was caught
- FLASHING GREEN: running
- SOLID WHITE/LIGHT GRAY: finished
- SOLID RED: an unhandled exception was thrown during the execution of BunyipsOpMode
- Note: Due to limitations on the FTC SDK, if the OpMode is stopped these lights will not update and remain as they were when the OpMode was stopped
Exceptionsclass is now more Java-friendly- The lambda function to log messages on an exception is now a
Consumer<String>, and is JVM static - This may break any custom implementations of
Exceptionsthat relied on the old(msg: String) -> UnitKFunction - This method also no longer handles the case of
throws InterruptedExceptionas realistically users won't need to handle this- The FTC SDK will still handle this exception, but it is not necessary to add it as a throws clause in Java code
- This does not change any previous functionality or API surface
- The lambda function to log messages on an exception is now a
- Modified all instances of
PIDControllerin BunyipsLib task construction to bePIDFControllers- Allows more flexibility in the construction of PID controllers, and allows for the use of feedforward gains
- PIDController extends PIDFController, and as such all previous PIDController implementations will still work
- Drive To Pose Task
- A RoadRunner-powered pose task that will drive the robot in a straight line to a target pose from the current estimated pose
- This task is different to a RoadRunner trajectory, as it will use PID and feedforward control to reach the pose
- Useful for dynamic "at runtime" pose alignment, where the pose estimate may have been updated externally
- An example of this is using the
AprilTagPoseEstimatorto update the pose of the robot, and then using theDriveToPoseTaskto ensure the robot is aligned properly with a target pose
- An example of this is using the
New methods, improvements, and features.
- New deprecations, these functions will continue to work but be marked as deprecated and are subject to removal in
future versions
runDebouncedofSchedulerhas been renamed torunOnce- Telemetry methods of
BunyipsOpModehave been deprecated in favour of the newDualTelemetrymethods (exposed through thetelemetryfield)- As a result,
BunyipsOpModenow exposes a field calledtwhich aliasestelemetryfor convenience and to solve a bug with Kotlin interop
- As a result,
HtmlItem's now report errors whenaddDatafunctions are called, as they are not supported
Storagewas revamped, moving all volatile memory items into the.memory()subclass
Cannon,SwitchandDualServosnow check if the open and fired states are configured the same, throwing an exception if they are- Task names throughout BunyipsLib have been updated to be more readable (e.g. "OpenServoTask" -> "Open:SIDE")
- All tasks as a default name try to represent what they are, including the
TaskGroupsby seeking the name of the tasks in the group
- All tasks as a default name try to represent what they are, including the
- Debugging telemetry has been improved
- Task group creation has been improved to show when created in
AutonmoousBunyipsOpModethrough thelogCreation()method CommandBasedBunyipsOpModewill try to describe what commands have been assigned to what subsystems and the binds to activate these commands
- Task group creation has been improved to show when created in
- The LynxModules in
BunyipsOpMode's are now controlled to blink and change colours in accordance with the OpMode state
- Fixed a bug where setting a default task was impossible when the subsystem was disabled, where it should be possible
- Removed an internal call to
update()inRoadRunnerTask, users will have to ensure subsystems are being updated properly RoadRunnernow constructs tasks properly to provide timeout information to the upper task- Improved
AutonomousBunyipsOpModeto busy-wait in the start phase of the OpMode for the UserSelection thread - Patch an FtcDashboard bug where telemetry was not working causing memory leaks
- Fixed a crash where
AutonomousBunyipsOpModewould crash if the user did not select an OpMode
BunyipsOpModehas aonActiveLoop(...)method, which adds functions (Runnables) to be called before theactiveLoop()- This is useful for any pre-loop operations that need to be performed before the main loop, or utilities that require a functional update
AprilTagPoseEstimatorfor RoadRunner drives, which will extract the pose from any Vision cameras that are attached to the robot- This will set the current pose of the RoadRunner drive pose to what the webcam sees, which allows for dynamic calibration and field awareness
- It is structured like a subsystem with an update method, but is not a subsystem and should be treated as a
utility, able to be updated in the
onActiveLoop()method
Storagehas been revamped to include static methods for accessing volatile memory and the filesystem- Gson is used to store and retrieve objects from the filesystem, storing any object that can be serialised in a simple HashMap that can be accessed by the user
CannonandSwitchnow haveisFired()andisOpen()(as well asisReset()methods) for polling the state of the servoDbghas astamp()method, which will log the current timestamp of a running BunyipsOpMode and user contextHoldableActuatornow supports a top limit switch, which will stop the actuator from moving if it reaches this upper bound- Configuration is performed similarly to the bottom switch, but by instead calling
withTopSwitch(...)
- Configuration is performed similarly to the bottom switch, but by instead calling
Schedulernow hasandIf()andorIf()methods to chain boolean expressions togetherBunyipsSubsystem's have virtual methodsonEnable()andonDisable()which are called when the subsystem is enabled or disabledonEnable()is called whenenable()is called, or on the first active loop of the subsystemonDisable()is called whendisable()is called, or whenassertParamsNotNull()auto-disables the subsystem
SchedulerhasgetAllocatedTasks()andgetManagedSubsystems()to retrieve the tasks and subsystems that are currently being managed by the schedulerTexthas aStringBuilderimplementation which internally usesformatString()to build a string- New ramping function providers
RampingSupplierandRampingValue- These are extensions of what
DcMotorRampingdoes, but can be used in other contexts for any values that need smooth damping
- These are extensions of what
BunyipsOpModehas a newloopSpeedfield, which can be set to a custom loop speed for the OpMode- This is useful for setting a custom target loop speed for the OpMode, which can be used to save CPU cycles
DualTelemetrynow displays the current time of when messages were logged in the telemetry log, if using a MovingAverageTimer- This behaviour is automatically enabled on
BunyipsOpMode, which uses thetimerfield to log the time of the message - Bracket colours of the telemetry log timestamp represent init and active phases
DualTelemetrynow exposes a logBracketColor field as a result
- This behaviour is automatically enabled on
DualTelemetryhas a loopSpeedSlowAlert field, which will change the colour of the loop time (if available) to yellow if the loop speed is slower than this valueBunyipsOpModeexposesrobotControllersas a method to get the LynxModule instances of the robot
Update BunyipsLib dependencies.
- Updated WPIUnits to the latest branch, which reworks the internal logic of unit construction
Tasknow extendsBunyipsComponentto retrieve theopModefield, instead of defining it again internally
- Units can now be divided by other units performing dimensional analysis, similar to the multiplication of units
- A few new units now exist, including a new base unit for moment of inertia and more integrated second-derivative
units (
FeetPerSecondPerSecond,RadiansPerSecondPerSecond, etc.)
Task timing and debugging telemetry improvements.
- Added an automatic
Dbgcall to run when theonReadycallback is processed, with a list of tasks added at this period- This is to provide a more detailed log of the tasks that are added up to the point of the
onReadycallback
- This is to provide a more detailed log of the tasks that are added up to the point of the
- Init-task now displays full verbose string into Logcat of when it starts running
- Renamed ACTIVE to READY in
Taskwhen calling a verbose string for clarity
- OnceTask has been updated to actually have a timeout of 1 millisecond as it was previously treated as infinite
- This allows telemetry to properly display the task as an instant task
- Fixed a bug in
RoadRunnerwhere the robot would not accept the implicit timeout construction of a trajectory- This resolves all RoadRunner trajectory tasks built with default parameters to be infinite
HTML-enhanced improved Driver Station and FtcDashboard telemetry.
Scheduler.addTaskReport()now takes an extra argument whether this task is a default task- This API was not designed to be used by the user, but rather by the
Schedulerto collect task and subsystem info - As such, this is a breaking change for any custom implementations of tasks/subsystems that may have used this method
- This is not enough to warrant a major version bump
- This API was not designed to be used by the user, but rather by the
DualTelemetrynow calls all setup methods from within its constructor- This removes the need to call
setup()after creating aDualTelemetryobject - This is a breaking change for any custom implementations of
DualTelemetry - However, since this is an internal developer change, it is not enough to warrant a major version bump
- This removes the need to call
UserSelectionno longer sets auto-clear to true for the init-phase- While this isn't an API change, it is a change in the default behaviour of
UserSelectionand may crash OpModes that relied on the auto-clear being active - You will need to ensure auto-clear is set yourself, as nowhere in BunyipsLib it is enabled automatically during the init-phase
- Auto-clear is disabled in the init phase, and re-enabled in the active phase
- Init tasks that report continuous telemetry should use a single added retained telemetry item and call
setValue()on it
- While this isn't an API change, it is a change in the default behaviour of
- Added colours and styles to telemetry messages in the Driver Station
- All standard telemetry items associated with the stock usage of BunyipsLib have been updated to be more vibrant and easier to read
- Information is now colour-coded based on importance, and size varying to indicate between debug and normal telemetry
StartingPositionsnow has a HTML generator when usingStartingPositions.use()to display the starting position in a more readable format, reducing confusion
UserSelection, when running will now flash at the user with vibrant colours to indicate an action is needed- This is to ensure the user is aware that they need to select an OpMode
- The message for the selected OpMode has also been moved to the log instead of telemetry to de-clutter the user telemetry space
- FtcDashboard will now display the selected OpMode status properly in a concise
USRkey, with time data of when it was selected relative to the start of init
AutonomousBunyipsOpModenow sends task finish messages to Logcat with time execution details- Exceptions are now shown more clearly in the Driver Station telemetry log
StartingPositions.use()now returns an Array instead of a List- This array is backed by the JVM as a
StartingPositions[]
- This array is backed by the JVM as a
- Telemetry messages have been improved throughout BunyipsLib
TaskandTaskGroupnow display their timeout information when added to theAutonomousBunyipsOpModetask queueTaskGroupis calculated by the maximum timeout of all tasks in the group, but may end early depending on the group's finish conditionTaskGrouplogs to the Driver Station as being added as a single task, but generates additional logs for each task in the group on construction
- Scheduler messages have been reduced in size and made more concise to be one line
AutonomousBunyipsOpModetask queue messages have been refined to reduce wordiness- Integrated subsystems now use colour to indicate their status in the Driver Station
RoadRunnerTasknow sets the task timeout of itself to the trajectory duration if the task timeout is not set- This is to ensure provide metrics on how long an Autonomous will take to complete as the task time should be the same as the trajectory time
BunyipsOpModenow slows down the loop during periods of idle execution to save CPU cycles- During the
readyphase, the loop is reduced to 5 iters/sec - During a
haltedstate, the loop is reduced to 10 iters/sec - During the
finishedstate, the loop is reduced to 2 iters/sec - All other phases continue to run at maximum available speed
- During the
BunyipsOpModewill no longer runactiveLoop()at least once if the OpMode is stopped before the first loop- This is to prevent actuating motors or doing any heavy work when we want to stop the robot
- This effectively has moved the activeLoop from a do-while to a while loop
- Other loop-based methods such as
onInitLoop()still use a do-while
DualTelemetrynow uses theFunc<T>constructor to pass data to the Driver Station telemetry- This does not change any functionality but allows the internal state to work properly, but may present potential issues with clearing telemetry if not aware
DualTelemetry'sremoveItemis no longer deprecated as it will callremoveRetainedinternally- The purpose of the deprecation was to discourage removing telemetry items that weren't retained, however to remove complication the method has been restored
- Fixed a critical bug in
AutonomousBunyipsOpModewhere an exception would be thrown for an OpMode that doesn't callsetOpModes()- Additionally,
onReady()will no longer be called if the OpMode is ended before the user selects an OpMode
- Additionally,
- Fixed a faulty debug statement in
BunyipsSubsystemwhen a subsystem is enabled viaenable(). - Exceptions thrown for
BunyipsSubsystem's default task ending now includes the class name - Improved no-subsystem operation of
CommandBasedBunyipsOpMode, where an exception will still be thrown however it will not stop the calling ofassignCommands()- We choose to throw an exception here as passing no subsystems shouldn't be a common use case of this command-based system
- This is to prevent the user from accidentally running a command-based system without any subsystems and therefore no motor output
- Various fixes for
DualTelemetry- FtcDashboard user packets should no longer be dropped
- Fixed a
ConcurrentModificationExceptioncaused by a missingsynchronizedcall on the dashboard items inupdate() - In order to let HTML modifications make their way to the dashboard, the internal structure of
DualTelemetryhas been reworked- Dashboard items are now a string by reference, which will be updated when the Driver Station evaluates the telemetry function
- FtcDashboard telemetry indexing has been vastly improved
- The telemetry is now indexed by type and accommodates for the alphabetical sorting of telemetry items
- This ensures the telemetry on the dashboard is as close to the DS as possible without any manual intervention
- Fixed a clearing bug for telemetry where items would be removed based on a clone instead of the original item
- Telemetry now uses HTML formatting to enhance the appearance of telemetry messages
- Allows customisation of telemetry messages, including bold, italic, underline, and colour
- New HTML text builder utility
Text.html()and built-in builder-like value wrappers for thetelemetry.add()method, (.bold(),.italic(), etc)- See
HtmlItemofDualTelemetryfor more information
- See
- These changes also apply to the FtcDashboard telemetry
- Manual tags can also be used, such as
<b>,<i>,<u>,<font color="red">, etc
AutonomousBunyipsOpModenow provides more concise data on the overhead display message- This includes the current task, current task index, and a new Estimated Time Remaining field
- The Estimated Time Remaining field is calculated by the sum of the timeouts of all tasks after the current task
- If the task is a
RoadRunnerTask, the time remaining will be calculated by the time remaining in the trajectory - However, if it is an infinite task, the time remaining will be calculated by adding an arbitrary amount of time as
defined by the static field in
AutonomousBunyipsOpMode - This is to provide more information to the driver on the current state of the autonomous program
DualTelemetrynow includes aoverheadSubtitle, which is a customisable text field that can be used to display additional information just under the main status- This is useful for displaying statistics similar to the standard
BunyipsOpModetiming and controller information
- This is useful for displaying statistics similar to the standard
DualTelemetrynow has anoverrideStatusfield, which allows the user to set the status message to a custom string- This will override the status message set by the
opModeStatusfield, and will be displayed in the same location - This field is used internally by
BunyipsOpModeto display 'error' if an exception is thrown
- This will override the status message set by the
Dbgnow includes newlogTmp()methods, which will log a message just likelog(), but is marked as deprecated- This is to ensure all temporary debug messages are removed before committing, as sometimes these log messages may be forgotten and hamper performance
Referencenow has new methodssetIfNotPresent()andsetIfPresent()- These methods are for setting the reference based on the nullability of the current reference
Minor bug fix for MoveToAprilTagTask.
- Fixed a missing constructor assignment in
MoveToAprilTagTask, where the targetTag was not being assigned to the class field- This caused the task to always search and lock onto any tag, essentially ignoring the targetTag parameter
New utilities, autonomous task allocation improvements, API surface simplification, and vision integrity improvements.
BunyipsOpMode's MovingAverageTimer has been reworked to be exposed as a public fieldtimer- This makes it so like the gamepads and telemetry, the MovingAverageTimer can be accessed in a similar fashion
getMovingAverageTimer()now is called withtimer
- Removed various encoder-related systems including
EncoderMotor,PivotMotor,ScopedEncoder- These systems span from the pre-RoadRunner era of BunyipsLib, where we would use this to measure deadwheel distance
- It has become far too tedious to maintain, as RoadRunner has deprecated these systems, however, we chose to continue maintaining them for other systems such as PivotMotor
- However, at their core, they simply convert the tick reading from the encoder into human units, and can be delegated to a utility to handle
- An appropriate util class
EncoderTickshas been implemented to accommodate the lost functionality from these utility classes - This promotes using motor objects only supplied by the SDK, where the intervention of their implementations should only be handled if core functionality is modified
- Removed
Rotatorand integrated these methods intoHoldableActuator- All
Rotators should now be exchangedHoldableActuators - All methods from
Rotatorthat were useful were transferred and reimplemented - Rotator was simply a HoldableActuator under the hood, and as HoldableActuator was changing to include newer features such as overcurrent and limit switches Rotator became outdated and code repetition was happening
- Like the encoder-related systems removed in the above change, Rotator simply converted encoder ticks to human units
- The methods available in
HoldableActuatorandEncoderTicksreplace whatRotatordid
- All
- AutonomousBunyipsOpMode
removeTaskIndexmethod has been renamed toremoveTaskAtIndexto match the new methodaddTaskAtIndex - Renamed
Scheduler'sfinishingWhentask allocation method tofinishingIf- This is to reduce confusion presented by
finishingWhenwhere it would be perceived as the task would only finish when this condition was met - Documentation has been updated to clarify that
finishingIfwill add an early-finish boolean expression to the task - The corresponding
inTimeFinishingWhenmethod has also been renamed toinTimeFinishingIf
- This is to reduce confusion presented by
- Removed useless generic parameters for various tasks, including
AlignToAprilTagTask,MoveToAprilTagTask,AlignToContourTask,MoveToContourTask, andHolonomicDriveTask- Construction of these tasks now do not have to mention generic parameters, which simply involves removing the
<>from instantiating these tasks - Parameters now pass in
BunyipsSubsystems, which will be typecasted to the proper drive systems
- Construction of these tasks now do not have to mention generic parameters, which simply involves removing the
- All methods in the
Limitclass now take instances ofRoadRunnerDriveto get an instance ofDriveConstants, after a bugfix related to static constraints- Instead of passing DriveConstants into Limit methods, you will now have to pass the entire drive
- This does not apply to the RoadRunner interface
atVelocityetc. methods
MovingAverageTimernow passes backMeasure<Time>instead ofdoublefor access methods- This also comes with a few timer methods being renamed, to include
loopTimeorloopfor clarity - Since we are now using WPIUnits, the
averageString()(nottoString()) method was removed as it was redundant - Previously, a time unit was passed into the main access methods and conversion was done on the spot
- However, this is not good practice and therefore all calls now return WPIUnits for the user to utilise, especially
in the new
timerfield
- This also comes with a few timer methods being renamed, to include
- Angular acceleration limits from
Limitwas removed, as they don't actually serve any purpose in RoadRunner, but instead are part of theturnConstraint- This type of angular limit never existed to begin with, and only applies to turn requests in RoadRunner
RoadRunnerinterface now no longer extendsRoadRunnerDriveInstanceas it has been removed- Any implementations that utilised
RoadRunnerDriveInstanceis a breaking change
- Any implementations that utilised
- Fix
AlignToAprilTagTaskwhere it was hardcoded to only look for the tag with id2- The constructor now passes in a targetTag integer, where if set to -1 it will search for any tag
SmoothDampofMathfhas been reworked to use WPIUnits and Reference for velocity storing, and has been tested to work properly- This officially integrates SmoothDamp into BunyipsLib, including the creation of
DcMotorDamping, however, the old array return was removed and the function was reworked - Any previous use of
Mathf.smoothDampwill need to be rewritten - SmoothDamp allows variables to be gradually incremented, effectively giving a "velocity" to a value that may be updated over time
- This officially integrates SmoothDamp into BunyipsLib, including the creation of
HoldableActuatordisplays more telemetry regarding revolutions per secondHoldableActuatornow has software bounding limits, much like the oldRotatorangle limitsHoldableActuatornow auto-cancels tasks if they move over the software bounding limitsHoldableActuatornow has minimum and maximum power clamps that will be applied to the motorGetTriPositionContourTasknow have a fallback timer, where it will reset toLEFTafter not seeing any of the appropriate contours for a set amount of time- Various nullability annotations added throughout the codebase to indicate null handling (
@Nullable,@NonNull) - Added telemetry of the currently detected
GetTriPositionContourTaskposition while the task is running - Patched
AlignToAprilTagTask's bearing unboxing nullability problem
- RoadRunner constraints were made default instead of static, which was a bug that applied Mecanum constraints to
non-Mecanum robots
- The non-Mecanum RoadRunner code has not been tested by our team due to time constraints, tread with care
- Fixed a missing parameter in a logd call in
BunyipsOpMode RobotConfigwill no longer swallowonSuccesscallback exceptions- Will be handled like a standard handled exception as DS messages were being suppressed from exceptions raised in the callback
- Switched
AlignToAprilTagTaskfrom using yaw to bearing, which was previously the incorrect unit
- MovingAverageTimer now has a
deltaTime()method, which will return the unfiltered raw duration since the lastupdate()- Useful in precise applications where you require the usage of instant precise loop timings
- New CENTERSTAGE-specific
SpikeMarkBackdropIdutility undervision/processors/centerstage, which given a spike mark direction and starting position will return the tag ID of the backboard location for bonus points DcMotorRampingmotor wrapper, which will apply aMathf.smoothDampon thesetPower()method- This allows motors to be ramped up and down smoothly, and includes additional methods to configure and override this behaviour
RobotConfigwill try to automatically instantiate this based on thegetHardware()class parameter as well- As such, DcMotorRamping can be treated the exact same as a DcMotor in terms of creation, and goes in your config
- DcMotorRamping implements DcMotor, and can be down and upcasted as the only method overridden is
setPower()
EncoderTicksutility, which allows conversion between encoder ticks, angle, and distance using WPIUnits- AutonomousBunyipsOpMode
addTaskAtIndex, which allows the insertion of tasks at any given index in the task queue- While methods have been implemented to try and stop race conditions, it is recommended that any asynchronous operations with this method are minimised
- RoadRunner turnConstraint methods
setAngVelandsetAngAccel(and reset methods) which are applied when rotating the robot in place
Rotator exception patches and telemetry improvement.
- Fixed misuse of infinities with default lower and upper limits, replaced with
-Double.MAX_VALUEandDouble.MAX_VALUErespectively
- Hide infinite limits and replace with infinity symbols in telemetry for
Rotator
Improvement of various subsystems for RoadRunner and Autonomous operation.
- The
onReady(OpModeSelection)abstract method ofAutonomousBunyipsOpModehas been replaced with aReference<?>, and a second parameter of typeControlsexists for determining the button that was pressed during the init-phase whensetOpModes()is called- Instead of
protected void onReady(@Nullable OpModeSelection selectedOpMode) {}, new code usesprotected void onReady(@Nullable Reference<?> selectedOpMode, Controls selectedButton) {} OpModeSelectionhas been deleted, as it fundamentally serves the same as aReferenceand has more features to check nullabilityselectedOpModewill return null if the user did not select an OpMode when they had the option to, whilstselectedOpModewill return a null reference if there were no OpModes to select fromselectedButtonwill beControls.NONEuntil it is changed by the selection of an OpMode- See the
Referenceclass for utilising new methods to access objects passed back byUserSelection
- Instead of
- Removed unnecessary generic type from
RoadRunnerTask - Renamed
HoldableActuator'swithZeroHitThreshold(int)->withHomingZeroHits(int) - Renamed
GetTeamPropTask->GetTriPositionContourTask, and removed debugging statement (class still requires testing) - Removed
RedTeamProp- This class was too specific for BunyipsLib, and teams should implement their own team prop pipelines
- This is also why
GetTeamPropTaskwas renamed, as it applies to a general case
- Added a safeguard to
Taskwhere callingrun()on a finished task will no longer callperiodic()- Ensure your code does not rely on the ignoring of
pollFinished()
- Ensure your code does not rely on the ignoring of
setInitTask()ofAutonomousBunyipsOpModehas been raised toBunyipsOpMode- As a result,
BunyipsOpModewill handle running init-tasks, and don't have to be used solely in Autonomous. This is useful for running a task before starting TeleOp. - This does not change the API surface for AutonomousBunyipsOpMode
- As a result,
Storage.lastKnownPositionis now updated every update loop, instead of when the robot is stopped, increasing the accuracy of the last known robot pose.- Added ticks per second information to
HoldableActuator - Added telemetry to
TankDriveto matchMecanumDrive
- Fixed a race condition where the TelemetryPacket of
DualTelemetrywould be set to null- This may bring lost data that are attached to FtcDashboard packets. This will be monitored.
- Fixed a
Rotatorbug where the default "infinite" limit was usingDouble.MIN_VALUEinstead ofDouble.NEGATIVE_INFINITY, causing unexpected behaviour - Fixed telemetry in
RotatorandWaitTaskwhere WPIUnitstoString()methods were being called instead of rounding - Fixed an EncoderMotor bug where
holdCurrentPosition()wouldn't actually hold the current position when called repeatedly- Users now must call
resetHoldPosition()to set a new setpoint forholdCurrentPosition()to use, latching to ensure a single position is held
- Users now must call
- Trajectory mirroring now works properly, removing code that did not work from the RoadRunner interface
- RoadRunner trajectories can be mirrored with
.mirrorToRef(Reference<TrajectorySequence>)
- RoadRunner trajectories can be mirrored with
- Fixed flawed calculations of angle in
RoadRunnerTask, where the angle will now represent the angle the robot is to the end pose using trigonometry
- The RoadRunner interface now has new velocity and acceleration constraint creation methods
atVelocityandatAccelerationwhich integrate with WPIUnits HoldableActuatorHomeTask overcurrent detection algorithm based on an exceeding of current over a constant time value (for example if the current exceeds 4A for 1s straight, the HomeTask will end)- These methods are optional
- Added
Limitutility class for easy construction of velocity and acceleration constraints using WPIUnits (internally used by the RoadRunner interface) - UserSelection now exposes
selectedButtonfield (used in theonReady()callback of ABOM) - Added new
require(),ifPresent(Consumer),ifNotPresent(Runnable),ifPresentOrElse(Consumer, Runnable),getOrElse(V)methods toReference
Initial release and first semantic version of BunyipsLib.
BunyipsLib is a comprehensive robotics library tailored for FTC teams, providing a suite of development tools for
efficient robot code creation, including modules for error handling, dynamic device initialization, and integrated
systems like RoadRunner, FtcDashboard, Vision, Command-based paradigms, and more. Designed for ease of use and
versatility, BunyipsLib aims to streamline the programming process for students of all skill levels, fostering rapid
development and code reusability across different robots.
- Previous versions of BunyipsLib were not following semantic versioning. This version is the first to do so.
- RoadRunner methods
addNewTrajectory(...),newTrajectory(...), andaddTrajectory(), have been removed and replaced withmakeTrajectory().- The new method is more flexible and culminates all task and trajectory creation into one method.
- To create new trajectories for ABOM, simply use
makeTrajectory()and calladdTask()to represent whatbuild()used to do - Alternatively, you can call
buildTask()to return a task object without adding it to the task list (for grouping or manual allocation). - To add pre-built trajectories as tasks, you may use
makeTrajectory().runSequence(), allowing you to have access to task properties before building.