The Basics
Variables, data types, operators, scope, and writing code other people can actually read.
Variables & Data Types
ok so before we write a single line of robot code, we need to talk about the most fundamental thing in all of programming: variables. if you've never programmed before, don't worry — this is actually pretty intuitive once you have the right mental model for it.
the mental model
imagine you're making a sandwich and you need to remember how many slices of bread you have left. you'd probably just hold that number in your head. your brain grabs a little chunk of memory and stashes the number there so you can use it later. a variable is exactly that: a named slot in your computer's memory where you can stash a value and pull it back out whenever you need it.
think of it like a labeled box. you write a name on the outside (the variable name), decide what kind of thing goes inside (the type), and put something in it (the value). later, whenever you need that value, you just look at the box with that name on it.
what's RAM? when your program runs, Java grabs a chunk of your computer's RAM (random access memory) to work with. RAM is super fast but temporary — it only exists while the program is running. every variable you declare takes up a little piece of that RAM. when the robot reboots, poof, it's all gone. that's totally fine for us, because the robot starts fresh every time anyway.
in robot code, variables are everywhere. your robot needs to track what speed each motor is running at, whether a button is currently pressed, what the encoder is reading (an encoder measures how far a motor shaft has rotated), and which subsystem (a distinct part of the robot — intake, drivetrain, shooter — represented as a class) is active. every single one of those is a variable. you cannot write robot code without them.
declaring a variable
in Java, when you create a variable you have to tell Java three things: the type (what kind of thing), the name (what you want to call it), and optionally a starting value. this process of creating a variable is called "declaring" it.
the format is always: type name = value;
let's see each of the four types you'll use in robot code, one by one:
// int — whole numbers only, no decimals // use it for things that are always a whole number: motor IDs, counts, encoder ticks int motorID = 5; // double — decimal numbers (very precise, 64-bit) // use it for speeds, distances, angles — anything that can be a fraction double motorSpeed = 0.75; // boolean — only two possible values: true or false // use it for on/off states, flags, "did this happen?" boolean isRunning = false; // String — a piece of text (note the capital S — it's special) // use it for labels, log messages, display names String subsystemName = "Drivetrain";
here's another example showing a full block of variable declarations you'd actually see in robot code — notice how each line has a comment explaining what it represents:
// shooter subsystem variables int topMotorID = 7; // the unique number that identifies this motor on the robot's wiring system int bottomMotorID = 8; // same idea — unique ID for the bottom flywheel motor on the CAN bus double targetSpeed = 0.85; // desired flywheel speed (0.0 to 1.0) boolean isAtSpeed = false; // whether shooter has reached target speed String subsystemName = "Shooter"; // used for logging and dashboard display
the final keyword — constants
sometimes you have a value that should never change. like a motor's CAN ID — once you wire it to port 5, it stays port 5 forever. you'd never want some random part of your code to accidentally change that to 7 at runtime and suddenly the wrong motor is spinning.
that's what final is for. it's like a sticky note that you can write on exactly once, and then the note is laminated shut. you can read it forever, but you can NEVER change what it says.
// regular variable — can be changed later double motorSpeed = 0.5; motorSpeed = 0.8; // totally fine, reassignment is allowed // constant — can NEVER be reassigned after this line final int kMotorID = 5; kMotorID = 6; // COMPILE ERROR: cannot assign a value to final variable kMotorID // in robot code, constants live in Constants.java and look like this: public static final int kShooterMotorID = 7; public static final double kMaxSpeed_mps = 4.5; // meters per second public static final double kGearRatio = 8.46; // motor turns per wheel turn
WRT convention: on our team, constants use a k prefix — kMotorID, kMaxSpeed_mps. member (instance) variables use m_ prefix — m_targetSpeed. you'll see this absolutely everywhere in our codebase. we'll go deeper on naming in topic 3, but start noticing it now.
the four core types (reference table)
there are actually tons of types in Java, but these four are what you'll use 95% of the time in robot code. memorize them:
| Type | Category | What it holds | FRC use case |
|---|---|---|---|
int | Primitive | Whole numbers only (-2 billion to +2 billion) | Motor CAN IDs, encoder ticks, loop counters, game piece counts |
double | Primitive | Decimal numbers, very precise (64-bit) | Motor speeds (-1.0 to 1.0), distances in meters, velocities, angles in degrees |
boolean | Primitive | true or false, that's it | Limit switch state, "is shooter at speed?", "did autonomous finish?", button state |
String | Non-primitive | Any text, any length | Shuffleboard widget labels, log messages, error descriptions, subsystem names |
primitive vs object — what's the difference? primitives (int, double, boolean) are raw values stored directly in memory — super simple, super fast. non-primitives like String are objects, which means they're more complex under the hood and come with built-in methods (name.length(), name.toLowerCase(), etc). the distinction matters more once we hit OOP week, but just know: String with a capital S is special compared to the lowercase primitives.
what if you don't give a variable a starting value?
this is actually an important distinction that trips up beginners a lot. there are two kinds of variables in Java: instance variables (variables declared at the top of a class, outside any method) and local variables (variables declared inside a method).
instance variables get free default values if you don't set them. local variables do NOT — Java will refuse to let you use one until you've given it a value first.
public class ShooterSubsystem { // instance variables — these get default values automatically private int m_motorID; // defaults to 0 private double m_speed; // defaults to 0.0 private boolean m_isRunning; // defaults to false private String m_name; // defaults to null (nothing) public void someMethod() { // local variable — NO default, must assign before using int speed; System.out.println(speed); // COMPILE ERROR: variable speed might not have been initialized // fix: assign it first, then use it int fixedSpeed = 0; System.out.println(fixedSpeed); // works fine, prints: 0 } }
common beginner gotcha: just because an instance variable can default to 0 or false doesn't mean you should rely on that. always initialize your variables explicitly. it makes your code way clearer and prevents subtle bugs where you forget to set something and it silently uses 0 or null when you didn't expect it.
naming your variables well is one of the most important skills you'll pick up in this course. we go deep on this in topic 3, including the specific prefixes (k, m_) your code must use on this team.
Topic 1 — Coding Prompt
Declare four variables using WRT naming conventions:
• a constant int — the shooter motor's CAN ID (value: 5)
• a constant double — the max shooter speed (value: 0.9)
• a boolean — whether the shooter is currently spinning (start it as false)
• a String — the subsystem name (value: "Shooter")
Then print all four with System.out.println.
Topic 1 — Quick Check
Operators
operators are just symbols that let you do stuff with values — add them, subtract them, compare them, combine them. you already know most of these from math class. a few have Java-specific twists that are worth knowing cold because they cause real bugs if you don't.
ok so what are these, exactly
an operator is a tiny machine that takes values in and spits a result out. the + operator takes two numbers and gives you their sum. the > operator takes two numbers and gives you a yes/no answer about which is bigger. that's really all it is.
in robot code, operators are literally everywhere: converting encoder ticks to rotations, clamping motor speeds to safe ranges, checking if a sensor reading crossed a threshold. if you don't understand integer division and modulo in particular, you will introduce bugs in your first week of writing real robot code.
arithmetic operators
let's go through each one with a standalone example. no giant code dumps — just one at a time so you actually remember them:
// + addition — adds two values double total = 3.0 + 1.5; // total = 4.5 // - subtraction — subtracts second from first double diff = 5.0 - 2.0; // diff = 3.0 // * multiplication — multiplies two values double product = 4.0 * 2.5; // product = 10.0 // / division — divides first by second (CAREFUL with ints! see below) double quotient = 9.0 / 4.0; // quotient = 2.25 // % modulo — gives you the REMAINDER after division int remainder = 7 % 3; // 7 ÷ 3 = 2, with 1 left over. so remainder = 1
the integer division gotcha (this WILL bite you)
ok story time. imagine you have 5 cookies and 2 friends. you want to split them evenly. in real life, each person gets 2.5 cookies. but Java doesn't work like that for integers. Java says: each person gets 2 cookies. the leftover half? thrown in the trash. silently. no warning, no error. just gone.
this is called integer division and it is the source of SO many bugs in FRC code. any time you divide two int values, the decimal part is simply chopped off and discarded:
// classic FRC bug: encoder math with integer division int ticks = 1500; int ticksPerRev = 2048; int revs = ticks / ticksPerRev; // you think this is ~0.73 right? WRONG // it's 0. the 0.73 is silently thrown away. // ───────────────────────────────────────── // Fix 1: cast one of the ints to double first double revsFixed = (double) ticks / ticksPerRev; // 0.732... correct!! // Fix 2: use a double literal (the .0 forces Java to use double math) double revsFixed2 = 1500.0 / ticksPerRev; // also 0.732... correct!! // Fix 3: declare both as double from the start if you need decimals double dTicks = 1500.0; double dTicksPerRev = 2048.0; double revsFixed3 = dTicks / dTicksPerRev; // 0.732... correct!!
this bites you HARD in FRC. encoder math, gear ratio calculations, PID error terms, distance calculations — all of these involve division. every time you write a division, ask yourself: "do I want integer or decimal math here?" if there's any chance the answer has a decimal, use doubles.
modulo — the clock operator
modulo (%) gives you the remainder after dividing. here's a quick way to think about it: imagine a 12-hour clock. if it's 8pm and you add 15 hours, what time is it? 8 + 15 = 23, but on a 12-hour clock that's 23 % 12 = 11. so it's 11am.
in robot code, modulo is great for things like "wrap around to the beginning of a list" or "keep an angle between 0 and 360":
// basic examples int a = 10 % 3; // 10 ÷ 3 = 3 remainder 1 → a = 1 int b = 12 % 4; // 12 ÷ 4 = 3 remainder 0 → b = 0 (divides evenly) int c = 7 % 10; // 7 ÷ 10 = 0 remainder 7 → c = 7 (smaller ÷ bigger = smaller) // FRC use case: cycle through an array of 4 autos int index = 0; index = (index + 1) % 4; // 0→1→2→3→0→1→2→3... wraps around forever
shortcut assignment operators
these are just shorthand for "do the thing and save the result back." you'll write these ALL the time in loops and control code:
double speed = 0.5; // long way vs shorthand — they're exactly the same thing speed = speed + 0.1; // speed is now 0.6 speed += 0.1; // speed is now 0.7 — shorthand for speed = speed + 0.1 speed -= 0.2; // speed is now 0.5 — shorthand for speed = speed - 0.2 speed *= 2.0; // speed is now 1.0 — shorthand for speed = speed * 2.0 speed /= 4.0; // speed is now 0.25 — shorthand for speed = speed / 4.0 // ++ and -- add or subtract exactly 1 int count = 0; count++; // count is now 1 — shorthand for count = count + 1 count++; // count is now 2 count--; // count is now 1 — shorthand for count = count - 1
comparison operators
these compare two values and always give you back a boolean (true or false). you use these constantly in if statements and conditions (which we cover next week):
int speed = 80; boolean r1 = speed == 80; // true — is speed EQUAL to 80? boolean r2 = speed != 80; // false — is speed NOT EQUAL to 80? boolean r3 = speed > 50; // true — is speed GREATER THAN 50? boolean r4 = speed < 100; // true — is speed LESS THAN 100? boolean r5 = speed >= 80; // true — greater than OR equal to? boolean r6 = speed <= 79; // false — less than or equal to 79?
the = vs == trap. = is assignment (stores a value). == is comparison (checks if two things are equal). accidentally writing = when you meant == won't always cause a compile error — it can just silently do the wrong thing. triple-check this any time you're writing a condition.
operator precedence — order of operations
Java follows the same rules as math class: multiplication and division happen before addition and subtraction. when in doubt, use parentheses — they're free and make your intent obvious to anyone reading the code.
int a = 2 + 3 * 4; // 14, not 20 — multiplication happens first int b = (2 + 3) * 4; // 20 — parentheses force addition to go first // FRC example: velocity conversion with explicit parentheses // (much easier to read and verify than a long unseparated expression) double kWheelCircumference_ft = Math.PI * (4.0 / 12.0); // 4-inch radius in feet double speed_fps = encoderRate * (1.0 / 2048) * 10 * kWheelCircumference_ft;
Topic 2 — Coding Prompt
A TalonFX encoder reports 2048 ticks per revolution. Start with int rawTicks = 9216; and calculate three things — print each one:
1. total revolutions as a double (hint: rawTicks / 2048.0 — the .0 matters, try it without and see what breaks)
2. distance in inches — a 4-inch diameter wheel has a circumference of Math.PI * 4, so distance = revolutions × circumference
3. a boolean: has the robot moved more than 12 inches?
Topic 2 — Quick Check
Scope & Naming
two of the most important "invisible" concepts in programming — you can't see scope in the output of your program, and naming doesn't affect whether the code runs. but both of them will absolutely destroy you if you ignore them when working on a team.
rooms and doors — the scope analogy
imagine your house has rooms. stuff you bring into the kitchen (a cup, a bowl, some cereal) only exists in the kitchen. you can't take a kitchen cup into the bedroom just by thinking about it; you'd have to explicitly carry it through the door. scope is the same idea: a variable only exists in the block of code where it was created.
in Java, blocks are defined by curly braces { }. anything declared inside a pair of curly braces only exists within those curly braces. once execution leaves that block, the variable is gone. Java frees up that memory automatically.
"cannot find symbol" is one of the most common compile errors beginners hit, and it almost always means you tried to use a variable outside the scope where it was declared. once you understand scope, you can read that error immediately and know exactly where the fix goes.
public void periodic() { // 'speed' is declared here — it lives for the WHOLE method double speed = 0.5; if (isButtonPressed) { // 'boost' is declared inside this if block // it ONLY exists inside these curly braces double boost = 0.2; speed += boost; // fine — both 'speed' and 'boost' exist here } // 'boost' is GONE here — the if block ended, boost died with it // trying to use boost here would be a compile error: cannot find symbol setMotor(speed); // 'speed' is still alive — it was declared in this method scope }
nested scopes — going deeper
scopes can be nested inside each other like Russian dolls. inner scopes can see variables from outer scopes. outer scopes cannot see variables from inner scopes.
public void runShooter(double requestedSpeed) { // method scope — visible to everything below in this method double safeSpeed = Math.min(requestedSpeed, 1.0); if (safeSpeed > 0.1) { // if-block scope — 'clampedOutput' only lives in here double clampedOutput = safeSpeed * 0.9; // 10% safety margin m_motor.set(clampedOutput); // fine — clampedOutput exists here // this inner scope can see 'safeSpeed' from the outer scope ✓ System.out.println("Running at: " + safeSpeed); } // clampedOutput is gone — can't use it here // safeSpeed is still alive — use it freely }
class scope vs method scope
there's one more level above method scope: class scope. variables declared directly inside a class (not inside any method) are accessible from any method in that class. these are your instance variables — the things that represent the "state" of the object:
public class ShooterSubsystem { // CLASS SCOPE — these are accessible from ANY method in ShooterSubsystem private double m_targetSpeed = 0.0; private boolean m_isSpinning = false; public void setSpeed(double speed) { // METHOD SCOPE — 'clampedSpeed' only lives inside setSpeed() double clampedSpeed = Math.min(speed, 1.0); m_targetSpeed = clampedSpeed; // modifying the class-level variable ✓ m_isSpinning = (clampedSpeed > 0.05); // reading AND writing class vars ✓ } public double getSpeed() { // m_targetSpeed is accessible here too — it's class scope return m_targetSpeed; // clampedSpeed is NOT accessible here — it died when setSpeed() ended } }
access modifiers: private means only THIS class can access it. public means any class can. in FRC, member variables are almost always private — external code uses methods (like getSpeed()) to read and write values instead of reaching into the class directly. this is called encapsulation, and we'll cover it deeply in OOP week.
naming conventions — the full table
on a team with 10+ programmers all editing the same codebase at 1am at a regional, naming conventions are the difference between "oh i see exactly what that does" and "whose code is this and why is nothing labeled." we have a full style guide, but here's the naming cheat sheet:
// BAD — cryptic garbage. no one knows what this does double x1 = 0.8; int y = 3; boolean f = true; // GOOD — completely self-documenting final double kMaxShooterSpeed_mps = 0.8; // k prefix + units in name!! final int kShooterMotorID = 3; boolean m_isShooterEnabled = true;
| What it is | Convention | Example |
|---|---|---|
| Local variable or parameter | camelCase | targetSpeed, motorId, angleRad |
| Instance (member) variable | m_camelCase | m_targetSpeed, m_isRunning, m_encoder |
Constant (final value) | kCamelCase | kMaxSpeed_mps, kMotorID, kGearRatio |
| Class name | PascalCase | ShooterSubsystem, DriveCommand, Constants |
| Method name | camelCase | setSpeed(), getPosition(), isAtTarget() |
unit suffixes: on WRT, we often put units directly in constant names — kMaxSpeed_mps (meters per second), kArmLength_in (inches), kAngle_deg (degrees). this sounds like overkill until you're trying to debug why your robot is driving 3x too fast because someone mixed up meters and feet. the suffix makes unit conversion bugs immediately obvious.
Topic 3 — Quick Check
Type Casting
sometimes you have a value stored as one type and you need it in another type. like you have a speed in int form but the motor library expects a double. or you have a precise double position and you want a whole-number count of full rotations. converting between types is called type casting.
before the syntax, the idea
picture pouring water between containers. if you pour from a small cup into a large bucket, all the water makes it (nothing lost). that's widening conversion. but if you pour from a large bucket into a small cup, the cup can only hold so much and some water spills on the floor. that's narrowing conversion.
in Java: going from a smaller type (like int) to a larger type (like double) is widening. no information is lost and Java does it automatically. going from a larger type (double) to a smaller type (int) is narrowing. you LOSE the decimal part, and Java forces you to explicitly say you're okay with that.
in robot code you're constantly moving data between sensor readings (often double), loop counters (int), motor inputs (double), and display strings (String). knowing when Java will auto-convert and when you need to be explicit prevents real runtime bugs.
widening vs narrowing
// ── WIDENING — automatic, zero data lost ────────────────────────── // int is 32 bits, double is 64 bits — int fits perfectly inside double int ticks = 500; double pos = ticks; // Java automatically converts: pos = 500.0 // no cast needed, no data lost — Java handles this silently // ── NARROWING — must be EXPLICIT, data will be lost ─────────────── // double is 64 bits, int is 32 bits — the decimal part gets chopped double reading = 3.87; int truncated = (int) reading; // you must write (int) to say "yes i know i'm losing data" // truncated = 3 — the .87 is GONE // more examples of narrowing double a = 9.99; int ia = (int) a; // ia = 9, NOT 10 double b = 1.01; int ib = (int) b; // ib = 1 double c = -2.8; int ic = (int) c; // ic = -2 (not -3 — truncates TOWARD ZERO)
truncation is NOT rounding. this trips up basically everyone at first. (int) 3.87 is 3, not 4. (int) 9.99 is 9, not 10. (int) -1.9 is -1, not -2. Java ALWAYS truncates toward zero — it literally just throws away everything after the decimal point. if you need actual rounding, use Math.round(3.87) which gives you 4L (a long), then cast that to int: (int) Math.round(3.87) = 4.
common casting examples in robot code
// scenario 1: encoder math — need double result from int inputs int rawTicks = 3072; int ticksPerRev = 2048; double revolutions = (double) rawTicks / ticksPerRev; // cast first, then divide // without the cast: 3072 / 2048 = 1 (integer division! wrong!) // with the cast: 3072.0 / 2048 = 1.5 (correct) // scenario 2: gear ratio math final double kGearRatio = 8.46; double motorRPM = 5400.0; double wheelRPM = motorRPM / kGearRatio; // ~638.3 RPM int wheelRPM_approx = (int) wheelRPM; // 638 — dropped the .3 // scenario 3: rounding properly (for display purposes) double speed_mps = 3.7892; int rounded = (int) Math.round(speed_mps); // 4 — actually rounds correctly
String conversion
converting numbers to Strings (and back) comes up constantly for Shuffleboard displays, log messages, and parsing config. there are a few different ways to do it:
// ── Number → String (for display and logging) ───────────────────── double speed = 0.75; // method 1: string concatenation — easiest String label1 = "Speed: " + speed; // "Speed: 0.75" // method 2: String.format — gives you control over decimal places String label2 = String.format("%.2f m/s", speed); // "0.75 m/s" (2 decimal places) String label3 = String.format("%.0f RPM", 638.3); // "638 RPM" (0 decimal places) // method 3: Integer.toString / Double.toString String idStr = Integer.toString(7); // "7" // ── String → Number (parsing config, reading sensor text) ───────── String raw = "42"; int parsed1 = Integer.parseInt(raw); // 42 double parsed2 = Double.parseDouble("3.14"); // 3.14
Fill in the Blanks
motorID = 5;
final kMaxSpeed = 1.0;
double val = 4.9;
int result = ()val;
int ticks = 500;
pos = ticks;
Topic 4 — Coding Prompt
Start with these two variables:final double kGearRatio = 8.46;double motorRPM = 5400.0;
Do three things:
1. Calculate wheelRPM by dividing motorRPM by kGearRatio. Print it.
2. Cast wheelRPM to an int and store it in a new variable. Print it — what did casting do to the decimal?
3. Add a comment above each line explaining what it does.
Topic 4 — Quick Check
Comments & Code Syntax
last topic of week 1! this is about the structure of Java files and how to write code that other humans (and future you) can actually understand.
sticky notes for future you (and everyone else)
a comment is text in your code that the compiler completely ignores. it's purely there for humans to read, like sticky notes you leave explaining what's going on.
here's the scenario: it's 1am at a regional. your robot is broken. some subsystem has weird behavior in autonomous and no one knows why. the programmer who wrote it graduated last year. the code has zero comments. the variable names are x1, y, and val2. nobody can fix it in time. that's the actual horror story that motivates good commenting habits.
FRC is a team sport. other people will read your code. you will read your own code six months later with zero memory of what you were thinking. comments are how you leave a trail of breadcrumbs for everyone who comes after you, including yourself.
the three comment types
// ── Type 1: Single-line comment ─────────────────────────────────── // everything after // on this line is ignored by the compiler // use for: quick explanations of a single line, inline notes double speed = 0.5; // starting speed — will be adjusted by driver input /* * ── Type 2: Block comment ───────────────────────────────────────── * spans multiple lines. * use for: explaining a big section of code, temporarily disabling * a chunk during debugging (just wrap it in these and it's gone) * * this entire block is ignored by the compiler */ /** * ── Type 3: Javadoc comment ─────────────────────────────────────── * this generates HTML documentation AND shows as hover tooltips in your IDE. * use above EVERY public class and EVERY public method. * the @param tag explains an input parameter. * the @return tag explains what the method gives back. * * @param speed the target motor speed, from -1.0 (full reverse) to 1.0 (full forward) * @return true if the motor successfully reached the target speed within tolerance */ public boolean setSpeed(double speed) { // implementation here... return true; }
WRT rule: every public method gets a Javadoc comment. every tricky piece of logic gets an inline comment explaining why, not just what. "// set speed" is useless — the code already says that. "// clamp to safe range — motor faults if output exceeds 1.0" is actually helpful. explain the reason, not the action.
the anatomy of a Java file
every Java file has a specific structure that Java expects. if things are in the wrong order, the compiler refuses to compile. here's a labeled breakdown of what a complete robot subsystem file looks like:
package frc.robot.subsystems; // 1. package — tells Java where this file lives in the project // always matches the folder path. always first line. import edu.wpi.first.wpilibj2.command.SubsystemBase; // 2. imports — bring in other classes you need import com.ctre.phoenix6.hardware.TalonFX; // TalonFX = the motor controller our team uses (made by CTRE) /** 3. Javadoc for the class — what does this subsystem do? */ public class ShooterSubsystem extends SubsystemBase { // 3. class declaration // 'extends SubsystemBase' = this is a WPILib (the Java library all FRC teams use for robot programming) subsystem // 4. fields (instance variables) — the "state" of this subsystem private final TalonFX m_motor; private double m_targetSpeed = 0.0; // 5. constructor — runs once when the subsystem is created at robot startup public ShooterSubsystem() { m_motor = new TalonFX(7); // create the motor object on CAN ID 7 } // 6. methods — what this subsystem can DO public void setSpeed(double speed) { m_targetSpeed = Math.min(speed, 1.0); m_motor.set(m_targetSpeed); } public double getSpeed() { return m_targetSpeed; } } // end of class — NO semicolon after the closing brace!!
the semicolon rule
think of semicolons like periods at the end of sentences. every complete statement (an instruction to the computer) ends with a ;. block headers (things that introduce a block of code with { }) do NOT get semicolons.
forgetting a semicolon is literally the #1 beginner compile error. the good news: the compiler will tell you exactly which line it's on.
int x = 5; — every variable declaration and assignment is a statement.motor.set(0.5); — every standalone method call is a complete statement.if (x > 0) { — no semicolon. The opening { starts the block body instead.public class Robot { and public void periodic() { — no semicolon, body follows in { }.case sensitivity and reserved keywords
Java is completely case-sensitive. Speed, speed, and SPEED are three totally different variables. some words are "reserved" — they're part of the Java language itself and you can't use them as variable names. things like class, int, if, return, final, void, new. your IDE will highlight them in a different color to warn you.
// WRONG — 'class' is a reserved keyword, can't use it as a variable name int class = 5; // COMPILE ERROR: 'class' is reserved by Java // WRONG — 'Class' with capital C is totally different from 'class' // Class (capital C) is an actual Java built-in type, unrelated to what you want // WRONG — forgot semicolon on variable declaration int motorID = 5 // COMPILE ERROR: ';' expected // WRONG — semicolon where it doesn't belong if (speed > 0.5); { // this compiles but does something totally wrong!! m_motor.set(speed); } // CORRECT int myClass = 5; String className = "Shooter"; if (speed > 0.5) { m_motor.set(speed); }
the sneaky semicolon bug: if (condition); with a semicolon after the condition is actually valid Java — it creates an if statement with an empty body. the block that follows runs unconditionally. this is a bug that compiles perfectly and is incredibly hard to spot. always check your if/for/while lines for rogue semicolons.
helpful reference: w3schools.com/java/java_syntax.asp has a clean, runnable breakdown of Java syntax rules — good bookmark for when you hit a weird compiler error and don't know what's wrong.
Topic 5 — Quick Check
first time only — set up your project environment:
- install VS Code if you don't have it → code.visualstudio.com
- install the Java extension: open VS Code → press Ctrl+Shift+X → search
Extension Pack for Java→ Install - create a GitHub repository for your project: follow the instructions in this doc :D GitHub Setup Guide
- clone it to your computer: open a terminal (Ctrl+` in VS Code) and run
git clone [URL of your new repo] minibot-project - open the folder in VS Code: File → Open Folder → select
minibot-project
commit often — whenever something major is working, at the end of each week, or before you close your laptop. use commit messages that mean something to a teammate reading them cold.
now create Constants.java directly inside your minibot-project folder. this is the foundation of your entire MiniBot project — every magic number in your robot code lives here, named and typed properly so nothing is mysterious to anyone reading it later.
- Create two
public static final classinner classes:DriveKandShooterK - Inside
DriveK: four motor CAN IDs (FL, FR, BL, BR askFrontLeftIDetc.), a max speed constant in m/s, and a gear ratio - Inside
ShooterK: two motor CAN IDs (top and bottom flywheel), a max RPS target, and a speed threshold double for "at speed" detection - All constants use
kprefix and arepublic static final— no bare numbers anywhere - Add a Javadoc
/** ... */comment above the outerConstantsclass and each inner class explaining what goes in each - Include unit suffixes where the unit matters (speeds in _mps, lengths in _in, etc.)
- Reference: Constants.java from the 2026 season
Weekly Test
covers everything from week 1. longer than the topic quizzes. try it without looking back at the material first, then use it to find gaps. your first attempt score gets sent to the leads as a learning signal (not a grade :)