Claude Code के साथ एक अंतरिक्षयान कंप्यूटिंग सिमुलेटर बनाना

मैं समझना चाहता था कि अंतरिक्षयानों के कंप्यूटर कैसे काम करते हैं। रियल-टाइम शेड्यूलिंग, रेडिएशन हार्डनिंग, विलंब-सहिष्णु नेटवर्किंग जो मंगल के रोवर्स को पृथ्वी से जोड़े रखती है। Artemis II के क्षितिज पर आने (50 से अधिक वर्षों में पहला चंद्र मानव मिशन) के साथ, यह गहराई से समझने का सही समय लगा। तो मैंने एक सिमुलेटर बनाया। शुरू से। Claude Code को अपने जोड़ी प्रोग्रामर के रूप में लेकर।

कोई भौतिक हार्डवेयर नहीं। सब कुछ लैपटॉप पर QEMU और Docker में चलता है। GitHub पर कोड।

flowchart LR
    QEMU["QEMU (Cortex-M3)"] -->|UART socket| Bridge[uart_bridge.py]
    Bridge -->|bpsendfile| SC[Spacecraft Node]
    SC -->|LTP + 5s delay| GS[Ground Station]

    subgraph Docker
        SC
        GS
    end
flowchart TB
    QEMU["QEMU (Cortex-M3)"] -->|UART socket| Bridge[uart_bridge.py]
    Bridge -->|bpsendfile| SC["Spacecraft Node (Docker)"]
    SC -->|LTP + 5s delay| GS["Ground Station (Docker)"]

यह प्रोजेक्ट क्यों

मैं कुछ सच में कठिन सीखना चाहता था। कुछ ऐसा जहाँ अवधारणाएँ अपरिचित हों और टूल्स कठोर हों। ARM को टार्गेट करने वाले C कंपाइलर्स। लिंकर स्क्रिप्ट्स। मेमोरी-मैप्ड I/O। इंटरप्ट वेक्टर टेबल।

Claude Code ने यह संभव किया। इसलिए नहीं कि इसने सारा कोड लिखा, बल्कि इसलिए कि इसने समझाया कि एक लिंकर स्क्रिप्ट क्या करती है जब हम एक लिख रहे थे, ताकि स्पष्टीकरण उस वास्तविक समस्या में निहित हो जो मैं हल कर रहा था। volatile, FreeRTOS प्राथमिकता प्रीएम्पशन और LTP रीट्रांसमिशन टाइमर के लिए भी यही था।

रोडमैप

मैंने प्रोजेक्ट को चार चरणों में विभाजित किया, प्रत्येक पिछले पर निर्मित:

चरणक्यामुख्य अवधारणाएँ
Bare MetalARM क्रॉस-कंपाइलेशन, UART आउटपुट, इंटरप्ट हैंडलर्समेमोरी-मैप्ड I/O, SysTick टाइमर, स्टार्टअप असेंबली
FreeRTOSटास्क, क्यू, वॉचडॉग, प्राथमिकता उलटावनिर्धारणवादी शेड्यूलिंग, mutex प्रोटोकॉल, प्रीएम्पशन
DTNदो-नोड नेटवर्क, डिग्रेडेड लिंक, CFDP, कॉन्टैक्ट-ग्राफ रूटिंगBundle Protocol, स्टोर-एंड-फॉरवर्ड, LTP विश्वसनीयता
एकीकरणमंगल-दूरी की देरी के साथ पूर्ण टेलीमेट्री पाइपलाइनUART ब्रिज, tc netem, सिंक्रनाइज़ ION OWLT

प्रत्येक चरण में स्वचालित परीक्षण हैं। प्रत्येक माइलस्टोन एक PR है जिसमें CI पास है।

चरण 1: Bare Metal

पहली चुनौती कुछ भी चलाना था। QEMU में Cortex-M3 (MPS2-AN385) को टार्गेट करते हुए ARM क्रॉस-कंपाइलेशन। कोई OS नहीं, कोई स्टैंडर्ड लाइब्रेरी नहीं, कोई printf नहीं।

