§ 01
A function becomes a control
Install it with pip install cognira-robotics. Then put a decorator on a function you already have. @robot.button runs it once per press. @robot.slider hands it a number, @robot.toggle a true or false, @robot.joystick an x and a y, and @robot.text whatever you type. @robot.hold tells it when a button goes down and when it comes back up.
hello_robot.py
from cognira_robotics import Robot
robot = Robot("Hello robot")
@robot.button("Wave", key="w")
def wave():
robot.log("waving")
robot.run()The first time you run it, it prints a code and opens cognira.dev so you can approve it. After that the robot is listed under Robotics in the chat sidebar whenever its script is running, with each control shown next to the Python function it calls. The SDK only makes outbound HTTPS requests, so a robot on home Wi-Fi needs no port forwarding. It has no dependencies outside Python's standard library.
§ 02
The first board: an ESP32 and a servo
An ESP32 can't run desktop Python, so the SDK runs on the computer it is plugged into and passes commands down the USB cable. The board runs a small sketch that reads one line at a time: a 120 moves the servo to 120°, off lets it go limp, and status reports where it is. Raspberry Pis, Jetsons and Arduinos on a serial port all fit the same pattern.
esp32_servo.py
import serial # pip install pyserial
from cognira_robotics import Robot
board = serial.Serial("COM7", 115200) # the ESP32 on USB
robot = Robot("ESP32 servo")
def send(line):
board.write((line + "\n").encode())
@robot.slider("Angle", min=25, max=155, default=90, unit="°")
def angle(degrees):
send(f"a {degrees}")
@robot.joystick("Steer")
def steer(x, y):
send(f"a {90 + x * 65:.0f}")
@robot.button("Sweep", key="s")
def sweep():
for target in (25, 155, 25, 155):
send(f"a {target}")
if not robot.sleep(0.6): # False the moment Stop is pressed
return
@robot.on_stop
def stop():
send("off") # let the servo go limp
robot.run()That's the whole bridge. The full example in the SDK also reads the board's status line every second and shows the real angle with robot.show(). That gave us a way to check each test against what the board itself reported. A slider set to 140 moved the servo to 140°. A value of 999 was capped at the slider's 155° limit before it reached the board. Full left on the joystick went to 25°, and half right went to 122°.
§ 03
Stop has to work every time
A robot is not a chat window. A late button press can knock something off a table. So the safety behaviour is built into the SDK rather than left to each script:
- Stop runs at once. The red button, or Esc, calls your
@robot.on_stopfunction even while another function is still running. Anything queued behind it is dropped. In our test, Stop arrived a second into a sweep. The servo went limp mid-swing at 104°, and the sweep'srobot.sleep()woke up and returned. - Held controls need a pulse. While you hold the joystick, the page re-sends its position four times a second. When that stops, because you let go or closed the tab or the Wi-Fi dropped, the robot re-centres after 1.5 seconds. We steered the servo hard left and then stopped sending, and it came back to 90° by itself.
- Late commands are dropped. A button press that can't be delivered within 10 seconds is discarded, and a joystick position within 1.5 seconds. Neither is replayed into a robot that has just reconnected.
§ 04
No account? Try it on your desk
robot.run(local=True) serves the same control panel from the robot itself at localhost:8700, with no sign-in. It's the quickest way to get the wiring right before you link the robot. It listens only on your own machine, so other people on your network can't drive it.
The SDK is cognira-robotics on PyPI, and the Robotics page has the quickstart. Robotics is in the site header, and inside chat it sits in the sidebar under Workspace.