https://www.twobraids.com/2024/01/air-cannon.html
Skip to main content
twobraids
Search
Search This Blog
[ ]
[SUBMIT]
Finding The Air Cannon
January 28, 2024
< Newer Article
< Newer Story
Home [?]
Older Article >
Older Story >
[geese]
tldr; An agricultural air cannon began firing every two minutes all
night long disrupting the sleep of many in my community. I used
Google Maps, three listening posts, and a programmed simulation to
pinpoint the field hosting the air cannon. The county tax assessor
office identified the land owner. I had a phone conversation with the
farm manager. That conversation was coincident with the cessation of
the nighttime air cannon. I can sleep again.
[screen-shot]
120dB;
serious hearing damage;
5 gallons of propane gives
18000 blasts
The use of agricultural air cannons south of Corvallis has been
extreme this month. Farmers with field crops are often beset with
Canadian Geese overwintering in the Willamette Valley. To scare the
geese away, they frequently use propane air cannons on timers.
Starting on January 5th, an air cannon began firing every two minutes
all day and throughout the night. My sleep and that of many neighbors
was disrupted for nearly a month.
Trying to figure out where the cannon shots originated, I drove out
and listened from several locations. It was loud on Airport Road,
Bellfountain Rd, 53rd St, Plymouth Dr, Nash Ave, Brooklane Dr, Wake
Robin Road, Rivergreen Ave and as far north as the Benton County Fair
Grounds. It was silent anywhere south of Llewellyn Rd. Trying to get
a heading for the sound with just my ears and a compass was way more
difficult than I expected.
[airport]
The Corvallis Airport
looking South
All indications were that the sound was coming from the area of the
airport, but I could not pin it down any more accurately. The airport
staff denied using an air cannon. However, they indicated that they
could hear one to the south.
The most easily identifiable farm south of the airport was Venell
Farms. They fervently denied they were using an air cannon.
That left a big chunk of land south and west of the airport that was
not crossed by public roads. Not willing to trespass to find the
source, I needed a new strategy.
You can support my
artwork and writing
on Patreon or Ko-fi
Retirement is tough.
Even small
contributions help.
After some deep thought, I theorized I could pinpoint the location of
the air cannon by logging the arrival times of the sound from three
locations. It took three people stationed at remote locations miles
apart using a synchronized clock on our cell phones. We each waited
over the same ten minute period, noting the exact time for each of
the five cannon shots that we heard.
The sound arrived at our Bellfountain Rd location first. About four
seconds later, the sound arrived at our Brooklane Dr. lookout. Two
seconds later, it arrived at our Rivergreen Ave listening post.
I took a screen capture of a Google Map of our area with a
measurement line on the map for scale. I plotted our three listening
locations. The scale allowed us to figure out how far apart our test
locations were and facilitated a method for translating back and
forth between the image coordinate system and the real world
coordinate system.
6.3km D~6S 3.8km D~4S 3.0km D~2S A B C Sound Source Search Area
Brooklane Dr Rivergreen Ave Bellfountain Rd
I wrote a program in Python (see source code below) that could
iterate all the points in the image in the search area where we
suspected the air cannon sat. Translating those image points to real
world coordinates, I used the speed of sound at 35 to calculate the
travel time to each of our three listening posts. Comparing the
arrival times of the simulated sounds, I could match them with the
deltas from the real observations. Once my program scanned and tested
every point on the south half of the map image, it identified a point
that exactly replicated the deltas. I knew I found the only possible
origin of the sound and therefore the location of the air cannon. I
translated my grid system back to real world coordinates and plotted
it on my map. That identified the offending farm field.
[angry-goos]
Image by claralieu, licensed under CC BY 2.0
Angry goose does not like
you or air cannons
I went to the County Tax Assessor Office to find the owner of the
property. With a company name, I found a Web site and a phone number.
I called the owner of the farm (headquartered in Monmouth) and asked
if they used an air cannon on their property near the Corvallis
airport. They confirmed that they do. I asked if they run it at
night, they said they do not. However, the manager said that he'd
contact the people working onsite. Twenty minutes later, he called
back reaffirming they are not running their cannons at night. He also
assured me that their air cannons could not be heard more than a mile
away. The air cannon that we tracked to his farm was clearly audible
6 miles away from the Benton County Fairgrounds. I did not trust his
knowledge of his own equipment nor how it was used by the onsite
staff.
However, in an amazing coincidence, the air cannons stopped that very
evening of our phone conversation (Thursday, January 25). The air
cannons have fallen silent at night since that day. I suspect that
the cessation was not a random correlation. I surmise that they
actually were using the cannon at night and the manager stopped the
practice.
It was a miserable twenty days of ruined sleep. I found threads about
the air cannon on Facebook, Reddit, Twitter/X and Nextdoor. How many
people in Corvallis and Philomath were disrupted?
I'm refraining from revealing the name of the farm. I don't want folk
harassing them. I will say, though, it wasn't Venell Farms as so many
expected.
Should the nighttime air cannon start up again, I have an easy tool
to figure out its exact location from miles away. I will exercise
this newly found power whenever I need it.
[geese]
Image by audreyjm529, licensed under CC BY 2.0
Please note: this code is shared to show the algorithm, not as a
drop-in application that just runs. It depends on two private modules
configmanners and points. Both of these are on github, but to upload
them to pip would be to commit to supporting them in perpetuity. I'm
not willing to do that.
There is no warranty, no guarantee, and the author is absentee.
The Source Code to my Air Cannon location search program.
#!/usr/bin/env python3
from math import sqrt, isclose
from functools import partial
from points import Point, Block
from configmanners import Namespace, configuration
from configmanners.converters import str_to_list
terrible_number = 100000
def distance(p1, p2):
return sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2)
str_to_Point = partial(
str_to_list, item_converter=float, list_to_collection_converter=Point
)
str_to_Block = partial(
str_to_list, item_converter=int, list_to_collection_converter=Block
)
def all_points_within_block_iter(a_block):
for x in range(a_block.left, a_block.right):
for y in range(a_block.upper, a_block.lower):
yield Point(x, y)
required_config = Namespace()
required_config.add_option(
"A_in_px",
default=Point(58.34, 844.29),
doc="point A in pixel coordinates",
from_string_converter=str_to_Point,
)
required_config.add_option(
"B_in_px",
default=Point(846.05, 290.27),
doc="point B in pixel coordinates",
from_string_converter=str_to_Point,
)
required_config.add_option(
"C_in_px",
default=Point(1574.73, 453.96),
doc="point C in pixel coordinates",
from_string_converter=str_to_Point,
)
required_config.add_option(
"AB_time_delta",
default=4.0,
doc="time delta between listening posts A and B",
from_string_converter=str_to_Point,
)
required_config.add_option(
"AC_time_delta",
default=6.0,
doc="time delta between listening posts A and C",
from_string_converter=str_to_Point,
)
required_config.add_option(
"BC_time_delta",
default=2.0,
doc="time delta between listening posts B and C",
from_string_converter=str_to_Point,
)
required_config.add_option(
"AB_in_m",
default=3800.0,
doc="distance in meters between points A and B",
)
required_config.add_option(
"speed_of_sound_in_mps",
default=332.24,
doc="the speed of sound in meters per second",
)
required_config.add_option(
"search_box_in_px",
default="400, 1000, 1200, 2000",
doc="coodinate extents in pixels of the search area",
from_string_converter=str_to_Block,
)
config = configuration(required_config)
scale = config.AB_in_m / distance(config.A_in_px, config.B_in_px)
def test_fitness(test_point_in_px):
SA_in_m = distance(config.A_in_px, test_point_in_px) * scale
SB_in_m = distance(config.B_in_px, test_point_in_px) * scale
SC_in_m = distance(config.C_in_px, test_point_in_px) * scale
TA_in_s = SA_in_m / config.speed_of_sound_in_mps
TB_in_s = SB_in_m / config.speed_of_sound_in_mps
TC_in_s = SC_in_m / config.speed_of_sound_in_mps
test_AB_delta = abs(TB_in_s - TA_in_s)
if not isclose(test_AB_delta, config.AB_time_delta, abs_tol=0.1):
return terrible_number
test_AC_delta = abs(TA_in_s - TC_in_s)
if not isclose(test_AC_delta, config.AC_time_delta, abs_tol=0.1):
return terrible_number
test_BC_delta = abs(TB_in_s - TC_in_s)
if not isclose(test_BC_delta, config.BC_time_delta, abs_tol=0.1):
return terrible_number
# return the deviation from the sum of the deltas as a fittness value
return abs(
test_AB_delta
+ test_AC_delta
+ test_BC_delta
- config.AB_time_delta
- config.AC_time_delta
- config.BC_time_delta
)
best_fitness = terrible_number
best_point = None
for test_point_in_px in all_points_within_block_iter(config.search_box_in_px):
fitness = test_fitness(test_point_in_px)
if fitness < best_fitness:
best_fitness = fitness
best_point = test_point_in_px
if best_point is not None:
print(f'{best_point=} at {best_fitness=}')
else:
print('the air cannon is not in the search area')
(this code is not currently hosted in a public repository)
Please note: this code is shared to show the algorithm, not as a
drop-in application that just runs. It depends on two private modules
configmanners and points. Both of these are on github, but to upload
them to pip would be to commit to supporting them in perpetuity. I'm
not willing to do that.
There is no warranty, no guarantee, and the author is absentee.
Powered by Blogger
(c)2024 by K Lars Lohn, All Rights Reserved