Claude ने मुझे स्टार्टअप सीक्वेंस समझने में मदद की: वेक्टर टेबल, रिसेट हैंडलर, .data को फ्लैश से RAM में कॉपी करना, .bss को जीरो करना। ये सब main() के चलने से पहले होता है।

पहली जीत UART कंसोल पर एक एकल अक्षर था:

#define UART0_DR  (*(volatile uint32_t *)0x40004000)

void uart_putc(char c) {
    UART0_DR = c;
}

C की दो लाइनें। कोई लाइब्रेरी नहीं। बस एक मेमोरी एड्रेस पर एक बाइट लिखना जो सीरियल पोर्ट से जुड़ा होता है। यह मशीन से सीधे बात करने जैसा लगा।

वहाँ से: SysTick टाइमर इंटरप्ट, इंटरप्ट हैंडलर्स, स्ट्रक्चर्ड आउटपुट। SysTick डेमो एक हार्डवेयर टाइमर को 2 Hz पर फायर करने के लिए कॉन्फ़िगर करता है और 10 टिक्स गिनता है:

SysTick interrupt demo
======================
Ticking at 2 Hz for 5 seconds (10 ticks)...

  tick 1
  tick 2
  tick 3
  tick 4
  tick 5
  tick 6
  tick 7
  tick 8
  tick 9
  tick 10

Done — 5 seconds counted by interrupt.

कोई खोया हुआ टिक नहीं। कोई अतिरिक्त टिक नहीं। CPU इंटरप्ट के बीच सोता है और हार्डवेयर उसे ठीक सही समय पर जगाता है। Bare metal से निर्धारणवादी निष्पादन।

चरण 2: FreeRTOS

Bare metal काम करने के बाद, मैंने FreeRTOS जोड़ा, एक रियल-टाइम ऑपरेटिंग सिस्टम जो मेडिकल डिवाइस से लेकर सैटेलाइट तक सब पर चलता है।

अभ्यास क्रमिक रूप से बनाए गए:

  1. अलग-अलग दरों पर दो टास्क। बेसिक मल्टीटास्किंग।
  2. क्यू-आधारित संचार। टास्क के बीच डेटा को सुरक्षित रूप से साझा करना।
  3. वॉचडॉग टाइमर। हैंग हुए टास्क का पता लगाना और रिकवरी।
  4. सेंसर पाइपलाइन। अलग-अलग दरों पर चार सेंसर एक प्रोसेसिंग चेन को फीड करते हैं।
  5. प्राथमिकता उलटाव। क्लासिक RTOS बग को ट्रिगर और हल करना।

यहाँ सेंसर पाइपलाइन बूट हो रही है। 10 Hz ग्यरोस्कोप स्ट्रीम को डोमिनेट करता है, टिक 1001 पर 1 Hz तापमान रीडिंग घुस आती है:

FreeRTOS Sensor Pipeline Demo
=============================

[GYRO]  Sensor online (10 Hz, priority 4)
[PROC]  Processor online (priority 3)
[TELEM] Telemetry online (priority 2)
[TEMP]  Sensor online (1 Hz, priority 1)
[TELEM] #000 GYRO: 300 at tick 100
[TELEM] #001 GYRO: 300 at tick 200
  ...
[TELEM] #009 GYRO: 300 at tick 1000
[TELEM] #010 TEMP: 1991 at tick 1001
[TELEM] #011 GYRO: 300 at tick 1100

यह प्राथमिकता-आधारित प्रीएम्पशन कार्रवाई में है। ग्यरोस्कोप प्राथमिकता 4 पर चलता है, तापमान सेंसर प्राथमिकता 1 पर। तापमान रीडिंग तभी गुजरती है जब ग्यरोस्कोप CPU पर कब्जा नहीं कर रहा।

