विमानों से प्यार करने वाली टॉडलर के लिए माता-पिता ने बनाया रडार
(jacobbartlett.substack.com)- दो साल की बेटी को विमानों से प्यार हो जाने के बाद, आसपास के विमानों को फोन रडार की तरह दिखाने वाला iOS ऐप Aviator कुछ शामों में एक side project के रूप में बनाया गया
- FlightRadar24 विमान की लोकेशन को मैप पर दिखाता है, लेकिन असली आसमान में किस दिशा में देखना है और बच्चे के लिए कौन-सा विमान ढूँढना आसान होगा, यह अलग से समझना पड़ता था
- ऐप Core Location की दिशा जानकारी, OpenSky Network के non-commercial REST API, MapKit annotations और SwiftUI UI को जोड़कर विमानों को डिवाइस की दिशा के अनुसार दिखाता है
- MVP टेस्ट में यह पुष्टि होने के बाद कि असली विमान और ऐप का डिस्प्ले मेल खा रहे हैं, इसमें मैप छिपाना, कम ऊँचाई वाले विमानों को बड़ा दिखाना, रडार animation, CRT effect, sound·haptics और color settings जोड़ी गईं
- अंतिम ऐप App Store पर जारी कर दिया गया, और आगे के सुधारों के लिए zoom level, OpenSky advanced API, departure·arrival country display, Metal shader improvements, distance·altitude filters और “zany mode” बचे हैं
विमान देखने से ऐप की requirements तक
- गर्मियों की विदेश यात्रा में 3 घंटे की उड़ान से पहले बेटी विमान यात्रा को लेकर उत्साहित थी, और बोर्डिंग के बाद cabin crew के मार्गदर्शन में cockpit देखने के बाद उसका विमान प्रेम और बढ़ गया
- उसके बाद वह अक्सर आसमान में विमान ढूँढने के लिए कहती थी, और यहाँ तक कि बगीचे में एक घंटे तक कंधे पर बैठाकर शाम के आसमान में विमान खोजने की नौबत आ गई
- FlightRadar24 मैप पर विमान की लोकेशन दिखाता था, लेकिन असली आसमान में किस दिशा में देखना है, यह यूज़र को खुद मिलाना पड़ता था
- 2D मैप पर 40,000 फीट पर उड़ता Learjet और London City Airport से अभी उड़ा AirBus एक जैसे लग सकते हैं, लेकिन असली आसमान में कम ऊँचाई पर बड़ा विमान ढूँढना आसान होता है
- दो साल के बच्चे को मैप समझना नहीं, बल्कि बस आसान विमान ढूँढना चाहिए था
- शुरुआती समस्या को तीन हिस्सों में बाँटा गया
- दिशा मिलान: डिवाइस की दिशा के अनुसार विमान की पोज़िशन असली आसमान की दिशा से मेल खानी चाहिए
- आकार दिखाना: विमान की ऊँचाई के अनुसार स्क्रीन पर उसका आकार बदलना चाहिए
- उपयोगिता: यह कोई कामकाजी flight tracking ऐप नहीं, बल्कि retro toy जैसा ऐप होना चाहिए
Aviator की शुरुआती डिज़ाइन
- ऐप का आइडिया था “आसपास की flights को रडार पर दिखाना”, और प्रोजेक्ट का नाम Aviator रखा गया
- तीन मुख्य requirements थीं
- डिवाइस घुमाने पर स्क्रीन भी साथ घूमे ताकि विमान सही दिशा में दिखें
- विमान की ऊँचाई के अनुसार स्क्रीन पर उसका आकार बदले
- बच्चे के इस्तेमाल के लिए मज़ेदार retro toy जैसा एहसास दे
- दिशा संभालने के लिए iOS Core Location API के heading updates का उपयोग किया गया
CLLocationManagerDelegateकेdidUpdateHeadingसे डिवाइस की दिशा ली गई- Combine के
CurrentValueSubjectसे दिशा का मान SwiftUI view तक पहुँचाया गया
- विमान डेटा के लिए OpenSky Network का उपयोग किया गया
- यह एक simple REST API है जो तय latitude·longitude range के लिए real-time विमान डेटा देता है
- non-commercial उपयोग के लिए यह मुफ़्त है
- यथार्थवादी radar sweep के लिए हर कुछ सेकंड में endpoint call करने की योजना थी
- लोकेशन डेटा Core Location से लिया गया, और यूज़र की लोकेशन के आसपास latitude·longitude range query की गई
- शुरुआती योजना में latitude ±1 degree रखा गया, और 0.1 degree लोकेशन precision लगभग 10km होने से यूज़र की लोकेशन को पर्याप्त रूप से धुंधला करने का विचार था
- लेकिन वास्तविक API example code में UK latitude पर लगभग square area पाने के लिए 0.5 degree latitude और 1 degree longitude range इस्तेमाल की गई
- OpenSky Network API non-commercial उपयोग तक सीमित था और ऐप भी commercial service नहीं था, इसलिए SwiftUI में simple MV structure अपनाया गया और सिर्फ API·Location जैसी core services को अलग किया गया
PoC: दिशा, विमान डेटा और मैप वेरिफिकेशन
- दिशा PoC में
LocationManagersingleton से location permission request, delegate setup और heading updates शुरू करने का काम किया गया - SwiftUI view ने
.onReceiveसेrotationAngleSubjectsubscribe किया और rectangles को गोलाकार में रखकर compass जैसी rotation effect बनाई - test device पर यह असली दिशा बदलाव पर अच्छी तरह प्रतिक्रिया दे रहा था, लेकिन 0 degree और 360 degree को अलग मानने वाली animation के कारण true north पार करते समय rectangles एक पूरा चक्कर लगाते दिखते थे
- OpenSky REST API latitude·longitude range के साथ
GETrequest पर स्थानीय flights की array लौटाता है- example endpoint
states/allमेंlamin,lamax,lomin,lomaxparameters जोड़ने के रूप में था - REST API दस्तावेज़ अच्छे थे, लेकिन response keyless structure में होने से JSON fields को क्रम के अनुसार parse करना पड़ा
- Swift के
UnkeyedContainerसेicao24,callsign,origin_country,time_position,last_contact,longitude,latitudeआदि decode किए गए
- example endpoint
- विमान ड्रॉ करने की पहली कोशिश में यूज़र लोकेशन और विमान के latitude·longitude अंतर पर fixed screen scale गुणा करके SF Symbol
airplaneimage रखी गई- latitude·longitude के 1 degree की असली दूरी लोकेशन के अनुसार बदलती है, इसलिए यह सटीक नहीं हो सकता था
- फिर भी शुरुआत के लिए उपयोगी था
- accuracy verify करने के लिए SwiftUI
Mapको background में रखा गया और उसके ऊपर विमान व compass overlay किया गया- FlightRadar projection से तुलना करने पर विमानों की संख्या और clusters लगभग मेल खाते थे, लेकिन पोज़िशन काफ़ी हटी हुई थी
- बाद में विमान सीधे मैप पर annotation के रूप में ड्रॉ करने की ओर बदला गया
MVP: MapKit annotations और user testing
- iOS 17 को target करते हुए MapKit की map annotation सुविधा से विमान-आकार markers को वास्तविक geographic coordinates पर दिखाया गया
FlightMapViewनेMap(position:)के ऊपर विमान annotations ड्रॉ किए और radar उपयोग के लिए.allowsHitTesting(false)से map interaction बंद किया- altitude-based scaling में शुरुआत में log scale लागू किया गया ताकि ऊँचे विमान बड़े दिखें
- विमान के
true_trackऔर Core Location की यूज़र दिशा को जोड़कर airplane icon की दिशा मिलाई गई
- विमान के
- पहले MVP user test में बेटी के साथ सच में विमान ढूँढे गए, और ऐप में दिख रहा विमान असली आसमान में भी नज़र आया
- टेस्ट के बाद दो सुधार सामने आए
- scaling उलटी थी: आसमान में आँख से आसानी से दिखने वाले विमान दिखाने के लिए कम ऊँचाई वाले विमान बड़े होने चाहिए थे
- बेटी को मैप नहीं, सिर्फ विमान चाहिए थे, इसलिए शोर कम करने के लिए मैप हटाना ज़रूरी था
- संशोधित scaling formula
min(2, max(4.7 - log10(flight.geo_altitude + 1), 0.7))था- स्थानीय आसमान स्कैन में 0.7 से 2.0 तक मान मिले और स्क्रीन पर वितरण अच्छा लगा
रडार UI बनाना
- OpenSky API अक्सर timeout,
502 Bad Gatewayऔर null data वाली 200 responses लौटाता था- यह मुफ़्त non-commercial API है और इसका कोई SLA नहीं है, इसलिए client में basic retry logic जोड़ी गई
- अगले दिन यह पूरे दिन अच्छी तरह चला, और कुछ high-traffic समयों को छोड़कर कुल मिलाकर ठीक लगा
- असली मैप को न दिखाने के लिए
MapPolygonoverlay का उपयोग किया गया- मूल रूप से यह मैप क्षेत्र highlight करने का overlay है, लेकिन इसका उपयोग विमान annotations छोड़कर मैप को ढकने के लिए किया गया
- Apple के overlay map के ऊपर और annotations के नीचे draw होते हैं, जिससे मनचाहा परिणाम मिला
- रडार स्क्रीन lines, concentric circles और 20-degree चौड़ाई वाले rotating angular gradient से बनाई गई
- बाद में radar line effect को 360-degree angular gradient से सरल किया गया
- green से transparent और फिर black तक जाने वाले gradient को rotate कर sweep और afterglow जैसा लुक दिया गया
- इसे “grug-brained” तरीका कहा गया और कई बार बेहतर माना गया
- डिवाइस को तेज़ी से घुमाने पर स्क्रीन के कोनों में मैप के टुकड़े दिखने का visual artifact था, जिसे radar view के बाहर काले रंग की reverse mask से ठीक किया गया
प्रोडक्ट बनाना: CRT effect, sound, settings, App Store
- retro toy जैसा एहसास देने के लिए CRT screen effect जोड़ा गया
- iOS 17 के
colorEffectमें built-in Metal shader support का उपयोग किया गया - shader काले रंग के अलावा बाकी pixels पर scanline value लागू करता था
timeparameter देकर scanlines को तेज़ी से ऊपर की ओर चलाया गया ताकि dynamic feel आए
- iOS 17 के
- OpenSky Network की policy के अनुसार App Store listing ठीक है या नहीं, यह पूछने पर 20 मिनट के भीतर जवाब मिला
- radar experience और accessibility के लिए flight updates पर system sound और haptics जोड़े गए
AudioServicesPlaySystemSound(1052)से beep-boop sound चलाई गई- SwiftUI के
sensoryFeedback(.levelChange, trigger:)का उपयोग किया गया
- आवाज़ परेशान कर सकती थी, इसलिए
@AppStorageआधारित settings जोड़ी गईंsilent: silent modeshowMap: radar overlay बंद करके नीचे का मैप देखा जा सकता हैuserColor: SwiftUI color picker से radar color चुना जा सकता है
- Midjourney subscription बंद होने के कारण Gencraft के non-commercial free generator से एविएशन कैप पहने बेटी जैसी Aviator mascot बनाई गई
- Apple Developer Program में फिर से शामिल होते समय £79 चुकाकर App Store distribution की तैयारी की गई
- केवल iOS 17 target था, लेकिन 6.5-inch और 5.5-inch iPhone screenshots जमा करने पड़े
- नवीनतम 5.5-inch iPhone, iPhone 8 Plus, अधिकतम iOS 16 तक ही जाता है, इसलिए AppScreens से दोनों आकार के screenshots export किए गए
- ऐप App Store पर प्रकाशित हो गया, और डाउनलोड लिंक है Aviator — Radar on your Phone
अगला version candidates
- कुछ शामों में बने इस side project के नतीजे से संतुष्टि थी, और बेटी के लिए खिलौना बनाने का coding अनुभव लंबे समय में सबसे मज़ेदार लगा
- अगली release के candidate features ये हैं
- map zoom level जोड़कर radar को सिर्फ पास के विमानों तक सीमित करना
- OpenSky Network advanced API से helicopter, satellite और airplane size classes दिखाना
- विमानों के लिए departure·arrival country display toggle जोड़ना
- अधिक उन्नत Metal shader से CRT screen effect सुधारना
- controls को resizable progressive-disclosure pull-out modal में refactor करना
- distance·altitude slider filters लागू कर कम ऊँचाई वाले दूर विमान आदि छिपाना
- radar पर UFO, विशाल कीड़े और aliens render करने वाला zany mode बनाना
1 टिप्पणियां
Hacker News की राय
बढ़िया काम है, और लेख भी अच्छा है। यह दिलचस्प है कि इस प्रोजेक्ट पर मूल radar display की डिज़ाइन कितनी मज़बूती से हावी है
हो सकता है कि बच्चे को असली CRT तो दूर, PPI display वाले ASR-9 को छूने का मौका भी कभी न मिले, फिर भी उसे simulate करने के लिए काफ़ी मेहनत की गई
शायद यह skeuomorphism पसंद होने की वजह से भी है, लेकिन इसलिए भी लगता है कि मूल radar screen “आसमान में कुछ है क्या, और वह मेरी स्थिति के हिसाब से कहाँ है?” को शानदार तरीके से संक्षेप में दिखाती है
आजकल के sky-watching UI ऐसा लगता है कि context information, external service links, और ad space की ओर जाते-जाते इस सवाल का आसानी से जवाब देने की क्षमता खो बैठे हैं
लक्ष्य की दूरी को केंद्र से दूरी के रूप में, और दिशा को वृत्त की परिधि के कोण के रूप में दिखाया गया था
हाँ, sweep की नकल करने वाला हिस्सा सवालों के घेरे में आने वाला डिज़ाइन फैसला हो सकता था, लेकिन चमकीले रंग और बिना नक्शे वाली पृष्ठभूमि स्क्रीन के उद्देश्य पर ध्यान केंद्रित कराते हैं, इसलिए वह बिल्कुल ठीक लगता है
फोन हाथ में लेकर घूमने पर compass tracking के कारण sweep का भ्रम टूटता हुआ भी दिखा
https://github.com/sky-map-team/stardroid
मैं इससे जुड़ी तकनीकी चीज़ें समझता हूँ और खुद ADSB station भी चलाता हूँ, लेकिन फिर भी जब कैमरा आसमान की ओर करके दिखने वाले विमानों का metadata दिखता है, तो वह अब भी चकित कर देता है
शानदार। इसे कभी-न-कभी बनाने वाली अपनी सूची में डाल लिया है
इसी तरह, मैंने अपने 5 साल के बेटे के लिए flight logbook बनाया था, और यह उसके शिशु होने के समय से शुरू किया था। हर उड़ान पर हम crew से पूछते हैं कि क्या captain उसमें कुछ लिख सकते हैं
उसमें route, aircraft type, और क्या-क्या हुआ, यह दर्ज किया जाता है, और crew को ऐसी चीज़ें सच में बहुत पसंद आती हैं। हमने cockpit और crew rest area भी देखा, और लिखे गए संदेश हमेशा बहुत स्नेहपूर्ण रहे
हर बार वापस मिलने पर बच्चे की बड़ी मुस्कान देखने को मिलती है, इसलिए छोटे plane nerds के लिए इसकी ज़ोरदार सिफारिश है
यह अच्छा लगा कि शुरुआती release के must-have features में display color बदलना शामिल था। इसका मतलब है कि target users की ज़रूरतों की समझ बहुत मज़बूत है
3 साल के बच्चे को color picker वाला कोई भी खिलौना पसंद आता है
HN पर karma 250 पार करने वाली बेवजह की खुशी जैसी बात समझ लीजिए
आज भी अगर दिखाओ तो बच्चा सबसे पहले रंग चुनने पर ध्यान देगा, और यह fine motor development के लिए भी अच्छा है
“हमने हवाई यात्रा को इतना बढ़ा-चढ़ाकर बताया कि बच्चा यह जानकर हैरान रह गया कि airport तक taxi से जाना पड़ता है। उसे लगा था कि घर से सीधे चलकर विमान में चढ़ जाएँगे” वाला हिस्सा सच में प्यारा, मज़ेदार, और पूरी तरह समझ में आने वाला था
https://www.architecturendesign.net/john-travoltas-house-is-...
प्यारे plane nerd बच्चे के साथ होने पर crew cockpit दिखा देता है—इस बात से याद आया कि मिलते-जुलते NASA नारंगी jumpsuit पहनना हर cockpit में घुसने का पासपोर्ट है
बच्चों से ज़्यादा crew उत्साहित हो जाता है, और airport पर बच्चे को ढूँढ़ना भी बहुत आसान हो जाता है
बंद हो चुके social network app Tapstack को सिर्फ परिवार के उपयोग के लिए clone करने पर लिखा गया लेख An app can be a home cooked meal भी इससे जुड़ा हुआ है
https://www.robinsloan.com/notes/home-cooked-app/
हाँ, viral हो जाना भी बुरा नहीं है
दो छोटी कमियाँ लगीं
विमान वाला dot स्क्रीन पर दिख जाने के बाद अगर हिलता रहता है तो immersion थोड़ा टूटता है। अगर उसे sweep द्वारा “paint” किया जाए और अगले sweep तक स्थिर रखा जाए, तो शायद वह ज़्यादा वास्तविक लगे
और ज़्यादा realism के लिए पिछले data point से extrapolate करके हर विमान को हर sweep पर लगातार आगे बढ़ते हुए भी दिखाया जा सकता है
दूसरा तो शायद और भी सरल हो सकता है। API flight speed लौटाती है, इसलिए सिर्फ एक data point से भी गणना की जा सकती है
बेटी के साथ करने के लिए यह एक बढ़िया गतिविधि है: सबसे नज़दीकी international airport के runway के landing-direction वाले सिरे के पास की सड़क, parking lot, या park में जाना अच्छा रहता है.
आम तौर पर यह हवा की दिशा पर निर्भर करता है, इसलिए उसी हिसाब से जाएँ, गाड़ी खड़ी करें और विमानों को नीचे आते और landing करते देखें.
बच्चा अपने radar पर देख सकता है कि कौन-सा विमान आ रहा है, और हमने
flightradar24इस्तेमाल किया था.बच्चों को यह देखकर जैसे जादू हो गया कि approach कर रहा बड़ा jet ज़मीन के कितना पास नीचे आता है, और वे कई घंटों तक आसानी से मज़े करते रहे. अगला विमान इससे बड़ा होगा या और पास आएगा, यह देखने के लिए वे जाना ही नहीं चाहते थे, इसलिए मनाना-पड़ाना पड़ा.
Airbus A318 आकार या उससे छोटे multi-engine fixed-wing aircraft में भी सिर्फ़ वही उड़ान भर सकते हैं जिन्हें 5.5° approach करने के लिए विशेष aircraft और crew certification मिली हो.
https://www.youtube.com/watch?v=yZIDFgpT0-o
https://en.wikipedia.org/wiki/London_City_Airport
इस app में एक समस्या है. App page पर साफ़ लिखा है 4 साल और उससे ऊपर, लेकिन target user 2 साल का है.
अच्छी तरह बनाया गया है.
शानदार.
एक छोटा-सा detail वाला सवाल: क्या CRT radar scope में सचमुच scan line होती थीं? मुझे लगा था कि यह vector display रहा होगा.
feature list के सिलसिले में, क्योंकि यह plane-watching app है, अगर किसी dot पर tap करने से कुछ सेकंड के लिए aircraft type दिखे तो बढ़िया होगा.
phosphor persistence की वजह से मज़बूत radar reflection थोड़ी देर तक स्क्रीन पर बनी रहती थी. अगर उस दौरान radar एक पूरा चक्कर या उससे ज़्यादा लगा ले, तो वही विमान थोड़ा-सा खिसका हुआ नया dot, यानी “plot”, बनकर दिखता था.
felt-tip pen से स्क्रीन पर plot को निशान लगाकर उसे “track” में भी बदला जा सकता था.
ऐसे विशेष display भी थे जिनमें radar screen की तरफ़ movie camera लगाकर कई घंटों के radar reflection रिकॉर्ड किए जाते थे और बाद में चलाए जाते थे.
उदाहरण के लिए, 1968 की Czechoslovakia क्रांति के दौरान Warsaw Pact aircraft का तेज़ करके चलाया गया रिकॉर्ड मौजूद है: https://youtu.be/rAUodXI4LPw?t=622
शुरुआती radar display केंद्र से बाहर की ओर radial दिशा में scan करते थे. Scan timing पहले से तय होती थी ताकि दूरी को scale किया जा सके, और beam intensity signal वही amplified radar reflection signal होता था.
इसलिए अधिक मज़बूत reflection signal, long-persistence screen पर ज़्यादा साफ़ दिखने वाले “blip” के रूप में नज़र आते थे.
दिलचस्प बात यह है कि radar beam को CRT screen के चारों ओर scan कराने के लिए पूरी cathode-ray tube emitter assembly को rotating radar dish के साथ synchronized motor से चलाया जाता था.
यह rotation हमेशा radar dish की speed और direction से मेल खाना चाहिए था, नहीं तो blip ग़लत जगह पर दिखाई देते.
स्थिर radial और range line, CRT tube पर या उसके transparent cover पर छपी होती थीं. ऐसे display दशकों तक इस्तेमाल हुए होंगे, शायद 1980s या 1990s की शुरुआत तक भी.
बाद के नए version में इस जटिल rotating beam-emitter assembly से बचने के लिए साधारण electronic circuit के ज़रिए X/Y direction को स्वतंत्र रूप से scan किया जा सकता था.
अधिक जानकारी: https://en.wikipedia.org/wiki/Radar_display#Plan_position_in...
कोण या तो deflection plate को physically घुमाकर बनाया जा सकता है, या sin/cos को electronic रूप से गणना करके X/Y deflection plate पर लागू करके.
return signal का amplitude सीधे beam current को drive करता है, इसलिए बड़े reflection वाले target ज़्यादा bright दिखाई देते हैं.
इसके ऊपर storage tube effect भी होता है, लेकिन यह शुरुआती कंप्यूटरों के storage-tube X-Y vector display के bistable mode जैसा नहीं, बल्कि कुछ oscilloscopes के variable persistence mode जैसा काम करता है.
इसी गुण के कारण SR-71 या XB-70 जैसे शुरुआती stealth aircraft design प्रयासों से जुड़े परिणाम भी सामने आए.
radar tube में beam current इस तरह सेट किया जाता था कि “blip” कई sweep तक जमा होता जाए, और आम तौर पर blip sweep के बीच अपनी ही diameter से कम दूरी खिसकता था.
लेकिन अगर किसी विमान का radar cross-section स्वभाव से बहुत कम हो और वह इतना तेज़ हो कि blip sweep के बीच उससे अधिक दूर चला जाए, तो radar operator, ख़ासकर बहुत-से targets वाले व्यस्त हालात में, उन छोटे ghost blip को noise समझ सकता था.