IROS 2026 Arizona State University Cornell University

Predicting plant shadows
for lighting-aware robotic agriculture.

A Helios and UE5 simulation pipeline plus a ControlNet-conditioned diffusion model that generate realistic, time-varying plant shadow maps from a fixed top-down camera, enabling in silico evaluation of supplemental lighting and its downstream effect on canopy photosynthesis.

Longchao Da1,*, Xiaoou Liu1,*, Xingjian Li2,*, Lirong Xiang2,†, Hua Wei1,† 1School of Computing and Augmented Intelligence, Arizona State University, Tempe, AZ   2Automation and Robotics Laboratory, Cornell University, Ithaca, NY *Equal contribution   Co-corresponding authors: lxiang@cornell.edu, hua.wei@asu.edu
0Image pairs
0Crop species
0Plant models
0Light positions
1920×1080Resolution
1CollectHelios · UE5 2Preprocesssource·target·prompt 3TrainControlNet + SD2.1 4Infershadow map 5PhotosynthesisNRH gain
PlantShade overview
Overview. A camera and a supplementary light on a circular trajectory capture plant image, shade ground truth, and depth; a generative model turns plant appearance + light position into a shadow map, supporting lighting optimization, light-exposure analysis, and robotic pruning.
Step 1 · Data collection

A Helios and UE5 pipeline for photorealistic shade.

We bridge the biophysical procedural modeling of Helios with the real-time photorealistic rendering of Unreal Engine 5 via ROSbridge/ROSIntegration. Plant meshes (OBJ + MTL) are streamed into UE5 and rendered from a fixed nadir camera, producing aligned RGB, plant-mask, and shadow-intensity ground truth as a supplementary light orbits the canopy.

Helios-UE5 data generation pipeline
Fig. 2. Helios procedural meshes stream into UE5 via ROSbridge/ROSIntegration; SceneCapture renders image data while a PointLight orbits along the light trajectory.

Dataset specifications

Total image pairs38,500
Resolution1920 × 1080
Camera height1.8 m (nadir view)
Plant speciesTomato · Soybean · Sugar beet · Strawberry
Plant age range7 to 119 days
Layout configs1×1 · 1×3 · 3×5 (50 cm spacing)
Solar elevation52.24°
Supp. light orbit1.8 m height · 1.25 m radius · 100 positions
ModalitiesRGB · Plant mask · Shadow mask · Depth
Download the simulator / release ↗
tomato
TomatoPmax 17.5
soybean
SoybeanPmax 32.5
sugar beet
Sugar beetPmax 20.0
strawberry
StrawberryPmax 12.0
growth stages
Growth stages. Aligned RGB and shadow ground truth across days 7 → 70 for strawberry and soybean.
Helios vs UE5 sun coverage
Fig. 3. UE5 shade intensity tracks Helios' sunlit-fraction curve as the light orbits, validating the real-time renderer.
Step 2 · Preprocessing

From raw renders to model inputs.

