Skip to main content

Lesson 9.2: Limiting Servo Travel Safely with scaleRange()


Technical Context

Most robot mechanisms have physical stops that prevent a servo from completing its full 180-degree rotation. Using scaleRange() prevents the software from attempting to drive the servo through a physical barrier, which protects the internal motor and mounting brackets from the high-current stall that occurs when a servo is forced against a hard stop.


Why scaleRange() Protects Your Mechanism

The scaleRange(double min, double max) method redefines the logical 0.0 to 1.0 window to map onto a specific physical subsection of the servo's total travel. Once called in init(), any subsequent setPosition() call operates within the new bounds:

  • setPosition(0.0) moves to the physical angle corresponding to min
  • setPosition(1.0) moves to the physical angle corresponding to max
  • setPosition(0.5) moves to the midpoint between min and max

This is a clean way to document hardware constraints in code — rather than remembering "don't go below 0.3" everywhere in your OpMode, you call scaleRange(0.3, 0.9) once in init() and the SDK enforces it automatically for the lifetime of that OpMode run.

Both parameters must be between 0.0 and 1.0, and min must be less than max.


Annotated Code

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.Servo;

@TeleOp(name="ScaleRange_Demo")
public class ScaleRangeDemo extends OpMode {

private Servo delivery;

@Override
public void init() {
delivery = hardwareMap.get(Servo.class, "delivery");

// Limit range to the middle 50% of travel to avoid mechanical binding
// setPosition(0.0) will now move to 0.25, setPosition(1.0) to 0.75
delivery.scaleRange(0.25, 0.75);

delivery.setPosition(0.0); // Safe start at the constrained minimum
telemetry.addData("Delivery", "Range constrained: 0.25 to 0.75");
}

@Override
public void loop() {
if (gamepad1.a) {
delivery.setPosition(1.0); // Moves to physical 0.75
} else if (gamepad1.b) {
delivery.setPosition(0.0); // Moves to physical 0.25
}
telemetry.addData("Position Command", delivery.getPosition());
}
}

Fill-in-the-Blank Practice

  1. The scaleRange() method takes two __________ parameters to define the physical window.
  2. After calling scaleRange(0.5, 1.0), a setPosition(0.0) command will actually move the servo to its physical __________ position.
  3. To reset the servo to its factory full range, you would call scaleRange(__________, 1.0).
Show answers
  1. double
  2. 0.5 (the minimum of the defined range)
  3. 0.0

Template Challenge

Robot Scenario: Your scoring arm hits a metal bar if the servo goes below 0.3 or above 0.9. Configure the "arm" servo to operate safely within these bounds, then command it to its open (1.0) and closed (0.0) positions using the bumpers.

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.Servo;

@TeleOp(name="Range_Safety_Challenge")
public class RangeSafety extends OpMode {

private Servo arm;

@Override
public void init() {
arm = hardwareMap.get(Servo.class, "arm");

// INSERT CODE HERE: Constrain the range between 0.3 and 0.9
// INSERT CODE HERE: Set initial position to 0.0 (within the constrained range)
}

@Override
public void loop() {
if (gamepad1.right_bumper) {
arm.setPosition(1.0); // Moves to physical 0.9
} else if (gamepad1.left_bumper) {
arm.setPosition(0.0); // Moves to physical 0.3
}
telemetry.addData("Arm Position", arm.getPosition());
}
}
Show answer
@Override
public void init() {
arm = hardwareMap.get(Servo.class, "arm");
arm.scaleRange(0.3, 0.9);
arm.setPosition(0.0);
telemetry.addData("Arm", "Range set: 0.3 to 0.9");
}

Ready to move on?

Sign in with Google to save your progress with Telemark, or continue without saving.