Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ jobs:
# ------------------------------------------------------------
build:
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2024-22.04
if: ${{ github.event_name != 'pull_request' || github.event.pull_request == null }}

steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Set up Java 25
uses: actions/setup-java@v6.0.1
with:
distribution: temurin
java-version: '25'

- name: Mark repo as safe for git
run: git config --global --add safe.directory $GITHUB_WORKSPACE

Expand All @@ -34,13 +39,18 @@ jobs:
# ------------------------------------------------------------
spotless:
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2024-22.04
# Only run for PRs or pushes targeting main/develop
if: github.base_ref == 'main' || github.base_ref == 'develop' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop'
steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Set up Java 25
uses: actions/setup-java@v6.0.1
with:
distribution: temurin
java-version: '25'

- name: Grant execute permission for gradlew
run: chmod +x gradlew

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-submission.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ jobs:
uses: actions/setup-java@v6.0.1
with:
distribution: 'temurin'
java-version: 17
java-version: '25'
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v6
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "java",
"name": "Main",
"request": "launch",
"mainClass": "frc.robot.Main",
"mainClass": "first.Main",
"projectName": "Az-RBSI"
},
{
Expand Down
8 changes: 4 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"org.mockito.Mockito.*",
"org.mockito.ArgumentMatchers.*",
"org.mockito.Answers.*",
"edu.wpi.first.units.Units.*"
"org.wpilib.units.Units.*"
],
"java.completion.filteredTypes": [
"java.awt.*",
Expand All @@ -62,9 +62,9 @@
"javax.swing.*",
"javax.management.*",
"javax.smartcardio.*",
"edu.wpi.first.math.proto.*",
"edu.wpi.first.math.**.proto.*",
"edu.wpi.first.math.**.struct.*",
"org.wpilib.math.proto.*",
"org.wpilib.math.**.proto.*",
"org.wpilib.math.**.struct.*",
null
],
"editor.defaultFormatter": "richardwillis.vscode-spotless-gradle",
Expand Down
2 changes: 1 addition & 1 deletion .wpilib/wpilib_preferences.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"enableCppIntellisense": false,
"currentLanguage": "java",
"projectYear": "2026",
"projectYear": "2027_alpha5",
"teamNumber": 9986
}
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![CI](https://github.com/AZ-First/Az-RBSI/actions/workflows/ci.yaml/badge.svg)](https://github.com/AZ-First/Az-RBSI/actions/workflows/ci.yaml)

![AzFIRST Logo](https://github.com/AZ-First/Az-RBSI/blob/main/AZ-First-logo.png?raw=true)
![AzFIRST Logo](assets/AZ-First-logo.png)

# Az-RBSI

Expand All @@ -11,6 +11,22 @@ Az-RBSI is a robot-code template for teams that want a reliable swerve,
odometry, vision, autonomous, logging, and tuning baseline without starting from
an empty project.

## 2027 CANOPY/BIOCORE

<p>
<img src="assets/season-2027/first-canopy-logo.png" alt="FIRST CANOPY logo" width="260">
<img src="assets/season-2027/first-biocore-frc-lockup.png" alt="FRC BIOCORE logo" width="300">
</p>

To use the BIOCORE VS Code theme:

1. Open the Extensions view in VS Code.
2. Select `...` > `Install from VSIX...`.
3. Install
[`themes/frc-biocore-high-contrast-theme-1.0.1.vsix`](themes/frc-biocore-high-contrast-theme-1.0.1.vsix).
4. Run `Preferences: Color Theme` from the command palette and select
`FRC BIOCORE High Contrast`.

## Documentation

Start with the full documentation index:
Expand Down
File renamed without changes
Binary file added assets/season-2027/first-biocore-frc-lockup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/season-2027/first-canopy-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 45 additions & 49 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
plugins {
id "java"
id "edu.wpi.first.GradleRIO" version "2026.2.1"
id "org.wpilib.GradleRIO" version "2027.0.0-alpha-6"
id "com.gradleup.shadow" version "9.3.0"
id "com.peterabeles.gversion" version "1.11.0"
id "com.diffplug.spotless" version "8.10.4"
id "io.freefair.lombok" version "9.8.2"
id "com.google.protobuf" version "0.10.0"
}

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
}

sourceSets {
Expand All @@ -20,52 +21,43 @@ sourceSets {
}
}

def ROBOT_MAIN_CLASS = "frc.robot.Main"
def ROBOT_MAIN_CLASS = "first.Main"

// Define my targets (RoboRIO) and artifacts (deployable files)
// Define my targets (SystemCore) and artifacts (deployable files)
// This is added by GradleRIO's backing project DeployUtils.
deploy {
targets {
roborio(getTargetTypeClass('RoboRIO')) {
systemcore(getTargetTypeClass('SystemCore')) {
// Team number is loaded either from the .wpilib/wpilib_preferences.json
// or from command line. If not found an exception will be thrown.
// You can use getTeamOrDefault(team) instead of getTeamNumber if you
// want to store a team number in this file.
team = project.frc.getTeamNumber()
debug = project.frc.getDebugOrDefault(false)
team = project.wpilib.getTeamNumber()
// Use the default systemcore host name. This must be called after setting team
// as happens on the line above
useDefaultSystemcoreHostName()
debug = project.wpilib.getDebugOrDefault(false)

artifacts {
// First part is artifact name, 2nd is artifact type
// getTargetTypeClass is a shortcut to get the class type using a string

frcJava(getArtifactTypeClass('FRCJavaArtifact')) {
jvmArgs.add("-XX:+UnlockExperimentalVMOptions")
jvmArgs.add("-XX:GCTimeRatio=5")
jvmArgs.add("-XX:+UseSerialGC")
jvmArgs.add("-XX:MaxGCPauseMillis=50")

// The options below may improve performance, but should only be enabled on the RIO 2
//
// final MAX_JAVA_HEAP_SIZE_MB = 100;
// jvmArgs.add("-Xmx" + MAX_JAVA_HEAP_SIZE_MB + "M")
// jvmArgs.add("-Xms" + MAX_JAVA_HEAP_SIZE_MB + "M")
// jvmArgs.add("-XX:+AlwaysPreTouch")
wpilibJava(getArtifactTypeClass('WPILibJavaArtifact')) {
}

// Static files artifact
frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
wpilibStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
files = project.fileTree('src/main/deploy')
directory = '/home/lvuser/deploy'
// Change to true to delete files on roboRIO that no
directory = '/home/systemcore/deploy'
deleteOldFiles = false // Change to true to delete files on systemcore that no
// longer exist in deploy directory of this project
deleteOldFiles = true
}
}
}
}
}

def deployArtifact = deploy.targets.roborio.artifacts.frcJava
def deployArtifact = deploy.targets.systemcore.artifacts.wpilibJava

// Set to true to use debug for all targets including JNI, which will drastically impact
// performance.
Expand All @@ -81,11 +73,11 @@ dependencies {
implementation wpi.java.deps.wpilib()
implementation wpi.java.vendor.java()

roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio)
roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio)
systemcoreDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.systemcore)
systemcoreDebug wpi.java.vendor.jniDebug(wpi.platforms.systemcore)

roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio)
roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio)
systemcoreRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.systemcore)
systemcoreRelease wpi.java.vendor.jniRelease(wpi.platforms.systemcore)

nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
Expand All @@ -98,6 +90,9 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:6.1.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

implementation 'com.fasterxml.jackson.core:jackson-core:2.21.6'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.21.6'

def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text)
implementation "org.littletonrobotics.akit:akit-java:$akitJson.version"
annotationProcessor "org.littletonrobotics.akit:akit-autolog:$akitJson.version"
Expand All @@ -112,23 +107,21 @@ test {
wpi.sim.addGui().defaultEnabled = true
wpi.sim.addDriverstation()

// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar')
// in order to make them all available at runtime. Also adding the manifest so WPILib
// knows where to look for our Robot Class.
jar {
from {
configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
from sourceSets.main.allSource
manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS)
// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat/shaded jar')
// in order to make them all available at runtime and merging service files to make JSON work.
// Also adding the manifest so WPILib knows where to look for our Robot Class.
shadowJar {
mergeServiceFiles()
from('src') { into 'backup/src' }
from('vendordeps') { into 'backup/vendordeps' }
from('build.gradle') { into 'backup' }
manifest org.wpilib.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

// Configure jar and deploy tasks
deployArtifact.jarTask = jar
wpi.java.configureExecutableTasks(jar)
deployArtifact.jarTask = shadowJar
wpi.java.configureExecutableTasks(shadowJar)
wpi.java.configureTestTasks(test)

// Configure string concat to always inline compile
Expand All @@ -139,18 +132,21 @@ tasks.withType(JavaCompile) {
// Create version file
project.compileJava.dependsOn(createVersionFile)
gversion {
srcDir = "src/main/java/"
srcDir = "src/main/java/"
classPackage = "frc.robot"
className = "BuildConstants"
dateFormat = "yyyy-MM-dd HH:mm:ss z"
timeZone = "America/Phoenix"
indent = " "
className = "BuildConstants"
dateFormat = "yyyy-MM-dd HH:mm:ss z"
timeZone = "America/Phoenix"
indent = " "
}

// Create commit with working changes on event branches
def deployRequested = gradle.startParameter.taskNames.any({
it.toLowerCase().contains("deploy")
})
task(eventDeploy) {
doLast {
if (project.gradle.startParameter.taskNames.any({ it.toLowerCase().contains("deploy") })) {
if (deployRequested) {
def branchPrefix = "event"
def branch = 'git branch --show-current'.execute().text.trim()
def commitMessage = "Update at '${new Date().toString()}'"
Expand Down Expand Up @@ -183,7 +179,7 @@ createVersionFile.dependsOn(eventDeploy)
// Spotless formatting
project.compileJava.dependsOn(spotlessApply)
spotless {
enforceCheck true
enforceCheck = true
java {
target fileTree('.') {
include '**/*.java'
Expand Down
9 changes: 7 additions & 2 deletions doc/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ following components on your laptop and devices.
* Driver Station `Version 26.0` (comes with the FRC Game Tools from National
Instruments)
* CTRE Tuner X `26.2.4.0`, with all devices running firmware `26.0` or newer.
This includes all motors, CANivore, Pigeon 2.0, and all CANcoders.
This includes all motors, Pigeon 2.0, and all CANcoders. The 2027 SystemCore
template uses native `can_s*` ports for its recommended drive layout.
* REV Hardware Client `2.0`, with the PDH, all SPARK MAXs, and other devices
running firmware `26.1` or newer.
* Vivid Hosting Radio firmware `2.0.1` or newer is required for competition this
Expand Down Expand Up @@ -159,7 +160,11 @@ steps you need to complete:
10. Open [RBSI-Constants.md](RBSI-Constants.md) and work through the sections
that match your robot. At minimum, verify `RobotDevices`,
`DrivebaseConstants`, `OperatorConstants`, `AutoConstants`, and
`VisionConstants` before your first serious drive test.
`VisionConstants` before your first serious drive test. Set the five
`DrivebaseConstants` bus assignments to match the physical SystemCore ports;
see [CAN bus assignments](RBSI-Constants.md#canbuses). The default places
front modules on `can_s2`, back modules on `can_s3`, the Pigeon on `can_s4`,
and mechanisms on `can_s1`.


**NOTE:** If you have any other combination of hardware (including REV NEOs,
Expand Down
43 changes: 38 additions & 5 deletions doc/RBSI-Constants.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,44 @@ Tune these early for the real robot:
`CANBuses` names the robot CAN networks:

- `RIO`
- `DRIVE`
- `ALL`

These names must match CTRE, REV, and generated swerve configuration expectations. Add any
additional CANivore or vendor buses here and include them in `ALL` so health monitoring sees them.
- `SYSTEMCORE_0` through `SYSTEMCORE_4` (`can_s0` through `can_s4`)
- `ALL`, built from the buses actually selected for drive devices plus `RIO`

The five SystemCore names are its native interfaces, ordered left to right. `RIO` is a historical
name for the mechanism bus; it now aliases `SYSTEMCORE_1` (`can_s1`), not a roboRIO CAN network.
The registry initializes and health-monitors every bus in `ALL`. Add other mechanism buses to
`ALL` if you assign devices outside the drivebase to them.

`DrivebaseConstants` has one CAN assignment for each complete module (`kFLCANBus`, `kFRCANBus`,
`kBLCANBus`, and `kBRCANBus`) plus an independent `kPigeonCANBus`. A module's drive motor, steer
motor, and encoder always use its single selected bus; they cannot be split through these
constants. `RobotDevices` inherits these assignments through `SwerveConstants`, so CAN identity
and power monitoring stay consistent. The default follows FRC-2026: front modules on `can_s2`, back
modules on `can_s3`, Pigeon on `can_s4`, and mechanisms on `can_s1`. Port `can_s0` is available.

Change the five `DrivebaseConstants` assignments to match your wiring. These are useful layouts;
each row lists the front-left, front-right, back-left, back-right, and Pigeon buses in that order:

| Drive buses | FL | FR | BL | BR | Pigeon |
| --- | --- | --- | --- | --- | --- |
| One | `can_s2` | `can_s2` | `can_s2` | `can_s2` | `can_s2` |
| Two, front + IMU / back | `can_s2` | `can_s2` | `can_s3` | `can_s3` | `can_s2` |
| Two, left + IMU / right | `can_s2` | `can_s3` | `can_s2` | `can_s3` | `can_s2` |
| Three, front / back / IMU (default) | `can_s2` | `can_s2` | `can_s3` | `can_s3` | `can_s4` |
| Three, left / right / IMU | `can_s2` | `can_s3` | `can_s2` | `can_s3` | `can_s4` |

The five assignments can also use any other `SYSTEMCORE_*` port independently, up to five drive
buses. Keep all three devices of a module together. Assign the Pigeon to the desired bus, and
check that each assigned physical port and CAN ID match the hardware. `ALL` follows these values
automatically; add separately assigned mechanism buses manually.
REV's 2027 motor constructors use numbered native SystemCore CAN ports; this project maps the
`SYSTEMCORE_*` names to those ports and rejects an external named bus for a REV motor. Generated
Phoenix Tuner constants may still contain a single-bus name; the runtime device constructors use
the assignments above. Keep generated files as calibration inputs and configure the bus split here.

Placing modules on separate buses limits the scope of a bus failure, but does not itself implement
three-module fault-tolerant swerve control. Validate the wiring and loss-of-device behavior on
hardware before relying on device-out operation.

## RobotDevices

Expand Down
7 changes: 7 additions & 0 deletions doc/RBSI-Drive.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ Check these first:
- Pigeon/NavX configuration,
- PDH/PDP power ports.

For SystemCore wiring, select one bus per complete module with `kFLCANBus`, `kFRCANBus`,
`kBLCANBus`, and `kBRCANBus` in `Constants.DrivebaseConstants`; the Pigeon has a separate
`kPigeonCANBus`. A module's drive, steer, and encoder must all be wired to its selected bus. The
default uses front / back / IMU on `can_s2` / `can_s3` / `can_s4`, with mechanisms on `can_s1`.
See [CAN bus assignments](RBSI-Constants.md#canbuses) for one, two, and three bus layouts.

The power-port mapping does not control motors, but it affects current logging
and subsystem power monitoring. Bad power-port maps make electrical debugging
much harder.
Expand All @@ -87,6 +93,7 @@ Important values in `DrivebaseConstants`:
- `kMaxLinearAccelMetersPerSecSq`
- `kWheelRadiusMeters`
- `kSlipCurrentAmps`
- `kPigeonCANBus` and the four module CAN bus assignments
- `kDriveP`, `kDriveD`, `kDriveS`, `kDriveV`, `kDriveA`, `kDriveT`
- `kSteerP`, `kSteerD`, `kSteerS`
- `kStrafeP`, `kStrafeI`, `kStrafeD`
Expand Down
Loading
Loading