Adding a lock
Goal: Add a safety lock that halts robot motion when active.
Tutorial level: Intermediate
Time: 15 minutes
Background
A lock is a safety mechanism that prevents the robot from moving when active –
similar to an E-stop or deadman switch. In teleop_modular, locking is implemented
using a state input: a button whose value is controlled by commands rather than
directly from a hardware input source.
Control modes check this state button on every update. When it is true, the control
mode stops publishing motion commands and publishes a halt message instead.
Prerequisites
You should be familiar with the basics of configuring a teleop package:
Tasks
1. Add lock and unlock commands
State inputs are created automatically when a command first references their name. To
create a locked state button, declare two set_button commands in your teleop
parameter file:
teleop_arm:
ros__parameters:
# ...
commands:
names:
- lock
- unlock
lock:
on: "lock/down"
type: set_button
name: "locked"
value: true
unlock:
on: "unlock/down"
type: set_button
name: "locked"
value: false
type: set_button– sets the named state button to the given value when the command fireson: "lock/down"– fires once when thelockinput button is pressed (transitions from false to true)on: "unlock/down"– fires once when theunlockinput button is pressed
3. Confirm your control mode respects the lock
Built-in control modes like teleop_modular_twist/TwistControlMode automatically
check the locked state button and halt when it is true. If you are writing a
custom control mode, check is_locked() in your on_update() and publish a halt
message:
return_type MyControlMode::on_update(
const rclcpp::Time & now, const rclcpp::Duration & period) override
{
if (is_locked()) {
publish_halt_message(now);
return return_type::OK;
}
// ... normal update logic ...
}
4. Add log messages when the lock state changes
It is good practice to log whenever the system is locked or unlocked. Add log
commands that trigger on the state button’s own events:
commands:
names:
- lock
- unlock
- log_locked
- log_unlocked
lock:
on: "lock/down"
type: set_button
name: "locked"
value: true
unlock:
on: "unlock/down"
type: set_button
name: "locked"
value: false
log_locked:
on: "locked/down"
type: log
message: "Locked"
log_unlocked:
on: "locked/up"
type: log
message: "Unlocked"
Notice that log_locked fires on "locked/down" – the event for the state
button locked itself becoming true – not the physical lock button. This means
the log fires whenever the state changes, regardless of what caused it.
Summary
Complete lock configuration using a gamepad:
teleop_arm:
ros__parameters:
# ...
commands:
names:
- lock
- unlock
- log_locked
- log_unlocked
lock:
on: "lock/down"
type: set_button
name: "locked"
value: true
unlock:
on: "unlock/down"
type: set_button
name: "locked"
value: false
log_locked:
on: "locked/down"
type: log
message: "Locked"
log_unlocked:
on: "locked/up"
type: log
message: "Unlocked"
joy_input_source:
ros__parameters:
# ...
remap:
buttons:
lock:
from: "BACK"
unlock:
from: "START"
See also
Commands and state inputs – full reference for all command types and events