← back
Lettuce and radishes grown autonomously by Terrabot, with foliage so dense it nearly covers the camera lens. Calibration target and measuring stick visible in the background.
Autonomous growth result, foliage outgrew the measuring system and nearly covered the camera

TL;DR

GoalBuild a fully autonomous greenhouse capable of growing crops (lettuce/radishes) from seed to maturity with minimal human intervention.
ChallengeRunning complex computer vision and constraint-based scheduling entirely on memory-constrained edge hardware (Raspberry Pi).
SolutionA three-layer agent architecture utilizing an OR-Tools CP-SAT solver for daily scheduling, and an ONNX-optimized UNet for plant health monitoring.
ResultSuccessfully completed autonomous multi-week grow periods, achieving ~97% plant pixel extraction accuracy and robust hardware fault detection across 13 sensor channels.
Python PyTorch / ONNX OR-Tools (CP-SAT) Computer Vision Raspberry Pi / Edge ML

System Architecture

Terrabot runs a three-layer agent architecture: a behavioral layer of FSM-driven control behaviors, an executive layer with real-time monitors, and a planning layer that generates and adapts daily schedules using constraint satisfaction. Each layer operates on a 1-second tick cycle, with the planner regenerating schedules daily based on plant growth stage and environmental conditions.

Planning

OR-Tools CP-SAT solver generates daily schedules over 30-minute time blocks, satisfying duration, mutual exclusion, night-time, and spacing constraints across 7 concurrent behaviors.

Executive

Monitors sensor streams, triggers schedule replanning based on plant status, and adjusts behavioral parameters as the growth stage advances, increasing daily watering limits, shifting temperature setpoints post-germination, and feeding updated constraints to the planner so each day's schedule reflects the plant's current needs.

Behavioral

FSM-driven behaviors for lighting, temperature, humidity, soil moisture, image capture, and daily email reporting. Each behavior runs a perceive-act loop with actuator arbitration.

Vision Pipeline

Foliage classification, segmenting plant pixels from soil, hardware, and background, is handled by a fine-tuned UNet with a ResNet34 encoder, pretrained on ImageNet and exported to ONNX.

An initial Vision Transformer approach was abandoned after it caused out-of-memory failures on the Raspberry Pi during inference. The UNet traded a little accuracy (98% to 97%) for a far smaller memory footprint, proving more practical for continuous on-device operation.

The system captures images on a scheduled cadence: an FSM raises LED levels to 400-600 lux, waits for stabilization, then triggers the camera with up to 3 retry attempts on failure.

Before segmentation, a color calibration pipeline normalizes lighting variation across captures. A second UNet detects the physical calibration target, then an affine color transform computed in LAB space maps each image's color distribution to a reference, compensating for LED drift, time-of-day variation, and white-balance shifts.

Plant pixel extraction achieved ~97% accuracy on test data. During deployment, moss growth on the rockwool substrate introduced an out-of-distribution challenge absent from training; the model still excluded the moss from segmentation masks, though it may have affected foliage boundaries.

A height estimation module uses a reference ruler mask and the segmented foliage boundary to measure growth in centimeters, interpolating between tick marks to handle partial occlusion. Both metrics feed a health evaluation function that tracks greenery percentage and height changes over time, generating daily status messages.

Raw greenhouse camera capture showing lettuce and radish plants growing in rockwool cubes with the color calibration target (red, green, blue squares) and ruler measuring stick visible. Wiring and sensor boards visible in the background. UNet foliage segmentation mask overlaid on the raw capture, showing plant pixels in white and all non-plant regions masked to black.
Hover to see the UNet foliage segmentation mask

Sensor Monitoring & Anomaly Detection

Two redundant sensor boards each carry temperature/humidity, light, soil-moisture, and weight sensors, plus a shared reservoir-level sensor, microphone, and camera, 13 channels total.

The microphone verifies actuator operation by detecting pump and fan activity acoustically. Redundancy enables cross-validation: if Board0 and Board1 disagree beyond a threshold, the system flags a potential hardware fault.

Light 0
Light 1
Temp 0
Temp 1
Humidity 0
Humidity 1
Moisture 0
Moisture 1
Weight 0
Weight 1
Reservoir Level
Microphone
Camera

A SAT-based hardware diagnosis system models the full signal and power path, outlet through Raspberry Pi, Arduino, sensor boards, and actuators, as a Boolean constraint network.

When readings deviate from expected values, it generates all minimal diagnoses: the smallest sets of component failures or disconnections that explain the observations, using OR-Tools to enumerate solutions and prune supersets.

Constraint-Based Scheduling

The planner models the 24-hour day as 48 half-hour blocks and solves for a valid schedule satisfying minimum run durations (e.g. 8 hours of light), mutual exclusion between conflicting actuator demands (raising and lowering temperature can't co-occur), night-time caps, and min/max spacing between behavior instances.

The schedule regenerates daily, adapting to the current growth stage, for example, increasing watering limits and shifting temperature setpoints after germination.

Horizontal bar chart showing a generated 24-hour behavior schedule with 30-minute time blocks on the x-axis (0:00 to 24:00) and behavior names on the y-axis (Light, LowerHumid, LowerTemp, RaiseTemp, LowerMoist, RaiseMoist, TakeImage). Each behavior is a different color, with filled blocks indicating when that behavior is active. Light behavior spans most of the daytime hours (8:00–20:00), TakeImage appears in short blocks spaced several hours apart during the day only, and temperature/humidity/moisture behaviors are interleaved to avoid mutual exclusion conflicts.
Generated daily behavior schedule via OR-Tools CP-SAT solver

Automated Reporting

Every 24 hours the agent generates and sends an HTML email with the latest plant photo, foliage-segmentation and height overlays, time-series plots (daily and cumulative) for all sensor channels, and a watering summary with cumulative and delta volumes.

It also estimates plant weight, decomposing total weight change into water content vs. growth using soil-moisture correlation. A health-evaluation string built from greenery and height deltas gives an at-a-glance status per report.

The pipeline runs as its own FSM behavior on a 24-hour cadence, pulling data from across the system, vision outputs from the classifier and height measurer, sensor logs from the logging monitor, and watering totals from the soil-moisture behavior, making it a lightweight observability layer over the full agent.

Excerpt from an automated daily status email showing real sensor readings: 499.0 light, 22.5°C temperature, 87.5% humidity, 1475.02g weight, 611.0 soil moisture, and 6707.78 daily insolation.
Sensor summary from an automated daily status email. Images were lovingly chosen to boost morale.

Growth Timelapse

Images captured automatically by the agent over the grow period, assembled into a timelapse from first sprouts through full canopy coverage.

Autonomous growth over the deployment period, from sprouts to camera occlusion

Results

Plant Pixel Accuracy
~97% extraction accuracy via fine-tuned UNet with ResNet34 encoder
Sensor Channels
13 channels across redundant boards with cross-validation
Scheduling
7 concurrent behaviors scheduled daily via CP-SAT solver
Diagnosis
SAT-based minimal fault diagnosis across full hardware topology
Deployment
Plants outgrew the 9cm measuring stick during autonomous multi-week grow periods
Observability
Automated daily HTML reports with vision outputs, sensor plots, and health evaluation

Note: Because Terrabot was developed in conjunction with a core CMU curriculum project, the source code repository is kept strictly private to comply with Carnegie Mellon University academic policies. Architectural walk-throughs are available for engineering teams upon request.