प्राथमिकता उलटाव का अभ्यास सबसे शिक्षाप्रद था। मैंने तीन टास्क बनाए जहाँ एक कम-प्राथमिकता टास्क एक mutex रखती है जिसकी एक उच्च-प्राथमिकता टास्क को जरूरत है, और एक मध्यम-प्राथमिकता टास्क दोनों को भूखा रखती है। समाधान: प्राथमिकता विरासत, जहाँ FreeRTOS अस्थायी रूप से कम-प्राथमिकता टास्क को बढ़ाता है ताकि वह mutex तेजी से रिलीज कर सके।

यह वही बग है जिसने 1997 में Mars Pathfinder मिशन को लगभग नष्ट कर दिया था। इसे खुद बनाने से पाठ्यपुस्तक की व्याख्या समझ में आई।

चरण 3: विलंब-सहिष्णु नेटवर्किंग

TCP/IP अंतरिक्ष में काम नहीं करता। मंगल के राउंड-ट्रिप टाइम 6 से 44 मिनट तक होते हैं। जब ग्रह सिग्नल को रोकते हैं तो लिंक घंटों के लिए गिर जाते हैं। TCP की निरंतर, कम-विलंब कनेक्शन की धारणा पूरी तरह टूट जाती है।

NASA JPL का जवाब DTN है, या Delay-Tolerant Networking। Bundle Protocol डेटा को स्थानीय रूप से स्टोर करता है और जब लिंक उपलब्ध होते हैं तो इसे hop-by-hop आगे भेजता है। यह ठीक उन स्थितियों के लिए डिज़ाइन किया गया है जो इंटरनेट को तोड़ती हैं।

मैंने Docker में NASA की ION इम्प्लीमेंटेशन बनाई और क्रमिक रूप से कठिन परीक्षण चलाए:

इंटरमिटेंट लिंक टेस्ट कुछ आउटपुट लाइनों में पूरी DTN कहानी बताता है:

Test: intermittent link (send during outage, deliver on recovery)...
    qdisc: qdisc netem root refcnt 2 limit 1000 loss 100%
    confirmed: bundle queued (link is down)
    restoring link...
  PASS: bundle held during outage
  PASS: bundle delivered after link recovery

यह स्टोर-एंड-फॉरवर्ड कार्रवाई में है। bundle तब भेजा जाता है जब लिंक पूरी तरह मृत हो, 100% पैकेट लॉस। यह लोकल नोड की क्यू में बैठता है। जिस क्षण हम netem नियम को साफ करते हैं और कनेक्टिविटी बहाल करते हैं, LTP रीट्रांसमिट करता है और bundle दूसरे छोर पर पहुँच जाता है। TCP बहुत पहले हार मान लेता।

चरण 4: एकीकरण

अंतिम चरण सब कुछ जोड़ता है। FreeRTOS फर्मवेयर QEMU में टेलीमेट्री जनरेट करता है। एक Python ब्रिज स्क्रिप्ट UART आउटपुट पढ़ती है और इसे DTN bundle के रूप में इंजेक्ट करती है। bundle देरी वाले नेटवर्क से गुजर कर ग्राउंड स्टेशन तक पहुँचते हैं।

फर्मवेयर बूट होता है और तुरंत स्ट्रीमिंग शुरू करता है:

# Spacecraft Telemetry Firmware v1.0
# ===================================
# GYRO sensor online (10 Hz, priority 4)
# Processor online (priority 3)
# Telemetry online (priority 2)
# TEMP sensor online (1 Hz, priority 1)
# BATT sensor online (0.5 Hz, priority 1)
# SUN sensor online (2 Hz, priority 1)
$TELEM,0000,GYRO,300,100
$TELEM,0001,GYRO,300,200
  ...
$TELEM,0005,SUN,801,501
  ...
$TELEM,0011,TEMP,1991,1001
$TELEM,0012,SUN,801,1001

