Get started¶
This guide creates a complete HELM program with autonomous and driver-controlled behavior.
What you need¶
- Python 3.10 or newer.
- The HELM extension running in the editor.
- A student Python file selected in the extension.
- A Controller connected through the extension when using real hardware.
The extension launches the selected script with the HELM library and local link already configured. There is no need to copy the API into your project or open the Controller's serial port from Python.
1. Import the hardware types¶
Robot is the main program object. IMU, Thruster, and Servo are type
tokens used to describe the hardware connected to each port.
2. Declare the robot¶
robot = Robot()
robot.configure(
sensors={"S2": IMU},
effectors={
"A1": Thruster,
"A2": Thruster,
"A5": Servo,
},
pid={
"A1": (0.8, 0.1, 0.0),
"A2": (0.8, 0.1, 0.0),
},
)
Sensor ports begin with S; effector ports begin with A. Configuration is
sent through the extension and checked against the robot's response before the
program can arm.
3. Write the callbacks¶
initialize runs once after arming. autonomous and driver run when the
matching phase begins.
def initialize(robot):
robot.servo("A5").angle(0)
def autonomous(robot):
while robot.running:
reading = robot.imu.read()
if reading.ok and reading.heading >= 90:
robot.thruster("A1").set_duty(0)
robot.thruster("A2").set_duty(0)
else:
robot.thruster("A1").set_duty(30)
robot.thruster("A2").set_duty(-30)
def driver(robot):
previous_a = False
while robot.running:
forward = robot.controller.left_stick.y
turn = robot.controller.right_stick.x
left = clamp(forward + turn, -100, 100)
right = clamp(forward - turn, -100, 100)
robot.thruster("A1").set_duty(left)
robot.thruster("A2").set_duty(right)
a_is_down = robot.controller.button("A").is_down
if a_is_down and not previous_a:
robot.servo("A5").angle(90)
previous_a = a_is_down
def clamp(value, low, high):
return max(low, min(high, value))
Always check a sensor reading's ok field before using it for robot behavior.
Buttons report their current level only, so the example compares the current and
previous values to detect a new press.
4. Run the match¶
run() blocks while the session is active. It arms the robot, dispatches each
callback as phases change, idles outputs when a callback returns, and disarms
when the session ends.
Complete program¶
from helm import IMU, Robot, Servo, Thruster
robot = Robot()
robot.configure(
sensors={"S2": IMU},
effectors={"A1": Thruster, "A2": Thruster, "A5": Servo},
pid={"A1": (0.8, 0.1, 0.0), "A2": (0.8, 0.1, 0.0)},
)
def clamp(value, low, high):
return max(low, min(high, value))
def initialize(robot):
robot.servo("A5").angle(0)
def autonomous(robot):
while robot.running:
reading = robot.imu.read()
if reading.ok and reading.heading >= 90:
robot.thruster("A1").set_duty(0)
robot.thruster("A2").set_duty(0)
else:
robot.thruster("A1").set_duty(30)
robot.thruster("A2").set_duty(-30)
def driver(robot):
previous_a = False
while robot.running:
forward = robot.controller.left_stick.y
turn = robot.controller.right_stick.x
robot.thruster("A1").set_duty(clamp(forward + turn, -100, 100))
robot.thruster("A2").set_duty(clamp(forward - turn, -100, 100))
a_is_down = robot.controller.button("A").is_down
if a_is_down and not previous_a:
robot.servo("A5").angle(90)
previous_a = a_is_down
robot.run(
initialize=initialize,
autonomous=autonomous,
driver=driver,
)
Next, read Hardware configuration and Match lifecycle for the rules behind this program.