After downloading the per-scene zips from the data-collection release, 1_extract_shadow.py turns each rendered frame into the training target: it thresholds the shadow-intensity render, keeps the plant region, and composites a color-coded map (background #a0a0a0, skeleton #ffffff, shadow #070707), writing both target/ and the raw targetRaw/. Each sample becomes a (source, target, prompt) triplet, resized to 512×512, shuffled (seed 42) and split 80/20.

🌑 Step 1 · Extract shadow targets
# unzip a scene, then extract shadow maps
unzip data/examples/<scene>.zip -d data/PlantShadeUnzip/

python 1_extract_shadow.py \
    --base_root data/PlantShadeUnzip \
    --out_root  data/shadow
# -> data/shadow/target/ and data/shadow/targetRaw/
🧩 Step 2 · Triplet format + split
{"source": ".../seg_54.png",     # plant skeleton / edge
 "target": ".../target/.../seg_54.png",
 "prompt": "122.786 -23.423 280.000"}   # light x y z

# pair source/target/prompt, 80/20 split (seed 42)
python 2_build_split.py \
    --source_root data/PlantShadeUnzip \
    --target_root data/shadow/target --out_dir data

30,900 pairs for training and in-domain eval, 7,600 held out for out-of-domain (OOD) evaluation.

Interactive · Circular supplementary light

Watch the shadow follow the light.

The supplementary light orbits the canopy along a fixed circle (1.25 m radius, 1.8 m height). Pick a layout, then drag the slider or press ▶ Play to move the light through its sampled positions and watch the shadow map evolve for all four crops at a mid growth stage.

Circular supplementary light · four crops
position 1 / 100
azimuth 0°
tomato shadow
Tomato
soybean shadow
Soybean
strawberry shadow
Strawberry
sugar beet shadow
Sugar beet
Step 3 · Generative shade model

ControlNet-conditioned diffusion.

A text encoder maps the light-position prompt to an embedding injected via cross-attention, while a ControlNet branch fuses the structural condition (edge/mask) with the appearance prior and guides a Stable Diffusion v2.1 U-Net. Because appearance and structure stay fixed, variation in the output is driven purely by the moving light.

PlantShade model architecture
Fig. 4. A free-form text prompt (light position) is encoded and injected via cross-attention; a ControlNet branch fuses RGB + Canny-edge structure to guide the diffusion U-Net toward the shadow map.
🚀 Step 3 · Train the shade model
# ControlNet branch on a frozen SD v2.1 backbone
python 3_train.py

# key config (override via env vars)
init_ckpt     = models/control_sd21_ini.ckpt
batch_size    = 16   # PS_BATCH
learning_rate = 1e-5 # PS_LR
resolution    = 512 × 512
BackboneStable Diffusion v2.1
ControlControlNet (edge + appearance)
Conditiontext prompt = light position
Objectivedenoising ε-prediction loss
Step 4 · Inference

Plant appearance plus light prompt to shadow map.

Given a plant image and a text prompt for the light position, the model generates the shadow map without full 3D rendering. Below are representative cases where the generated shadow closely matches ground truth across the four crops, growth stages, and layouts.

Generated shadow maps (trained checkpoint, epoch 51)

input plant (RGB) predicted shadow
Plant (RGB)
Predicted shadow

Drag the divider to wipe between the input plant and the model's predicted shadow map. All four are held-out samples generated with DDIM (50 steps, guidance 9.0); predictions are upscaled to the capture resolution.

qualitative generation results
Fig. 6. For each case: raw image, ground truth, skeleton input, and the PlantShade-generated shadow (right of the dashed line). Results span species, growth stages, and 1×1 / 1×3 / 3×5 layouts.
🔮 Run inference on the test split
# checkpoint: huggingface.co/xiao0o0o/PlantShade-ControlNet
PS_CKPT=/path/to/plantshade_epoch51.ckpt \
PS_TEST_JSON=data/test_split.json python 4_infer.py

# key defaults
config      = models/cldm_v21.yaml
ddim_steps  = 50
guidance    = 9.0
shade_thresh = 40
# -> outputs/predictions/generated_*.png (pure) + compare_*.png
Aligned modalities

One frame, five registered views.

Every capture provides spatially-aligned RGB, structural edges, plant mask, shadow map, and a depth map used downstream for physically-grounded leaf-area and photosynthesis estimation.

rgb
RGB
Plant appearance I₀
edge
Edge
Structural cue S
mask
Plant mask
Leaf region
shadow
Shadow map
Target Mₜ
depth
Depth
For leaf-area A
Quantitative results

Consistently ahead of Stable Diffusion.

PlantShade vs. a Stable Diffusion baseline across species and layout complexity. Higher is better for mIoU / B-IoU; lower is better for LPIPS / MSE. Columns marked OOD are out-of-domain.

Both methods degrade under OOD placement, confirming the intrinsic difficulty of distribution shift, yet PlantShade keeps a clear margin in every setting.

ID to OOD performance
Fig. 5. Left: MSE degradation from in-distribution to OOD. Right: on the 3×5 OOD setting, PlantShade still dominates Stable Diffusion across all four metrics.
Step 5 · Downstream · Photosynthetic gain

From shadow maps to canopy carbon assimilation.

Predicted shadow maps and rendered depth maps drive a non-rectangular hyperbola (NRH) light-response model. Leaf area comes from depth under a pinhole camera (f=872.72 px); the shaded fraction f weights sunlit vs. shaded photosynthesis into a canopy rate. Explore each species' light-response curve below.

P(I) = 1⁄2θ [ αI + Pmax − √((αI+Pmax)² − 4θαI·Pmax) ]
Pmax32.5µmol CO₂ m⁻² s⁻¹
α (quantum yield)0.05mol CO₂ mol⁻¹
θ (convexity)0.7
I₀ (ambient PAR)1000µmol m⁻² s⁻¹
β (shade transmittance)0.3
🌿 Step 5 · Estimate canopy photosynthesis
python 5_photosynthesis.py \
    --split data/test_split.json \
    --pred_dir outputs/predictions \
    --output_csv outputs/photosynthesis.csv

def nrh(I, alpha, P_max, theta):        # non-rectangular hyperbola
    a = alpha*I + P_max
    disc = max(a**2 - 4*theta*alpha*I*P_max, 0)
    return (a - np.sqrt(disc)) / (2*theta)
📐 Leaf area and shaded fraction
# leaf area from depth (pinhole, fx=fy=872.72)
A_px = depth**2 / (fx*fy)
A_total  = A_px[leaf_mask].sum()
f        = A_px[shadow_mask].sum() / A_total   # shaded fraction

P_canopy = (1-f)*nrh(I0, ...) + f*nrh(beta*I0, ...)
photosynthetic gain pipeline and results
Fig. 7. Depth + predicted shadow → leaf area and shaded fraction → NRH canopy rate. Optimal supplemental light placement consistently raises canopy photosynthesis across all species and layouts.
Applications

What realistic shade prediction unlocks.

💡

Supplemental lighting optimization

Evaluate light placement and trajectory in silico to maximize canopy photosynthesis before physical deployment.

🌡️

Microclimate analysis

Spatially-resolved shade sequences inform planting density, row orientation, and sensor placement.

✂️

Shade-aware pruning

Simulate branch removal to reduce self-shading and improve canopy light uniformity and yield.

🤖

Sim-to-real perception

Large-scale pixel-aligned RGB/shadow pairs for lighting-invariant robot perception under diverse illumination.

Get the data

Load PlantShade.

🤗 Dataset + model on HuggingFace
from huggingface_hub import hf_hub_download

# one scene from the dataset
zip_path = hf_hub_download(
    "xiao0o0o/PlantShade",
    "tomato_seed2_14_7_77.zip", repo_type="dataset")

# trained checkpoint (~13 GB)
ckpt = hf_hub_download(
    "xiao0o0o/PlantShade-ControlNet",
    "plantshade_epoch51.ckpt")
⬇️ Data collection release
# Helios-UE5 simulator + raw captures
# github.com/ARLabXiang/AgriRoboSimUE5
#   releases/tag/plantshade
📄 Cite
@inproceedings{da2026plantshade,
  title     = {PlantShade: Predicting Plant Shadows for
               Lighting-Aware Robotic Agricultural Operation},
  author    = {Da, Longchao and Liu, Xiaoou and Li, Xingjian
               and Xiang, Lirong and Wei, Hua},
  booktitle = {IROS},
  year      = {2026}
}