{"id":19934183,"url":"https://github.com/quartz/aistudio-copterbot","last_synced_at":"2026-05-09T12:37:23.623Z","repository":{"id":38293214,"uuid":"167450322","full_name":"Quartz/aistudio-copterbot","owner":"Quartz","description":"tracking helicopters and hopefully figuring out why they're hovering","archived":false,"fork":false,"pushed_at":"2022-10-06T12:26:08.000Z","size":68600,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-01T11:45:45.266Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Quartz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-24T22:54:03.000Z","updated_at":"2020-05-13T14:33:52.000Z","dependencies_parsed_at":"2023-01-19T10:31:23.381Z","dependency_job_id":null,"html_url":"https://github.com/Quartz/aistudio-copterbot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Quartz/aistudio-copterbot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quartz%2Faistudio-copterbot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quartz%2Faistudio-copterbot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quartz%2Faistudio-copterbot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quartz%2Faistudio-copterbot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Quartz","download_url":"https://codeload.github.com/Quartz/aistudio-copterbot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quartz%2Faistudio-copterbot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32819750,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T23:16:04.229Z","updated_at":"2026-05-09T12:37:23.605Z","avatar_url":"https://github.com/Quartz.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"NYPD Copterbot\n==============\n\nChop chop chop!\n\nWhat the f*** is going on here?\n-------------------------------\n\nIt's a common feeling in New York City. _I got woken up at 4:30 in the morning last night by some damn police helicopter circling like five feet above my apartment_, you say. _Do you know what it was?_ your friend asks, even though they know. You don't have any idea.\n\nThis bot aims to help solve that problem, at least a little bit, by:\n\n 1. tracking where the NYPD's helicopters are flying -- with ADS-B\n 2. figuring out when they're hovering  -- with machine learning\n 3. calculating the center point of the circles they make while flying -- with geometry\n 4. figuring out what happened at that point around that time -- with machine learning\n\nSo far, #1, #2 and #3 are at least partially solved.\n\nFun fact!\n---------\n\nEtymologically, _helicopter_ comes from _helix_ + _pteron_ meaning, well, \"helix\" and \"wing\" (like a _pterodactyl_). But someone reanalyzed it as _heli_ + _copter_ and now we have _copters_! Wow.\n\nI want to do this myself, for my city.\n--------------------------------------\n\nCool. It's kind of involved but it's totally doable. I believe in you.\n\n1. You need to be able to receive ADSB signals for your area. You need to put a handful of Raspberry Pis with DVB-T receivers in areas with line of sight to most/all of your area. They don't have to all be in the same place. (We have receivers in far northern Manhattan, lower Manhattan and Brooklyn...)\n2. Build out a basemap in dump1090-mapper. In New York City, we use parks, airports and rivers/the bay as wayfinding guides. What to use here depends on your city; in Atlanta, I'd use the freeways. Pull requests accepted.\n3. Set up one MySQL database for all the receivers to write to.\n4. more to come...\n\n\nThe machine learning part of this\n---------------------------------\n\nOnce we've assembled a decent-sized corpus of helicopter flights, we need figure out how to detect when a helicopter is hovering. We're going to do that with machine learning. In order to do that, we need to give the computer hand-picked examples of helicopters hovering and helicopters doing other non-hovering things. Here's how we do that.\n\n1. Run `ruby generate_images_for_hand_classification.rb` with the appropriate database env vars. This generates a `hover_train_png` folder (and a `hover_train_svg` folder in which you should run a webserver with `python -m http.server` lol sorry this is complicated) with PNGs representing 5 minute long segments of helicopter paths, along with `shingles.csv` with metadata about each segment. (The segments overlap.)\n2. Create the `hand_coded_training_data` folder and COPY `hover_train_png` into `hand_coded_training_data/hover_train_png_hover_only` (not move, copy). Then, leaf through the images and delete all the ones that do not depict hovering. Use your judgment.\n3. With `generate_training_data_from_handclassified_shingles.rb`, generate `training_data.csv`, which should soon include data about each shingle, plus features we generated. If you use additional `..._hover_only` folders in `hand_coded_training_data` be srue to record them in the Ruby script.\n4. Then do some scikitlearn magic...\n\n\nMatching centerpoints to events\n-------------------------------\n\nExperiment. Download from Google sheets [Tweets by NYCFireWire](https://docs.google.com/spreadsheets/d/1Z8kI0FhtHVOSp__CliM-GQjzj8JDue5DR2StBPzQwbo/edit#gid=0). Run `nycfirewire_parser.rb`. Upload the resulting `NYCFireWire_tweets.csv` to the TAMU Batch geocoder. Download that to `NYCFireWire_tw.csv` and you have points for that guy's tweets.\n\n\nQz Janky Deployment:\n--------------------\n`scp -r ../nypdcopterbot/*.rb ec2-user@whatever:/home/ec2-user/nypdcopterbot/`\n`scp -r ../dump1090-mapper/*.js ec2-user@whatever:/home/ec2-user/dump1090-mapper/`\n\nhttps://twitter.com/lb_bklyn/status/970981102188941312","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquartz%2Faistudio-copterbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquartz%2Faistudio-copterbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquartz%2Faistudio-copterbot/lists"}