Skip to main content

Overview

Overview

The Blacksmith Framework is a collection of tools and utilities for FTC programming, which focuses on readability, brevity, and aiming to be as intuitive as possible. It allows you to program more declaratively and worry less about common logic that serve only to distract you and add more potential points of failure.

Blacksmith & docs by toptobes (Sin#9527)

Kalman filter wizardry by T-Lind (TXKL#1554)

tip

Consider giving our repo a star if you like it, but of course you don't have to

info

All code documentation provide both Java and Kotlin examples

Enough with the buzzwords, what does it do?

The Blacksmith Library provides a few different things:

  • The Scheduler API - An API to drastically simplify the creation and maintainability of your OpModes, and make them much cleaner and terser. It provides many methods to hide away a lot of extra logic that you don't need to worry about, such as scheduling when to run certain code.
  • Anvil - A wrapper around Roadrunner's TrajectorySequenceBuilder which provides a much nicer API for creating trajectories, as well as implicit unit conversion and utilities for creating trajectories on the fly without slowing down your auto.
  • BlackOp - An extension to the traditional OpMode/LinearOpMode which contains some extra features for a much more seamless and carefree development experience
  • Kalman Filters - Helps improve encoder readings (by potentially a lot) by dampening noise. Helped improve our own auto's localization a lot, and solved a lot of our lift issues.
  • And a decent amount of utilities..., including a few cool MeepMeep utilities

I recommend checking those out for examples of each.

tip

If you use Kotlin (or even if you don't honestly), I highly recommend checking out our codebase in TeamCode to see how Blacksmith is used in actual code

Here's a basic example of a TeleOp before and after using Blacksmith:

@TeleOp
public class NotCoolTeleOp extends OpMode {
@Override
public void init() {
// Initialize hardware
}

@Override
public void loop() {
// Loop code
}

// ...300 billion lines later...

private boolean gamepad2aPreviousState = //...;

private void checkIfShouldDoSomething() {
if (gamepad2.a && !gamepad2aPreviousState) { // Messy and ugly and ew 🤮
claw.intake();
} else if (!gamepad2.a && gamepad2aPreviousState) { // Ugly unreadable signal edge detectors
claw.close();
} // Can't tell if the driver does this or the codriver at the quick glance
gamepad1aPreviousState = //...;
} // ugh imperative hell
}
@TeleOp
public class CoolTeleOp extends BlackOp {
@EvalOnGo(method = "getReforgedGamepad2")
private ReforgedGamepad codriver;

@Override
public void go() {
codriver.a.onRise(claw::intake); // Simple and easy to read
codriver.a.onFall(claw::close); // Complexity is abstracted away

Scheduler.launchOnStart(this, () -> {
// Any extra code to run every loop
});
}
}

As you can see, the Blacksmith version is much different, but it's much more readable and easier to make changes to. It's easy to learn and only requires a little knowledge of Java (Shouldn't be much you haven't seen in RoadRunner and other libraries).

I don't want to use all of this magic

That's fine! Blacksmith is incrementally adoptable and you only have to use the parts you want.

I don't understand these symbols

The guide does require some knowledge of Java, but it's really not too hard to learn. You just need to have fairly surface level knowledge of lambdas and how to use an annotation and such to use this API. If you're not familiar with Java, I recommend checking out the FAQ page for some resources to learn what you need to know for this framework.

If you're using Kotlin, this guide does somewhat presume you know what you're doing and won't explain the Kotlin as much.

What are all these new methods and stuff?

They're probably described in the docs somewhere, just keep reading.

Okay... but what about performance?

The performance impact is negligible; CPUs are fast, and you have other things to worry about in terms of performance.

This API is simply a couple layers of abstraction on top of the existing FTC SDK, and is in no way computationally expensive.

Plus... the majority of the overhead is just at initialization time and clears up pretty quickly