Skip to content

Releases: Murray-Bridge-Bunyips/BunyipsLib

v6.1.1

13 Dec 12:30
7414282
Compare
Choose a tag to compare

v6.1.1 (2024-12-13)

PID systems refactoring and improvements.

Breaking changes

  • ProfiledPIDController now extends PIDController, delegating a lot of its methods over to the PIDFController
  • Renamed getPositionError() to getError() on PIDFController
  • Renamed getVelocityError() to getErrorDerivative() on PIDFController
  • For consistency, the setSetPoint and getSetPoint methods that spanned ProfiledPIDController and PIDFController are now simply setSetpoint and getSetpoint
    • To differentiate the double setpoint from the TrapezoidalProfile setpoint, the getSetPoint method still exists on ProfiledPIDController

Additions

  • PIDFController new methods and functionality
    • setClearIntegralOnNewSetpoint, which will erase the integration accumulation whenever the setpoint is changed
    • setIntegrationZone, also known as the IZone from WPILib, which sets a region around the error such that integration is enabled
    • enableContinuousInput, also from WPILib, which allows wrapping of PID outputs for continuous systems like angles
    • See the BunyipsLib wiki (IO section) for more information
  • PIDFController now uses a low-pass filter to smooth derivative readings
    • Comes with the setDerivativeSmoothingGain method, 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 PIDFController instances - set to Double.MIN_VALUE to disable or access/set the DEFAULT_DERIVATIVE_LP_GAIN field
  • New PIDFController getTotalError() method to accompany getError() and getErrorDerivative()

Non-breaking changes

  • 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
  • PIDFController now exposes the fields:
    • clearIOnNewSetpoint
    • minIClamp
    • maxIClamp
    • iZone
    • lowerClamp
    • and upperClamp
  • Various internal restructurings of PIDFController
  • reset() of PIDFController resets all errors now
  • The Filter.LowPass now exposes as a public final field the gain in use
  • Implementations of Filter.LowPass now have checks to stop reassignment on continuous set calls

v6.1.0

12 Dec 11:32
6211f23
Compare
Choose a tag to compare

v6.1.0 (2024-12-12)

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).

Breaking changes

  • The Task system has been altered to provide a richer API surface
    • Some task implementations, such as RunForTask, ContinuousTask, WaitUntilTask, and StartEndTask have been removed
    • The RunTask has been renamed to the Lambda, and the OnceTask has been merged into Lambda
    • The ForeverTask base has been removed, and instead all Task instances by default run forever (the requirement to override isTaskFinished and periodic is now optional)
    • The DynamicTask of old BunyipsLib was renamed to the DeferredTask
    • Several task bases, such as ActionTask, ConditionalTask, RepeatTask, SelectTask, are now elements of the bases package
    • To account for the missing classes, the new DynamicTask class 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 RunForTask previously 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 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
  • Additional changes were also made to methods such as pollFinished (now simply poll), and cleaning up constructors and methods to be more consistent
    • The withX methods (withName, withTimeout, onSubsystem etc) were removed in favour of the simpler versions such as named, timeout, on as it was confused with the with method which composes into a group and these methods were inconsistently named/had too many overloads
    • The timeout constructor has been removed and instead timeout can be accessed and set as a field on the task
    • hasDependency() replaced with simply using the Optional instance from getDependency().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
  • Exceptions.runUserMethod has flipped arguments from (Runnable, OpMode) to (OpMode, Runnable)
  • ProfiledServo has been renamed to ServoEx
  • API surface of MoveToContourTask has 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 withForwardErrorSupplier method (while removing withPitchTarget)
  • IndexedTable is 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 BunyipsOpMode initTask now only supports supersets of the Action interface, instead of Runnable
    • 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 full Task (Task implements Action internally so no changes are needed for already task-based init actions)
  • 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 NullSafety util class
    • Null safety is now performed at the class level for component assertions
  • Switch primary constructor has been updated for consistency
    • For all servo instances by default, 0 represents Closed, and 1 represents Open (applies to DualServos and now Switch)
    • 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
  • TaskBuilder for RoadRunner no longer takes in a parameter for calling subsystem on construction as it is handled at the task level
  • DualTelemetry now uses @JvmField for several properties, including:
    • opModeStatus
    • overrideStatus
    • overheadSubtitle
    • dashboardCaptionValueAutoSeparator
    • logBracketColor
    • loopSpeedSlowAlert

