Fencing works. It also destroys the habitat it's meant to protect.
Construction sites near wildlife corridors kill kangaroos when herds wander onto active roads. The usual fix is physical exclusion — fencing, which is expensive, disrupts the very corridor it's next to, and doesn't scale to sites with large herds.
The alternative under test here is acoustic: directional sound emitters tuned to a kangaroo's hearing range, aiming to nudge herds toward a safe exit corridor instead of walling them out. Nobody had field access, a hardware budget, or live kangaroos to test that on. So the question got answered in simulation first — build the behavior and physics model, and see whether acoustic guidance is even plausible before buying a single directional speaker.
What the research actually says
- Eastern grey hearing range: 1–18kHz, peak sensitivity 2–3.5kHz
- Foot-thump below 7kHz signals predator threat — raises vigilance, not approach
- No confirmed attraction sound exists in the literature for this species
- Commercial deterrents (Roo Guard, Shu Roo, Roobadge) show mixed or no proven results
What actually got built
A 2D grid simulation with a real behavioral model underneath it — not a toy. Every kangaroo carries stress, curiosity, herd cohesion, a panic threshold, and a velocity, and reacts to a physically modelled sound field rather than a scripted path.
Nine weeks, four real work sessions
RLController import, and added the CLI entrypoint. Most of the case study below happened in this single session.RL_ACTION_MAP into config.py, removed dead state fields from SoundEmulator, fixed a control-flow bug in the RL action dispatch, and closed the POC with final documented test results.Four bugs worth explaining
Picked for what they teach, not just that they got fixed. All four are real commits from 27 April – 6 May.
Root cause: two objects held the same data. AcousticField computed the real sound values every step; AcousticEnvironment held a cached copy that agents actually read from. The method that synced the cache, update_acoustic_fields(), existed and worked — it was just never called during a simulation step. Every kangaroo read an all-zero sound field, every step, for the entire early build. That's why Stage 1's acoustic tests failed on 8 March.
Root cause: the action dict always carried every key, with a default value when unset. if "activate_cue" in action is True whenever the key is present — which was always — so the social cue, ultrasound, and intensity branches fired every single step regardless of whether the controller had actually decided to activate them.
in checks presence, not truthiness. Easy to write, easy to miss in review, and it silently turns a conditional into an unconditional — three separate branches, same mistake, same commit.Root cause: get_action() computed an absolute target angle toward the corridor. apply_action() treated it as a relative delta and added it to the current beam angle every step. The beam angle grew without bound instead of tracking the corridor, and the herd's starting position was hardcoded into the angle calculation on top of that, so it never re-aimed as the herd moved.
adjust_beam_direction was ambiguous about absolute vs. relative — renamed at the call site to make the contract obvious rather than leaving a comment that would drift from the code.Root cause: two bugs, same commit, same root cause — control flow drifted out of the block it belonged in. Controller type detection used hasattr(controller, 'model') as a stand-in for "is this the RL controller," which is fragile — any object exposing a .model attribute for any reason would get routed down the RL path. Separately, the RL action-dispatch block was placed after the if/else instead of inside it, so it executed unconditionally, including for the rule-based controller, whose actions are a dict where the dispatch expected an integer key. TypeError, every step.
hasattr checks are a common shortcut for type detection in Python, but they detect shape, not identity. isinstance says what the object actually is.Where the POC actually landed
| Stage | Result | Notes |
|---|---|---|
| 1 — Behavior model | 4/4 Pass | Acoustic gradient influence, ultrasonic repulsion, stress response, herd behavior — core mechanics confirmed working. |
| 2 — Rule-based controller | 3/4 1 Fail | Near-road response, stress reduction, and baseline pass. Corridor guidance fails: starting distance of 40 grid units exceeds effective beam range at current attenuation settings — documented as a parameter limitation, not a code bug. |
| 3 — RL scaffold | 2 Pass / 3 Skip | Environment interface and RL-vs-rule comparison pass. Training convergence, safe-exit-rate, and generalization tests skipped — no trained model exists yet. |
What this doesn't prove
- Behavioral parameters aren't field-validated. Stress accumulation, curiosity response, and acoustic sensitivity curves are estimated from desk research about kangaroo hearing, not measured from real animals.
- No confirmed attraction sound exists in the literature. The mid-frequency guide beam is a working hypothesis, not an established fact — this is the central untested assumption the whole approach rests on.
- Habituation is unmodeled. Real animals adapt to repeated artificial stimuli over time; the simulation doesn't account for that.
- Outdoor sound dispersion and construction background noise are unresolved — the acoustic model runs in a clean simulated field.
Before any hardware gets built
- Train the PPO controller — target >80% safe exit rate
- Sensitivity analysis on curiosity, herd cohesion, and gradient strength
- Baseline comparison: random walk vs. acoustic-guided, to prove the influence is real and not noise
- Monte Carlo runs across multiple seeds for statistical validation
- Hardware prototype — Raspberry Pi, directional speaker, PIR sensor — only once simulation results hold up
- Field testing — requires a wildlife permit and ethics clearance
Acoustic guidance is plausible in simulation and unproven in the field. That's not a hedge — it's the actual, disciplined output of a proof-of-concept: don't spend a hardware budget or ask for a wildlife permit until the physics and behavior model earn it. The model earned a "maybe, worth prototyping." It didn't earn a "yes."