Meanlib is a Kotlin FRC Robot utility library made by Team 2471 Mean Machine.
-
WpiLib units library extensions:
- Number → Unit:
1.0.inches,2.5.degrees - Unit → Number:
Distance.asFeet,Angle.asDegrees"as" keyword - Supports all the same operations and functions as WpiLib units:
- Number → Unit:
-
PoseLocalizer:- Interacts with offboarded ParticleFilter, a program that uses an SIR Particle Filter to combine camera measurements and odometry data
- Sends vision measurements to ParticleFilter and latency-adjusts the poses it gets back.
- Custom
PhotonVisionCameraandLimelightCameraclasses support simulation/replay - Calculates three different poses:
pose/fusedPosePose2d from ParticleFilter (Global Positioning)singleTagPoseSimple trig position solver for the closest tag (Local Positioning)odometryPoseOnly the swerve odometry
- ParticleFilter and PoseLocalizer were originally made by Team 604 and modified by us.
-
CTRE device configuration utility functions: (TalonFX, TalonFXS, CANcoder, Pigeon2)
val hoodMotor = TalonFX(0); val hoodMotorFollower = TalonFX(1); val hoodEncoder = CANcoder(2)
hoodMotor.applyConfiguration {
currentLimits(25.0, 30.0, 1.0)
inverted(true)
brakeMode()
s(0.2, StaticFeedforwardSignValue.UseClosedLoopSign)
p(200.0)
d(0.0)
motionMagic(0.75, 5.0)
remoteCANCoder(hoodEncoder.deviceID, hoodSensorToMechanismRatio)
}
hoodMotor.addFollower(hoodMotorFollower, MotorAlignmentValue.Opposed)
hoodEncoder.setCANCoderAngle(0.0.degrees)-
LoggedTalonFXandLoggedTalonFXS:- Inherits from the normal TalonFX
- Includes WpiLib motor sim + motor sim configuration
- Runs asynchronously via coroutine when calling
brakeMode())andcoastMode(), so they are no longer blocking. - Automatically logs motor data and supports replay (wip)
-
SwerveDriveSubsystem:- Inherits from CTRE's SwerveDrivetrain, adds functionality
- Implements Choreo and Autopilot
- Settable path PID controllers and Autopilot constants
- Module and gyro disconnection Alerts
- Commands:
driveToPointdriveToAutopilotPointdriveAlongChoreoPathdriveToLinejoystickDriveAlongLine
-
Assortment of Kotlin/WpiLib extension functions:
- Math:
Double.deadband(),Double.round(),Translation2d.normalize(), etc. - Conversions:
Translation2d().toPose2d(heading),ChassisSpeeds().fieldToRobotCentric(heading), etc.
- Math:
-
BatteryLogger:- logs power usage (in amp-hours and watt-hours) for each subsystem
BatteryLogger.recordCurrent("Shooter Roller", shooterMotor.supplyCurrent.value * 2.0)LoopLogger:- Logs
sinceReset(time sinceLoopLogger.reset()was called) and, periodfor loop periods
- Logs
// First thing in robot periodic:
LoopLogger.reset()
// In subsystem periodic:
LoopLogger.record("Subsystem periodic")
val isConnected = camera.isConnected
LoopLogger.record("After camera check")-
WpiLib Commands v2 extension functions/syntax shortcuts:
runOnceCommand,sequenceCommand, etc. instead ofCommand.runOnce,Command.sequenceCommand
-
Custom Autonomous manager
Autonomiclass:- Automatically finds all Choreo paths, preloads them, and puts them in a keyed map
override val autoChooser: LoggedDashboardChooser<AutoCommand?> =
LoggedDashboardChooser<AutoCommand?>("Auto Chooser").apply {
addOption("8 Foot Straight", AutoCommand(eightFootStraight()) { robotStartPose2d })
}
private fun eightFootStraight(): Command {
return Drive.driveAlongChoreoPath(paths["eightFoot"]!!)
}- Kotlin Coroutines:
- This is used in a lot of utilities, and it is also exposed for use in robot code.
// Launch a new thread
GlobalScope.launch {
// do async task
periodic(0.02) { // loop at 50hz (0.02 seconds)
// do periodic task
this.stop() // exit loop
}
}- Other:
measureTimeFPGA {}measures code segment execution time.PDVelocityControllerCustom compounding PD controller for velocity control.NT4NonFMSPublisherAn AdvantageKitLogDataReceiverthat only publishes to NetworkTables when an FMS isn't connected:Logger.addDataReceiver(NT4NonFMSPublisher())
Start by creating a standard FRC robot project.
Add meanlib as a submodule inside your robot project:
git submodule add https://github.com/TeamMeanMachine/meanlib/Checkout the current year's branch:
git checkout frc[CURRENT_YEAR] # ex: "git checkout frc2026"Add Meanlib to your build.gradle dependencies:
dependencies {
implementation(project(":meanlib"))
..
}Add Meanlib to the jar task in your build.gradle:
jar {
dependsOn(':meanlib:jar') // <- add me
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
from sourceSets.main.allSource
manifest GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}Optional: Use meanlib vendordeps (paste anywhere in build.gradle):
// Tell the global WPILib provider to also load vendors from meanlib,
wpi.vendor.loadFrom(project(":meanlib"))