Unit 01 · lesson
Turn a Robot Rule Into a Method
The previous lesson put everything inside main. That is fine for a tiny demonstration, but real programs become unreadable if every rule lives in one giant method.
A method gives a piece of behavior a name.
Suppose the program needs a simple battery-warning rule:
Warn when the battery percentage is below 20.
You could write the comparison directly in main:
public class RobotStatus {
public static void main(String[] args) {
int batteryPercent = 18;
boolean needsCharge = batteryPercent < 20;
System.out.println("needsCharge=" + needsCharge);
}
}
Output:
needsCharge=true
The program works, but the rule is buried inside main. A named method makes the intent easier to find and reuse.
A method has inputs and a result
Rewrite the program like this:
public class RobotStatus {
static boolean needsCharge(int batteryPercent) {
return batteryPercent < 20;
}
public static void main(String[] args) {
int batteryPercent = 18;
boolean warning = needsCharge(batteryPercent);
System.out.println("needsCharge=" + warning);
}
}
Focus on this method:
static boolean needsCharge(int batteryPercent) {
return batteryPercent < 20;
}
Read it from left to right.
static lets this simple application call the method from main without creating an object first.
boolean is the return type. It tells Java that this method returns either true or false.
needsCharge is the method name.
int batteryPercent is a parameter. The method receives one integer input and temporarily names it batteryPercent while the method runs.
The return statement sends the result back to the caller.
Calling the method
This line:
boolean warning = needsCharge(batteryPercent);
calls the method and passes the current value of batteryPercent as the argument.
If batteryPercent is 18, the method evaluates:
18 < 20
which is true.
If the value is 87, it evaluates:
87 < 20
which is false.
The method does not remember the previous call. Each call receives an input, evaluates the rule, and returns a result.
The boundary value matters
Test three values:
| Battery percentage | Expression | Result |
|---|---|---|
| 18 | 18 < 20 | true |
| 20 | 20 < 20 | false |
| 21 | 21 < 20 | false |
The value 20 is important because it sits exactly at the threshold.
If the real policy is “warn at 20 percent or lower,” then this method is wrong:
return batteryPercent < 20;
It should be:
return batteryPercent <= 20;
Java will run either version exactly as written. The compiler cannot decide what the robot team's battery policy was supposed to be.
This is why boundary values deserve attention. A one-character operator change can change the behavior of the system without causing a compile error.
Methods make rules easier to test
A named method gives you something specific to test later.
For example:
needsCharge(18)
needsCharge(20)
needsCharge(87)
Each call asks the same rule a different question.
That is much easier to reason about than copying the comparison into several parts of the program.
It also reduces the chance that one part of the program uses < 20 while another quietly uses <= 20.
A second robot rule
Suppose a front range reading is considered too close when it is below 0.30 meters.
You could write:
static boolean obstacleTooClose(double rangeMeters) {
return rangeMeters < 0.30;
}
Now examine these calls:
obstacleTooClose(0.42) // false
obstacleTooClose(0.30) // false
obstacleTooClose(0.25) // true
Again, the exact boundary is part of the engineering rule.
The method also assumes that the input is really measured in meters. If another part of the program passes 25 meaning centimeters, Java sees only a double. The type is compatible, but the unit is wrong.
You will deal with units directly in Week 2.
A method result is not a motor command
This is a critical robotics boundary.
boolean blocked = obstacleTooClose(0.25);
can establish that the method returned true for the supplied value.
It does not establish that:
- the reading came from a live sensor;
- the reading is fresh;
- a WPILib command was interrupted;
- a ROS 2 message was received;
- a motor controller stopped;
- a physical robot avoided a collision.
The method is application logic. Other software has to connect that logic to robot behavior.
Where WPILib fits
WPILib is an open-source Java robotics framework used in FRC software. Its command-based architecture gives robot actions and mechanisms named responsibilities rather than putting everything into one giant loop.
That design idea matches what you are learning here: named behavior is easier to reason about than anonymous logic scattered through a program.
Do not overextend the comparison. A Java method is not automatically a WPILib command, and neither one is automatically a ROS 2 node or action. Those systems add their own runtime behavior and contracts.
Common mistakes
Returning the wrong type
This method claims to return a boolean:
static boolean needsCharge(int batteryPercent) {
return 18;
}
Java rejects it because an int cannot satisfy the declared boolean return type.
Forgetting to return a result
static boolean needsCharge(int batteryPercent) {
batteryPercent < 20;
}
The expression is evaluated and discarded. The method promises a boolean result but never returns one.
Hiding the threshold in several places
If the same 20 appears in five unrelated comparisons, changing the policy becomes error-prone. A named method keeps the rule in one obvious place.
Try it yourself
Write a method named:
static boolean batteryHealthy(int batteryPercent)
Use this rule:
A battery is considered healthy when the value is 20 percent or higher.
Then predict the result for:
19
20
21
Next, write:
static boolean insideRange(double rangeMeters)
that returns true only when the value is between 0.10 and 2.00 meters, inclusive.
Test your reasoning with:
0.09
0.10
0.42
2.00
2.01
The next lesson moves outward from local Java logic. You will compare ordinary Java application code with a WPILib robot application, a ROS 2 runtime, and physical hardware so you know which tool can answer which question.