Kenate

Tutorial

Build a Hexapod

A six-legged walking robot is the ultimate test of state management. Let's build one with Kenate.

Hexapod robot

What We're Building

A hexapod that can:

  • Idle - Stand still and wait
  • Walk - Move forward using a tripod gait
  • Turn - Rotate in place
  • Stop - Emergency halt (for when things get spicy)

Step 1: Create the Project

$ kenate init hexapod
$ cd hexapod

Step 2: Configure Hardware

Edit hardware.toml for 18 servos (3 per leg x 6 legs). Yeah, that's a lot of legs.

[driver]
type = "raspberry_pi"

[motors]
# Leg 1 (Front Left)
leg1_coxa = { pin = 0, type = "servo" }
leg1_femur = { pin = 1, type = "servo" }
leg1_tibia = { pin = 2, type = "servo" }

# Leg 2 (Front Right)
leg2_coxa = { pin = 3, type = "servo" }
leg2_femur = { pin = 4, type = "servo" }
leg2_tibia = { pin = 5, type = "servo" }

# ... continue for legs 3-6

Step 3: Create IdleState

Create states/idle.py:

import kenate

class IdleState(kenate.BaseState):
    def on_enter(self):
        self.log("Hexapod idle. Waiting for command...")
        # Set all legs to neutral position
        for i in range(18):
            self.set_servo_angle(i, 90)

Step 4: Create WalkState

The tripod gait alternates two sets of 3 legs. It looks cooler than it sounds. Create states/walk.py:

import kenate
import math

class WalkState(kenate.BaseState):
    def on_enter(self):
        self.phase = 0
        self.log("Walking!")
    
    def on_update(self):
        # Tripod gait: legs 1,4,5 move, then legs 2,3,6
        t = self.get_time()
        
        # Group A: legs 0, 3, 4 (indices for coxa servos)
        group_a = [0, 9, 12]
        # Group B: legs 1, 2, 5
        group_b = [3, 6, 15]
        
        # Sine wave for smooth motion
        wave = math.sin(t * 4) * 30  # ±30 degrees
        
        for idx in group_a:
            self.set_servo_angle(idx, 90 + wave)
        for idx in group_b:
            self.set_servo_angle(idx, 90 - wave)
        
        # Check for obstacle
        if self.get_distance(0) < 20:
            self.change_state("Stop")

Step 5: Create StopState

Emergency stop. For when things don't go according to plan. Create states/stop.py:

import kenate

class StopState(kenate.BaseState):
    def on_enter(self):
        self.log("EMERGENCY STOP!")
        # Return all servos to neutral
        for i in range(18):
            self.set_servo_angle(i, 90)

Step 6: Wire It Up

Create main.py:

import kenate
from states.idle import IdleState
from states.walk import WalkState
from states.stop import StopState

engine = kenate.Engine()
engine.load_config("hardware.toml")

engine.register_state("Idle", IdleState())
engine.register_state("Walk", WalkState())
engine.register_state("Stop", StopState())

engine.start("Idle")

Step 7: Run It!

$ kenate run

✓ Build up-to-date
Starting Engine...
[INFO] Hexapod idle. Waiting for command...

To switch to walking, you'd trigger self.change_state("Walk")from IdleState. Maybe when a button is pressed or a command is received.

Next Steps

  • Add a TurnState for rotation
  • Use SequenceState to chain movements
  • Launch the Visualizer to debug leg movements
  • Add IMU input for balance correction

"If it walks like a bug, it's probably your hexapod running Kenate. Ship it."