Bug fixes

  • The ActionTask (used internally by the TaskBuilder when 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)
  • TaskBuilder method .fresh() now internally calls .endTrajectory() to avoid odd unspliced behaviour using fresh() (upstream RR change)
  • IndexedTable set method 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().unusableComponents has been removed as a result
  • Patch SplineTest and ManualFeedbackTuner from doing nothing
    • The subsystem was not being updated internally causing the drive to do nothing in these tuners
  • Fix ProfiledServo instances 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
  • HoldableActuator subsystems 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 addFirst in AutonomousBunyipsOpMode would cause a stack overflow
    • This was due to a boolean flag representing an acknowledged callback being set too late, causing the internal call to addFirst to infinitely delegate the queue
  • Resolve concurrency problems with AutonomousBunyipsOpMode
    • Related to the pre and post-queues as they were not using thread-safe instances
  • The UserSelection field that shows on FtcDashboard is no longer small
  • CustomAccumulator register() method no longer throws an exception due to unsupported operations on an immutable list
  • Telemetry is no longer cleared when using a UserSelection on init, such as using setOpModes with AutonomousBunyipsOpMode
  • Patched UserSelection clearing telemetry on init when it shouldn't be
    • UserSelection now also no longer updates telemetry internally, as it should be handled by the main loop

Non-breaking changes and additions

  • build() and addTask() of TaskBuilder can now optionally take in a parameter of Reference<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)
  • BunyipsSubsystem now exposes static methods disableAll() and enableAll() to accompany updateAll() and the Scheduler methods of managing all subsystems
  • Adding of Measure overloads for Vel and Accel util classes
  • Added units FieldTilesPerSecond and FieldTilesPerSecondPerSecond to accompany FieldTiles
  • Various linting and improper docs updated
  • HoldableActuator withTolerance method now has an overload that invokes applyToMotor to true by default with one argument
  • SimpleRotator now exposes the underlying motor object under the actuator field
  • 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 NullSafety class
    • Exceptions ...
Read more

v6.0.0

21 Nov 04:34
c31db3f
Compare
Choose a tag to compare

v6.0.0 (2024-11-21)

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.