चार अलग-अलग दरों पर चार सेंसर। आप 10 Hz ग्यरोस्कोप को अधिकांश रीडिंग उत्पन्न करते देख सकते हैं, 2 Hz सन सेंसर, 1 Hz तापमान और 0.5 Hz बैटरी इंटरलीव्ड हैं। ब्रिज इन्हें हर 2 सेकंड में DTN bundle में बैच करता है।

मंगल-देरी परीक्षण साबित करता है कि पूरी पाइपलाइन यथार्थवादी परिस्थितियों में काम करती है:

Running Mars-delay end-to-end tests...
  PASS: tc netem delay 5s applied on spacecraft
  PASS: bridge exited cleanly
  PASS: bridge read telemetry lines
  PASS: bridge sent >= 1 bundle (got 12)
  PASS: ground station received files (got 8)
  PASS: received telemetry lines (got 224)
  PASS: telemetry CSV format valid (5 fields)
  INFO: delay observable (8 delivered at bridge exit < 12 sent)
7 passed, 0 failed

12 bundle भेजे, लेकिन ब्रिज एग्जिट होने तक केवल 8 डिलीवर। बाकी अभी भी 5-सेकंड की देरी में उड़ान में थे। यह देरी असली है, सॉफ्टवेयर में सिम्युलेट नहीं।

मंगल-देरी सिमुलेशन दो सिंक्रनाइज़ तंत्रों का उपयोग करता है:

  1. tc netem दोनों कंटेनरों में 5 सेकंड की वास्तविक नेटवर्क लेटेंसी जोड़ता है
  2. ION रेंज टेबल वही 5-सेकंड की एकतरफा लाइट टाइम सेट करती हैं ताकि LTP रीट्रांसमिशन टाइमर सही हों

दोनों को सहमत होना चाहिए। यदि वास्तविक देरी 5 सेकंड है लेकिन ION सोचता है कि यह 1 सेकंड है, तो LTP आक्रामक रूप से रीट्रांसमिट करता है और लिंक को भर देता है। इसे सही करने से मुझे विश्वसनीयता पर किसी भी पाठ्यपुस्तक अध्याय से अधिक प्रोटोकॉल डिज़ाइन के बारे में सिखाया।

Claude Code के साथ काम करना

यह प्रोजेक्ट Claude के बिना मुझे महीनों लेता। इसलिए नहीं कि कोड जटिल है (अधिकांश फाइलें 300 लाइनों से कम हैं) बल्कि इसलिए कि प्रत्येक डोमेन के लिए सीखने की वक्र खड़ी है।

जो अच्छा काम किया:

जिसमें सावधानी की जरूरत थी:

संख्याएँ

मेट्रिकमूल्य
कुल परीक्षण7 परीक्षण सुइट्स में 50+ assertions
भाषाएँC, Python, Bash
हार्डवेयरकोई नहीं (QEMU + Docker)
C की लाइनें~1,200 (फर्मवेयर + bare metal)
Python की लाइनें~1,500 (परीक्षण + ब्रिज + DTN स्क्रिप्ट)
ION DTN कॉन्फ़िग6 .rc फाइलों में ~350 लाइनें

इसे आज़माएँ

सब कुछ ओपन सोर्स है और QEMU और Docker के साथ किसी भी Linux मशीन पर चलता है:

sudo apt install gcc-arm-none-eabi qemu-system-arm build-essential
git clone https://github.com/granda/spacecraft-computing-sim
cd spacecraft-computing-sim

make -C bare-metal run          # bare metal UART output
make -C freertos run            # FreeRTOS sensor pipeline
make -C dtn test                # two-node DTN network
make -C integration test-bridge # full telemetry pipeline
make -C integration test-mars-delay  # Mars-distance delays

कोई भौतिक हार्डवेयर नहीं। कोई क्लाउड सेवाएँ नहीं। बस एक लैपटॉप और अंतरिक्षयानों के कंप्यूटर कैसे काम करते हैं इसके बारे में जिज्ञासा।