Changes

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.bunyipslib to au.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, Accumulator and Moveable interfaces
    • 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 the TaskBuilder
    • The drive subsystems now fully follow BunyipsLib convention for Task systems, where the RoadRunner Action is now just a superclass of Task
    • Some removed functionality for geometry classes in RoadRunner v1.0.0 is available as part of the Geometry util 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
  • PurePursuit has 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 MecanumGains object) 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
  • Scheduler has 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
  • SystemController is 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
  • Motor is now split into a SimpleRotator extension, to allow for CRServos to support motor caching techniques
  • addTask() and variants of AutonomousBunyipsOpMode has been replaced with add()
    • Other alias utilities including run(), defer(), and wait() (not of Object) now exist to accompany `add()
  • 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!

Bug fixes

  • getHardware() of RobotConfig now supports getting non-HardwareMap devices (such as the RawEncoder from RoadRunner)
  • HoldableActuator now sets the motor to BRAKE by default
  • Task.after() is no longer bugged in execution order (used to act like a then())
  • Fix a missing TurnTask overload
  • HoldableActuator no longer auto-resets the encoder on the arm on init as it discards known information
  • The target position of Motor is now stored locally instead of writing to the Lynx firmware
  • BoundedAccumulator (previously BoundedLocalization) now clamps velocity when a clamping operation is in progress
  • The AprilTagPoseEstimator has been reimplemented as the AprilTagRelocalizingAccumulator, with the bugs from the previous version fixed (360s, weird rotations)
  • The Filter.Kalman now exposes more methods to deal with continuous vs discrete inputs
  • Patch initialisation issue for MultiColourThreshold
  • Methods on the Switch subsystem have been renamed for consistency with clamping bounds
  • Controls string representation no longer breaks the Driver Station telemetry
  • Motor and Encoder readings 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 DifferentialDriveTask passing in the wrong vector

Other features

  • 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 MeepMeepRunner file, which has full support for the RoadRunner TaskBuilder and WPIUnits
    • This integration allows for faster path generation, all built into BunyipsLib without needing to perform any additional installation
  • RobotConfig now has a utility getLazyImu for getting the RoadRunner LazyImu instance used for the drive subsystems
  • Scheduler has split the task builder inTime and finishIf constructors into their own mini-builder, where calling finishIf twice will compose an OR condition
  • HardwareTester OpMode, which allows the scanning of HardwareMap to 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 @NonNull or @Nullable
  • Encoder now uses a delta approach to track position, allowing new known encoder positions to be set on the fly
  • HoldableActuator can now map TouchSensor instances to reset the encoder to a specific position when the switch is touched
  • New Condition class which handles rising and falling edge boolean detection (used internally by Scheduler)
  • DynIMU class to support delegating an IMU instance or using a 'null' IMU
  • Improvements to the TelemetryMenu children options
  • RoadRunner packets can now be synchronised to send at a single time using the new Dashboard util
  • New geometry utilities available as extension functions of Mathf
  • User setpoint control of HoldableActuator now provides delta time automatically through the Function provided
  • HoldableActuator now 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 for Controller to reset the initial state for debounce detection
  • New INTO THE DEEP processors for NeutralSample, RedSample, and BlueSample
  • Plus more additional valuable features!

v5.1.1

16 Oct 13:08
d90e7e1
Compare
Choose a tag to compare

v5.1.1 (2024-10-16)

Hotfixes for AprilTagPoseEstimator.

Bug fixes

  • 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

Upcoming changes

  • 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

v5.1.0

12 Oct 10:45
4279ed6
Compare
Choose a tag to compare

v5.1.0 (2024-10-12)

Several quality-of-life adjustments, bug fixes, and features.

Critical bug fixes

  • 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 BunyipsOpMode as 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 Motor class has been rewritten following a critical bug related to RUN_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 Motor was that it extended DcMotorImplEx; however, an internal method which is responsible for setting power was calling getMode(), which related to the overridden version in Motor
    • Note that Motor forces the actual motor to always run in RUN_WITHOUT_ENCODER mode as the hub-level PID controllers should always be disabled
    • This caused all setPower calls to be positive when RUN_TO_POSITION was active, as internally the power is taken for an absolute value in the standard RUN_TO_POSITION mode
    • Unfortunately, this would cause all system controllers on RUN_TO_POSITION to 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 DcMotorEx interface and handling the motor controller manually
    • As a side effect, the Motor class now supports the usage of all DcMotorEx methods in some proportion

Non-breaking changes

  • BunyipsComponent no longer needs to be running in the context of a BunyipsOpMode
    • This makes components that extend BunyipsComponent simply a utility instead of a strict requirement
    • Opens up subsystems, tasks, and all other components to not just BunyipsOpMode contexts, oftentimes when these components didn't need a reference to the OpMode anyways
    • Previous implementations of BunyipsComponent are unaffected, however, the opMode field has been made @Nullable which may throw some compiler warnings (as it is now possible for components to exist such that opMode is going to be null)
    • The new BunyipsComponent utilities now provide ways to assert behaviour and run code only on BunyipsOpMode contexts, such as require(opMode) and opMode(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
  • BunyipsOpMode active-loop runnables are now part of a HashSet rather than an ArrayList to prevent duplicates
  • Several components including DebugMode, AprilTagPoseEstimator, and new runnable components now auto-attach to the BunyipsOpMode runnables list if they can on construction
    • All runnable components also have the convention of a static method called enable() for concise construction
  • Mathf and EncoderTicks utilities now take in the Number supertype when taking in arguments
    • This removes the dual double/float methods of Mathf, and reduces the number of casts that need to be done when working with EncoderTicks that are sometimes in int or double forms
    • Internally, these Number supertypes are all converted to doubles
  • The Switch class has been disconnected from the Cannon class
    • This may cause some unknown method calls if using a Cannon method from a previous Switch class on migration
  • Task composition has been made simpler
    • AutonomousBunyipsOpMode now returns the added task instance when calling addTask()
      • RoadRunner does the same for addTask()
    • Tasks can now compose with utility functions attached directly to Task
      • .until which composes the current task with a RaceTaskGroup and a WaitUntilTask
      • .after which composes a task with the current task in a SequentialTaskGroup
      • .then which composes the current task with a task in a SequentialTaskGroup
      • .with which composes a ParallelTaskGroup with all the tasks
      • .race which composes a RaceTaskGroup with all the tasks
      • .during which composes a DeadlineTaskGroup with the current task being the deadline
      • .repeatedly which wraps the current task in a RepeatTask
    • These integrations make task construction more concise without having to construct groups manually for small operations
  • The ColourBlob vision data type from the ColourLocator processor can now be converted into ContourData instances
    • This allows tasks like AlignToContourTask and MoveToContourTask to be used with the new SDK 10.1 processors
    • To convert all list processor data into a ContourData list, 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 on Processor<ContourData>
  • PIDFController changes
    • Following conventions throughout BunyipsLib, PIDFController (and derivatives) now have builder-like patterns to allow for more streamlined construction
    • PIDFController also now has a setOutputClamps method to control the maximum and minimum results the controller may output
    • Variants ArmController and PIDFFController now support instances of the base PIDF to be used to allow profiled PID controllers instead of the hardcoded normal PID
  • Encoder now pipes acceleration estimation data through a built-in low-pass filter that can be modified via setAccelLowPassGain(double)
  • All previous tasks and components that relied on instance of RoadRunnerDrive have been abstracted via the new Moveable interface
    • 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 BunyipsSubsystem for their drive base have been migrated to Moveable, note that auto-attaching the task to a subsystem is still performed internally
  • Reference now implements Supplier and Consumer
  • DualServos and Cannon no longer auto-calls update() 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

Bug fixes

  • Acceleration information from Encoder can no longer be stale and is now updated on every loop with epsilon checks
  • RoadRunner withTimeout builder parameter now sets the timeout to infinite if a negative timeout is supplied
  • Various outdated docs updates
  • addTask of RoadRunner now checks for an active instance of AutonomousBunyipsOpMode to throw an exception early if it is not initialised
  • disableHardwareStopOnFinish() of AutonomousBunyipsOpMode is now a final method
  • Motor now clamps the RUN_TO_POSITION system controller output to -1 and 1 to allow the setPower argument to have a direct proportion over the controller
  • Encoder now flips the velocity readings depending on the direction, before this would only flip the current position
  • HoldableActuator is no longer affected by the user-defined min and max encoder limits when homing
  • The BlinkinLights internal setPattern call is now cached to prevent spamming Logcat or calling unnecessary code
    • Do be aware of this if you manually call setPattern on the RevBlinkinLedDriver
  • HoldableActuator update 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() and setMode()
    • 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
  • Various optimisations for AprilTagPoseEstimator to 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

Additions

  • Pure Pursuit implementation using a parametric look-ahead
    • Offered as a new component called PurePursuit which 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
  • New HardwareDevice drop-in replacement ProfiledServo to allow motion-profiled servos
    • Similar to the Motor class wrapping a DcMotor, the ProfiledServo class wraps a Servo
    • ProfiledServo exposes a new method setConstraints which can be used to define a TrapezoidalProfile that will be used to motion profile the servo
    • This allows velocity and acceleration control over the servo, while still conforming to the Servo interface for use in any previous code
    • Additional features from Motor including position cache tolerance and refresh rate have...
Read more

v5.0.0

24 Sep 05:20
a0681bc
Compare
Choose a tag to compare

v5.0.0 (2024-09-24)

Integration of SDK v10.1 and season-related features.

Breaking changes

  • Trajectory mirroring of the RoadRunner utility 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 MirrorMap types are now NONE, ALLIANCE_REFLECTION (default), and SYMMETRIC_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 BunyipsOpMode and/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)
  • Processor instances 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

Non-breaking changes

  • Various docs updates and migration to the wiki
  • DualTelemetry now displays the appropriate unit of Hz instead of l/s once the loop times are too fast to be represented as milliseconds
  • The slow loop speed warnings of DualTelemetry now don't show up during the init-phase when used in a LinearOpMode derivative
    • The init-phase is the heavy processing of the OpMode and loop times don't matter during init
  • Processor.getCameraDimensions() is now a public method
  • Ramping.DcMotor now extends DcMotorImplEx instead of DcMotorImpl

Bug fixes

  • RoadRunnerDrive watchdog 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
  • RoadRunnerDrive instances now cache their run mode during the constant setMode() 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 RoadRunnerDrive instance instead of the motors themselves, due to the caching

Additions

  • Update to SDK v10.1; the new recommended SDK version is now v10.1
    • New ColourLocator processor that wraps a ColorBlobLocatorProcessor
    • New ColourSensor processor that wraps a PredominantColorProcessor
    • Appropriate data classes with filtering methods are ColourBlob and ColourSample, appropriately
    • Since these processors are instance-based instead of abstract, their IDs are represented by coloursensor0, coloursensor1, etc. and colourlocator0, colourlocator1 etc. 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 ColourThreshold and AprilTag processors
    • The legacy ColourThreshold and MultiColourThreshold will not be deprecated

Notes

  • RoadRunner v1.0.0 is not planned for integration as of now
    • 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 Scheduler and Task system
    • Time is better spent for BunyipsLib development working on the wiki and new features rather than refactoring old but still useful systems
    • If support for RoadRunner v1.0.0 becomes more viable to integrate when external tools are updated to support RR v1.0.0, integration may be scheduled as another major release
  • StartingConfigurations assumes 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

v4.1.0

16 Sep 02:52
a6039c9
Compare
Choose a tag to compare

v4.1.0 (2024-09-16)

New features and additions for INTO THE DEEP.

Critical bug fixes

  • 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 FieldTile being 23.6 inches
    • This unit was supposed to have a magnitude of 24, where the approximation was used by mistake
  • TaskGroup timeout 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 TaskGroup abstraction
  • Scheduler runOnce() 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 on finishingIf() to end queued execution
  • Exceptions no longer swallows the ForceStopException (oops)

Non-breaking changes

  • AprilTagPoseEstimator now 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! setHeadingEstimate now defaults to true, as the Kalman filter should now filter out the erratic heading readings
  • BunyipsComponent and 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 Unit instances that called toString() 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 return 1234 V/m
    • This combines toLongString() without the full unit name
    • Previous scientific notation behaviour has been preserved in a new toScientificString() method
  • BunyipsOpMode now exposes the previously protected methods onActiveLoop and setInitTask as public to allow static access
    • This allows you to add activeLoop snippets from anywhere, including the RobotConfig
  • toString() of StartingPositions instances now internally call StartingPositions.getHTMLIfAvailable() to return an HTML-receiver-friendly output without having to call getHTMLIfAvailable() manually
    • The built-in name() method preserves the old behaviour of toString()
  • FtcDashboard now shows more overlay data for certain AlignTo tasks, including vector powers for drive input
  • Various JavaDoc and debugging statement updates
  • OnceTask internal timeout has been increased to 10ms to allow interpretation of summed timeouts to work properly
  • BunyipsOpMode onActiveLoop now runs all Runnables through the Exceptions handler to ensure exceptions do not hamper the rest of the loop
  • Various uses of PIDFController in constructors have been replaced with the more relaxed PIDF interface 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
  • BlinkinLights now has methods for setting the default pattern to other patterns if desired, it is no longer final
    • To follow subsystem convention, BlinkinLights methods now return their instance for builder-like patterns
  • Task.reset() now no-ops if the task has already been reset, preventing the multi-fire of onReset()
  • BunyipsOpMode will now try to reset the RC lights via exit() if it can, since it still has access to hardware writes
  • TelemetryMenu now spaces options slightly more to allow FtcDashboard users to read the menu easier

Bug fixes

  • Hardcoded values of org.murraybridgebunyips.bunyipslib have been replaced with the BuildConfig.LIBRARY_PACKAGE_NAME constant 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 in AutonomousBunyipsOpMode now strips HTML from the selected OpMode
  • setDefaultTask of BunyipsSubsystem now internally calls onSubsystem(this) to ensure default tasks are assigned to the current subsystem
  • The PIDF interface now extends SystemController as they are always used together
  • BunyipsOpMode no longer initially sleeps before evaluating the init-loop for the first time
  • Exceptions thrown via Exceptions during init will now be recognised and alerted in the BunyipsOpMode init-cycle
  • DualTelemetry.addData now accepts nullable data parameters to match other instances of adding telemetry data
  • Fix a missing return from an early return in UserSelection

Additions

  • New StartingConfiguration system to assist in robot starting configuration selection
    • This class has been designed to expand the StartingPositions enum following the 2024 season not being limited to simply two tiles per alliance
    • Instances of a StartingConfiguration.Position indicate 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 AutonomousBunyipsOpMode through the setOpModes() 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
    • Position toString() method will return a HTML human-friendly output (for UserSelection)
      • Red Alliance, Right from StartingPositions becomes On Red, Tile #3 from RIGHT wall in 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
  • New Filter class, which provides data and sensor filters
    • The newly added filters available through this class are a LowPass filter, 1D Kalman filter, and WeightedFusion filter
    • The Kalman filter is used internally in the AprilTagPoseEstimator
  • 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
  • Motor now 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 setPowerDeltaThreshold and setPowerRefreshRate of Motor
  • AprilTagData is now populated with a new field robotPose which 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 AprilTag builder
  • All RoadRunnerDrive instances now must include a setRotationPriorityWeightedDrivePower() override to run the weighted drive power calculation with rotational priority
    • Custom implementations of RoadRunnerDrive will need to extend this new method and implement it accordingly
    • CartesianMecanumDrive now exposes an internal static method to calculate rotation priority Mecanum poses
  • IMUEx now has a setYawMultiplier() 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
  • BunyipsOpMode now has a stopMotors() method which serves as a softer alternative to safeHaltHardware()
  • Exceptions now stores a static list of all exceptions that have been thrown
    • The reset method for this instance has been appended to Storage.resetAllStaticFieldsForOpMode()
  • BunyipsOpMode now has a static method ifRunning() which will execute the supplied Consumer<BunyipsOpMode> if BunyipsOpMode.isRunning() is true
  • BunyipsOpMode now has a getInitTask() method to return an Optional<Runnable> of the currently respected init-task
  • Text.removeHtml() created to regex out HTML tags and non-breaking spaces from strings
  • Text.upper() and .lower() created for cross-compatibility reasons in Kotlin, which will uppercase and lowercase strings

v4.0.0

07 Sep 17:31
debefb1
Compare
Choose a tag to compare

v4.0.0 (2024-09-08)

Major INTO THE DEEP season release.

Breaking changes

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 TFOD and TfodData
      • The SDK no longer offers TFOD; future vision integrations are expected to use OpenCV, which is integrated into BunyipsLib through the Processor pipelines.
  • BunyipsLib removal of v3.5.0 deprecations
    • Previously deprecated methods have been removed, which include BunyipsOpMode methods such as addTelemetry(), log(), and other telemetry-related methods.
      • To access telemetry, use the standard telemetry object which integrates as a DualTelemetry object. All methods that were removed from BunyipsOpMode is equivalently available through the telemetry object
    • DualTelemetry.removeRetained() (alias for remove()) has been removed
    • Scheduler.ConditionalTask.runDebounced() (alias for runOnce()) has been removed
  • The subsystem convention for Task exposure 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 called tasks
    • 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 to HoldableActuator.tasks.home()
    • Future BunyipsLib subsystems will continue to follow this standard
  • Examples directory removed
  • CameraType implementation 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 AprilTag processor, which is the primary use case for these intrinsics
  • RampingValue, RampingFunction, RampingSupplier, and DcMotorRamping have all been compressed into a single interface for brevity
    • New interface name is Ramping, and is the equivalent of RampingFunction with implementations for Ramping.Value, Ramping.Supplier, and Ramping.DcMotor
    • The setMaxDelta method has also been renamed to setMaxRampingDelta
    • Ramping.DcMotor now only extends DcMotor, instead of extending DcMotorEx
  • Vision systems updated to support multi-camera configurations
    • This includes Processor now 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, access getCameraDimensions(). 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)
  • addSubsystems() of CommandBunyipsOpMode and AutonomousBunyipsOpMode has 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 HolonomicDriveTask allow 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
  • Task system was reorganised for brevity
    • This includes the removal of abstract extensions of Task such as the NoTimeoutTask, where this can simply be done now by extending Task with no timeout parameter
    • The RobotTask interface was removed as this does not have usefulness with the evolved Task system
      • Frequently this lead to classes that did support RobotTask to perform instance checks and cast to Task, where this degraded code cleanliness for no reason
      • Tasks now extend the built-in Runnable, so previous implementations that used RobotTask only now are represented by the default type of Runnable
      • BunyipsOpMode now supports taking in a Runnable to use as the init-task which will run indefinitely during init unless it is a Task that has reported as finished
    • These reorganisations emphasise the idea that a Task is simply a Runnable with a timeout and finish condition
  • 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
  • AprilTagPoseEstimator now implements Runnable, the update() method is now run() 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 RoadRunnerTuningOpMode class, 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_TIMEOUT field from RoadRunner interface (Use Task.INFINITE_TIMEOUT)
    • RoadRunnerTask will still continue to have a task timeout equal to the trajectory duration by default
  • The RoadRunner interface now consolidates mirrored poses when using makeTrajectory()
    • 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 IMUOp subsystem has been redesigned from the ground-up as a HardwareDevice replacement
    • The new replacement is called IMUEx
    • The old IMUOp did 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 IMU interface to continually retrieve values and update public volatile fields
    • This can be integrated with subsystem-like integrations such as multithreading
    • IMUEx now 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 IMU interface 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
    • IMUEx also implements the IMU Universal Interface, so it can be used in place of other IMUs and hardware devices at the config level
  • CartesianFieldCentricMecanumDrive has been redesigned to not rely on another subsystem (old IMUOp) and now takes in an instance of the universal IMU
    • Construction now should be as simple as passing in the IMU from HardwareMap
  • GetTriPositionContourTask has been renamed to GetDualSplitContourTask which 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, or Direction.ZERO)
    • A convenience method getMappedPosition now 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)
  • 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
  • HoldableActuator.tasks.runFor has 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() of MecanumDrive has been standardised back to setMotorPowers() (new override) as found in t...
Read more

v3.5.0

12 Jul 08:59
acdbc1e
Compare
Choose a tag to compare

v3.5.0 (2024-07-12)

Migration to SDK v9.2, integration of new external control systems, some bug fixes and stability improvements.

Breaking changes

  • New deprecations which will be removed alongside SDK v10.0, including Tensorflow Object Detection
    • TFOD and GetWhitePixelTask will 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 centerstage packages 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
    • VisionTest has been removed of TFOD

Non-breaking changes

  • 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
  • VisionTest has changed which processors that can be tested, and now has options of RAW, APRILTAG, and the four CENTERSTAGE pixels

Bug fixes

  • Fixed broken implementations throughout RoadRunner where the method overloads were not being reflected properly
    • This was due to not implementing correct methods from the TrajectorySequenceBuilder interface
    • waitFor() has been given an additional overload to match the scheme of (magnitude, unit) for RoadRunner task building
  • Fix a misparse of the Controller gamepad 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

Additions

  • New control system utilities from WPILib have been ported to BunyipsLib
    • This includes the TrapezoidProfile, ArmFeedforward, ElevatorFeedforward, SimpleMotorFeedforward, and ProfiledPIDController classes
    • Documentation on using these utilities can be sourced from WPILib/FTCLib, as these classes are in line with these counterparts
    • ArmFeedforward has been updated to use WPIUnits for the calculation method, to interop with the EncoderTicks class

v3.4.2

02 Jul 09:14
b7489bd
Compare
Choose a tag to compare

v3.4.2 (2024-07-03)

Improved exception handling and edge case fixes.

Breaking changes

  • The toString() method of Task has 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 the withName() method

Non-breaking changes

  • dynamic_init is now in a while loop as opposed to a do-while loop, ensuring an early exit is respected before running more initialisation code

Bug fixes

  • Improved error catching with the initTask, where exceptions during the onFinish() method would cause a full crash
  • BunyipsOpMode now takes in a RobotTask instead of a Task in setInitTask(...)
    • This was the intended behaviour, as it supported using a minimal interface to begin with