Add shop links, full dimensions, and fix the flight animation
- Every component now has a `url` (schema + JSON) pointing to the shop it was priced from; surfaced in the run detail and the BOM (new "Купить" column). Wire/switch/capacitor entries also expose gauge, ratings, single-vs-bank values; detail reports coil inner/outer diameter (=tube outer), tube inner bore + wall, projectile mass in grams and bore fit. - Animation was wrong: it stitched flight+discharge segments by sorting on time, which tore the trajectory into discontinuities. Rebuilt it sequentially -- coast (ballistic) between discharges + exact discharge trajectory, global x = coil center + local discharge_x -- so the slug moves continuously and coils sit at their real positions. Cleaner visuals: labeled coils that glow gold on discharge, blue slug. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
"esr_ohm": 0.45,
|
||||
"max_current_a": 40.0,
|
||||
"price": 140.0,
|
||||
"source": "REAL цена: chipdip.ru, категория 'kondensator-400v' (https://www.chipdip.ru/catalog/popular/kondensator-400v); ESR ОЦЕНКА 0.3-0.6 Ом. max_current_a — ОЦЕНКА ИМПУЛЬСНОГО тока для одиночного coilgun-выстрела (не ripple из даташита), ограничено ESR/фольгой; в пачке параллельно (как у пользователя, 8шт) суммируется"
|
||||
"source": "REAL цена: chipdip.ru, категория 'kondensator-400v' (https://www.chipdip.ru/catalog/popular/kondensator-400v); ESR ОЦЕНКА 0.3-0.6 Ом. max_current_a — ОЦЕНКА ИМПУЛЬСНОГО тока для одиночного coilgun-выстрела (не ripple из даташита), ограничено ESR/фольгой; в пачке параллельно (как у пользователя, 8шт) суммируется",
|
||||
"url": "https://www.chipdip.ru/catalog/popular/kondensator-400v"
|
||||
},
|
||||
{
|
||||
"part_number": "cap-68uf-400v",
|
||||
@@ -15,7 +16,8 @@
|
||||
"esr_ohm": 0.3,
|
||||
"max_current_a": 60.0,
|
||||
"price": 440.0,
|
||||
"source": "REAL цена: chipdip.ru (https://www.chipdip.ru/catalog/popular/kondensator-400v); ESR ОЦЕНКА. max_current_a — ОЦЕНКА импульсного тока (одиночный выстрел), не ripple"
|
||||
"source": "REAL цена: chipdip.ru (https://www.chipdip.ru/catalog/popular/kondensator-400v); ESR ОЦЕНКА. max_current_a — ОЦЕНКА импульсного тока (одиночный выстрел), не ripple",
|
||||
"url": "https://www.chipdip.ru/catalog/popular/kondensator-400v"
|
||||
},
|
||||
{
|
||||
"part_number": "cap-180uf-400v",
|
||||
@@ -24,7 +26,8 @@
|
||||
"esr_ohm": 0.15,
|
||||
"max_current_a": 120.0,
|
||||
"price": 109.9,
|
||||
"source": "REAL цена: procontact74.ru, CHANG 180uF 400V 105C (https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/180uf-400v-105c-2530-411213/); ESR ОЦЕНКА. max_current_a — ОЦЕНКА импульсного тока, не ripple"
|
||||
"source": "REAL цена: procontact74.ru, CHANG 180uF 400V 105C (https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/180uf-400v-105c-2530-411213/); ESR ОЦЕНКА. max_current_a — ОЦЕНКА импульсного тока, не ripple",
|
||||
"url": "https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/180uf-400v-105c-2530-411213/"
|
||||
},
|
||||
{
|
||||
"part_number": "cap-470uf-400v",
|
||||
@@ -33,7 +36,8 @@
|
||||
"esr_ohm": 0.08,
|
||||
"max_current_a": 250.0,
|
||||
"price": 498.0,
|
||||
"source": "REAL цена: procontact74.ru, JCCON 470uF 400V 105C 30x45мм (https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/kondensator-elektroliticheskiy----470uf-400v-105-c-35-45-cd294-elzet/), проверено, 325.84₽ от 5шт; ESR ОЦЕНКА ~0.05-0.1 Ом. max_current_a — ОЦЕНКА импульсного тока (низкий ESR -> держит сотни А в импульсе), не ripple"
|
||||
"source": "REAL цена: procontact74.ru, JCCON 470uF 400V 105C 30x45мм (https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/kondensator-elektroliticheskiy----470uf-400v-105-c-35-45-cd294-elzet/), проверено, 325.84₽ от 5шт; ESR ОЦЕНКА ~0.05-0.1 Ом. max_current_a — ОЦЕНКА импульсного тока (низкий ESR -> держит сотни А в импульсе), не ripple",
|
||||
"url": "https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/kondensator-elektroliticheskiy----470uf-400v-105-c-35-45-cd294-elzet/"
|
||||
},
|
||||
{
|
||||
"part_number": "cap-1000uf-400v",
|
||||
@@ -42,7 +46,8 @@
|
||||
"esr_ohm": 0.06,
|
||||
"max_current_a": 350.0,
|
||||
"price": 700.0,
|
||||
"source": "ОЦЕНКА (низкая уверенность по цене): категория подтверждена на procontact74.ru/asenergi.ru, точная цена не подтверждена. max_current_a — ОЦЕНКА импульсного тока для coilgun, не ripple"
|
||||
"source": "ОЦЕНКА (низкая уверенность по цене): категория подтверждена на procontact74.ru/asenergi.ru, точная цена не подтверждена. max_current_a — ОЦЕНКА импульсного тока для coilgun, не ripple",
|
||||
"url": "https://procontact74.ru/01-elektronnyie-komponentyi-/41-kondensatory/411-elektroliticheskie-kondensatory/"
|
||||
},
|
||||
{
|
||||
"part_number": "cap-2200uf-400v",
|
||||
@@ -51,6 +56,7 @@
|
||||
"esr_ohm": 0.05,
|
||||
"max_current_a": 450.0,
|
||||
"price": 1400.0,
|
||||
"source": "ОЦЕНКА (низкая уверенность по цене): категория подтверждена на asenergi.ru (https://asenergi.ru/catalog/kondensatory-elektroliticheskie/2200mkf.html). max_current_a — ОЦЕНКА импульсного тока для coilgun, не ripple"
|
||||
"source": "ОЦЕНКА (низкая уверенность по цене): категория подтверждена на asenergi.ru (https://asenergi.ru/catalog/kondensatory-elektroliticheskie/2200mkf.html). max_current_a — ОЦЕНКА импульсного тока для coilgun, не ripple",
|
||||
"url": "https://asenergi.ru/catalog/kondensatory-elektroliticheskie/2200mkf.html"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
"mu_r": 550.0,
|
||||
"b_sat_tesla": 1.9,
|
||||
"price_per_kg": 55.0,
|
||||
"resistivity_ohm_m": 1.6e-7,
|
||||
"source": "Цена REAL: горячекатаный круг Ст3, ros-met.com/metallurg-moskva.ru, ~49-60₽/кг (одна из позиций ~51.4₽/кг за тонну); плотность/μr/B_sat/resistivity — ОЦЕНКА (справочные значения для конструкционной стали; удельное сопротивление ~1.6e-7 Ом·м)"
|
||||
"resistivity_ohm_m": 1.6e-07,
|
||||
"source": "Цена REAL: горячекатаный круг Ст3, ros-met.com/metallurg-moskva.ru, ~49-60₽/кг (одна из позиций ~51.4₽/кг за тонну); плотность/μr/B_sat/resistivity — ОЦЕНКА (справочные значения для конструкционной стали; удельное сопротивление ~1.6e-7 Ом·м)",
|
||||
"url": "https://ros-met.com/krug-stalnoy-kupit/"
|
||||
},
|
||||
{
|
||||
"name": "Сталь 10 (низкоуглеродистая)",
|
||||
@@ -14,8 +15,9 @@
|
||||
"mu_r": 1500.0,
|
||||
"b_sat_tesla": 2.05,
|
||||
"price_per_kg": 55.0,
|
||||
"resistivity_ohm_m": 1.4e-7,
|
||||
"source": "ОЦЕНКА по всем полям: отдельного розничного объявления на 'Сталь 10' не найдено, цена той же полосы, что и Ст3 (~50-70₽/кг); μr выше из-за чистоты; удельное сопротивление ~1.4e-7 Ом·м — справочная оценка"
|
||||
"resistivity_ohm_m": 1.4e-07,
|
||||
"source": "ОЦЕНКА по всем полям: отдельного розничного объявления на 'Сталь 10' не найдено, цена той же полосы, что и Ст3 (~50-70₽/кг); μr выше из-за чистоты; удельное сопротивление ~1.4e-7 Ом·м — справочная оценка",
|
||||
"url": "https://ros-met.com/krug-stalnoy-kupit/"
|
||||
},
|
||||
{
|
||||
"name": "Армко-железо (чистое железо)",
|
||||
@@ -23,7 +25,8 @@
|
||||
"mu_r": 3500.0,
|
||||
"b_sat_tesla": 2.15,
|
||||
"price_per_kg": 160.0,
|
||||
"resistivity_ohm_m": 1.0e-7,
|
||||
"source": "ОЦЕНКА по всем полям: специализированный товар, розничной цены не найдено; цена ~3x от Ст3; μr/B_sat — справочные для отожжённого чистого железа; удельное сопротивление ~1.0e-7 Ом·м (чище -> ниже)"
|
||||
"resistivity_ohm_m": 1e-07,
|
||||
"source": "ОЦЕНКА по всем полям: специализированный товар, розничной цены не найдено; цена ~3x от Ст3; μr/B_sat — справочные для отожжённого чистого железа; удельное сопротивление ~1.0e-7 Ом·м (чище -> ниже)",
|
||||
"url": "https://ros-met.com/krug-stalnoy-kupit/"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
"kind": "hall",
|
||||
"propagation_delay_ns": 5000.0,
|
||||
"price": 19.9,
|
||||
"source": "REAL: procontact74.ru (https://procontact74.ru/01-elektronnyie-komponentyi-/34-datchiki/datchik-holla-a3144e-34111/), 19.90₽ (6.48₽ от 200шт); время срабатывания на странице не указано, ОЦЕНКА ~5мкс (середина типового диапазона 3-7мкс для А3144-класса)"
|
||||
"source": "REAL: procontact74.ru (https://procontact74.ru/01-elektronnyie-komponentyi-/34-datchiki/datchik-holla-a3144e-34111/), 19.90₽ (6.48₽ от 200шт); время срабатывания на странице не указано, ОЦЕНКА ~5мкс (середина типового диапазона 3-7мкс для А3144-класса)",
|
||||
"url": "https://procontact74.ru/01-elektronnyie-komponentyi-/34-datchiki/datchik-holla-a3144e-34111/"
|
||||
},
|
||||
{
|
||||
"part_number": "TCST2103",
|
||||
"kind": "optical",
|
||||
"propagation_delay_ns": 9000.0,
|
||||
"price": 220.0,
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/tcst2103-optopara-shirokogo-naznacheniya-4-pin-vishay-2693015011), 220₽ (161₽ от 200шт); время включения/выключения 8-10мкс — REAL с даташита Vishay, взята середина диапазона"
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/tcst2103-optopara-shirokogo-naznacheniya-4-pin-vishay-2693015011), 220₽ (161₽ от 200шт); время включения/выключения 8-10мкс — REAL с даташита Vishay, взята середина диапазона",
|
||||
"url": "https://www.chipdip.ru/product/tcst2103-optopara-shirokogo-naznacheniya-4-pin-vishay-2693015011"
|
||||
},
|
||||
{
|
||||
"part_number": "inductive-pickup-lm393",
|
||||
@@ -20,6 +22,7 @@
|
||||
"price": 15.0,
|
||||
"source": "ОЦЕНКА: не готовый компонент, а самодельная схема — виток(-и) провода (цена уже учтена в wires.json) + компаратор LM393 (~15₽, типовая розничная цена); время задержки 1.3мкс — реальный паспортный параметр LM393, но чувствительность/порог ниже — грубая оценка, не датащит-значение",
|
||||
"sensitivity_v_per_mps": 0.01,
|
||||
"threshold_v": 0.05
|
||||
"threshold_v": 0.05,
|
||||
"url": "https://www.chipdip.ru/search?searchtext=LM393"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"on_voltage_drop_v": 1.5,
|
||||
"turn_on_time_ns": 10000.0,
|
||||
"price": 140.0,
|
||||
"source": "REAL: КУ202Н, chipdip.ru (https://www.chipdip.ru/product/ku202n) 140₽ / procontact74.ru (https://procontact74.ru/44-tiristory/ku202n-tiristor-10a-400v-44011/) 189₽; Von=1.5В с даташита; время включения ОЦЕНКА ~10мкс (типично для тиристора этого класса, точное значение в листинге не приведено)"
|
||||
"source": "REAL: КУ202Н, chipdip.ru (https://www.chipdip.ru/product/ku202n) 140₽ / procontact74.ru (https://procontact74.ru/44-tiristory/ku202n-tiristor-10a-400v-44011/) 189₽; Von=1.5В с даташита; время включения ОЦЕНКА ~10мкс (типично для тиристора этого класса, точное значение в листинге не приведено)",
|
||||
"url": "https://www.chipdip.ru/product/ku202n"
|
||||
},
|
||||
{
|
||||
"part_number": "BT151-650R",
|
||||
@@ -19,7 +20,8 @@
|
||||
"on_voltage_drop_v": 1.7,
|
||||
"turn_on_time_ns": 1500.0,
|
||||
"price": 190.0,
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/bt151-650r), ~180-200₽ (BT151-600R вариант подтверждён на 180₽); Von и время включения ОЦЕНКА (типично для тиристора этого класса, не указаны продавцом)"
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/bt151-650r), ~180-200₽ (BT151-600R вариант подтверждён на 180₽); Von и время включения ОЦЕНКА (типично для тиристора этого класса, не указаны продавцом)",
|
||||
"url": "https://www.chipdip.ru/product/bt151-650r"
|
||||
},
|
||||
{
|
||||
"part_number": "IRFP254PBF",
|
||||
@@ -30,7 +32,8 @@
|
||||
"on_voltage_drop_v": null,
|
||||
"turn_on_time_ns": 30.0,
|
||||
"price": 39.9,
|
||||
"source": "REAL: procontact74.ru (https://procontact74.ru/01-elektronnyie-komponentyi-/43-tranzistory/polevyie--mosfet-/58406-tranzistorirfp254pbfmosfetnch250v23ato247acoriginalbydemontajnogi10mm/); ВНИМАНИЕ: демонтированная (Б/У) деталь, не новая партия; время включения ОЦЕНКА ~30нс (типично для этого класса MOSFET)"
|
||||
"source": "REAL: procontact74.ru (https://procontact74.ru/01-elektronnyie-komponentyi-/43-tranzistory/polevyie--mosfet-/58406-tranzistorirfp254pbfmosfetnch250v23ato247acoriginalbydemontajnogi10mm/); ВНИМАНИЕ: демонтированная (Б/У) деталь, не новая партия; время включения ОЦЕНКА ~30нс (типично для этого класса MOSFET)",
|
||||
"url": "https://procontact74.ru/01-elektronnyie-komponentyi-/43-tranzistory/polevyie--mosfet-/58406-tranzistorirfp254pbfmosfetnch250v23ato247acoriginalbydemontajnogi10mm/"
|
||||
},
|
||||
{
|
||||
"part_number": "IRFP250PBF",
|
||||
@@ -41,7 +44,8 @@
|
||||
"on_voltage_drop_v": null,
|
||||
"turn_on_time_ns": 35.0,
|
||||
"price": 320.0,
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irfp250), новая деталь, 320₽ (276₽ от 15шт, 245₽ от 150шт); Rds(on)=0.085Ом при 18А/10В с даташита; время включения ОЦЕНКА"
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irfp250), новая деталь, 320₽ (276₽ от 15шт, 245₽ от 150шт); Rds(on)=0.085Ом при 18А/10В с даташита; время включения ОЦЕНКА",
|
||||
"url": "https://www.chipdip.ru/product/irfp250"
|
||||
},
|
||||
{
|
||||
"part_number": "IRFP4468PBF",
|
||||
@@ -52,7 +56,8 @@
|
||||
"on_voltage_drop_v": null,
|
||||
"turn_on_time_ns": 40.0,
|
||||
"price": 610.0,
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irfp4468pbf), 610₽ (534₽ от 15шт); паспортный максимум 290А при 25°C, взято консервативное практическое значение 180А; Rds(on)=0.0026Ом при 180А/10В с даташита; время включения ОЦЕНКА"
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irfp4468pbf), 610₽ (534₽ от 15шт); паспортный максимум 290А при 25°C, взято консервативное практическое значение 180А; Rds(on)=0.0026Ом при 180А/10В с даташита; время включения ОЦЕНКА",
|
||||
"url": "https://www.chipdip.ru/product/irfp4468pbf"
|
||||
},
|
||||
{
|
||||
"part_number": "IRG4PC50F",
|
||||
@@ -63,6 +68,7 @@
|
||||
"on_voltage_drop_v": 1.8,
|
||||
"turn_on_time_ns": 300.0,
|
||||
"price": 504.0,
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irg4pc50f-8048990896), ~504₽; Vce(sat) и время включения ОЦЕНКА (типично для этого семейства IGBT, не подтверждено со страницы товара)"
|
||||
"source": "REAL: chipdip.ru (https://www.chipdip.ru/product/irg4pc50f-8048990896), ~504₽; Vce(sat) и время включения ОЦЕНКА (типично для этого семейства IGBT, не подтверждено со страницы товара)",
|
||||
"url": "https://www.chipdip.ru/product/irg4pc50f-8048990896"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 0.35,
|
||||
"price_per_m": 3.5,
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 0.3мм, 1050₽/200г-катушка ~300м (https://www.chipdip.ru/product/petv-2-d-0.3-mm-provod-emalirovannyy-obmotochnyy-300m-dlina-9000272019)"
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 0.3мм, 1050₽/200г-катушка ~300м (https://www.chipdip.ru/product/petv-2-d-0.3-mm-provod-emalirovannyy-obmotochnyy-300m-dlina-9000272019)",
|
||||
"url": "https://www.chipdip.ru/product/petv-2-d-0.3-mm-provod-emalirovannyy-obmotochnyy-300m-dlina-9000272019"
|
||||
},
|
||||
{
|
||||
"part_id": "cu-petv2-0.71mm",
|
||||
@@ -17,7 +18,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 1.98,
|
||||
"price_per_m": 16.2,
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 0.71мм, 890₽/200г-катушка ~55м (https://www.chipdip.ru/product/petv-2-d-0.71-mm)"
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 0.71мм, 890₽/200г-катушка ~55м (https://www.chipdip.ru/product/petv-2-d-0.71-mm)",
|
||||
"url": "https://www.chipdip.ru/product/petv-2-d-0.71-mm"
|
||||
},
|
||||
{
|
||||
"part_id": "cu-petv2-1.0mm",
|
||||
@@ -27,7 +29,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 3.93,
|
||||
"price_per_m": 8.445,
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 1.0мм, 1200₽/кг (https://www.chipdip.ru/product0/9000289279); ₽/м пересчитано нами из ₽/кг"
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 1.0мм, 1200₽/кг (https://www.chipdip.ru/product0/9000289279); ₽/м пересчитано нами из ₽/кг",
|
||||
"url": "https://www.chipdip.ru/product0/9000289279"
|
||||
},
|
||||
{
|
||||
"part_id": "cu-petv2-1.4mm",
|
||||
@@ -37,7 +40,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 7.7,
|
||||
"price_per_m": 45.266,
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 1.4мм, 3610₽/1.1кг-упаковка (https://www.chipdip.ru/product0/8004178560); ₽/м пересчитано нами из ₽/кг"
|
||||
"source": "REAL: chipdip.ru, ПЭТВ-2 1.4мм, 3610₽/1.1кг-упаковка (https://www.chipdip.ru/product0/8004178560); ₽/м пересчитано нами из ₽/кг",
|
||||
"url": "https://www.chipdip.ru/product0/8004178560"
|
||||
},
|
||||
{
|
||||
"part_id": "cu-petv2-0.8mm",
|
||||
@@ -47,7 +51,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 2.51,
|
||||
"price_per_m": 11.259,
|
||||
"source": "ОЦЕНКА: товар реален на chipdip.ru (https://www.chipdip.ru/product0/8004178423), но точная цена не подтверждена при парсинге; 2500₽/кг интерполировано между подтверждёнными 0.71мм (~4566₽/кг) и 1.0мм (1200₽/кг)"
|
||||
"source": "ОЦЕНКА: товар реален на chipdip.ru (https://www.chipdip.ru/product0/8004178423), но точная цена не подтверждена при парсинге; 2500₽/кг интерполировано между подтверждёнными 0.71мм (~4566₽/кг) и 1.0мм (1200₽/кг)",
|
||||
"url": "https://www.chipdip.ru/product0/8004178423"
|
||||
},
|
||||
{
|
||||
"part_id": "cu-petv2-2.0mm",
|
||||
@@ -57,7 +62,8 @@
|
||||
"resistivity_ohm_m": 1.68e-08,
|
||||
"max_current_a": 15.71,
|
||||
"price_per_m": 30.964,
|
||||
"source": "ОЦЕНКА: chipdip.ru (https://www.chipdip.ru/product0/9000289280), цена частично 'по запросу', взята середина наблюдаемого диапазона 1000-1200₽/кг"
|
||||
"source": "ОЦЕНКА: chipdip.ru (https://www.chipdip.ru/product0/9000289280), цена частично 'по запросу', взята середина наблюдаемого диапазона 1000-1200₽/кг",
|
||||
"url": "https://www.chipdip.ru/product0/9000289280"
|
||||
},
|
||||
{
|
||||
"part_id": "al-0.3mm",
|
||||
@@ -67,7 +73,8 @@
|
||||
"resistivity_ohm_m": 2.82e-08,
|
||||
"max_current_a": 0.28,
|
||||
"price_per_m": 1.4,
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)"
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)",
|
||||
"url": "https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php"
|
||||
},
|
||||
{
|
||||
"part_id": "al-0.71mm",
|
||||
@@ -77,7 +84,8 @@
|
||||
"resistivity_ohm_m": 2.82e-08,
|
||||
"max_current_a": 1.58,
|
||||
"price_per_m": 6.48,
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)"
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)",
|
||||
"url": "https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php"
|
||||
},
|
||||
{
|
||||
"part_id": "al-1.0mm",
|
||||
@@ -87,7 +95,8 @@
|
||||
"resistivity_ohm_m": 2.82e-08,
|
||||
"max_current_a": 3.14,
|
||||
"price_per_m": 3.378,
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)"
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)",
|
||||
"url": "https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php"
|
||||
},
|
||||
{
|
||||
"part_id": "al-1.4mm",
|
||||
@@ -97,6 +106,7 @@
|
||||
"resistivity_ohm_m": 2.82e-08,
|
||||
"max_current_a": 6.16,
|
||||
"price_per_m": 18.106,
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)"
|
||||
"source": "ОЦЕНКА: алюминиевый эмальпровод в рознице РФ практически не продаётся поштучно (cable.ru и др. требуют запрос цены, см. https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php); цена оценена как 0.4x от цены медного провода того же сечения (типовое соотношение стоимости сырья Cu/Al)",
|
||||
"url": "https://cable.ru/cable/kabel-alyuminij_obmotochnyj_v_razdel-9.php"
|
||||
}
|
||||
]
|
||||
@@ -14,6 +14,7 @@ class WireSpec:
|
||||
max_current_a: float
|
||||
price_per_m: float
|
||||
source: str
|
||||
url: str | None = None # прямая ссылка на магазин, где купить
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -25,6 +26,7 @@ class CapacitorSpec:
|
||||
max_current_a: float
|
||||
price: float
|
||||
source: str
|
||||
url: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -46,6 +48,7 @@ class CapacitorBank:
|
||||
esr_ohm: float
|
||||
max_current_a: float
|
||||
price: float
|
||||
url: str | None = None
|
||||
|
||||
@property
|
||||
def count(self) -> int:
|
||||
@@ -64,6 +67,7 @@ class CapacitorBank:
|
||||
esr_ohm=spec.esr_ohm * n_series / n_parallel,
|
||||
max_current_a=spec.max_current_a * n_parallel,
|
||||
price=spec.price * n_series * n_parallel,
|
||||
url=spec.url,
|
||||
)
|
||||
|
||||
|
||||
@@ -78,6 +82,7 @@ class SwitchSpec:
|
||||
turn_on_time_ns: float
|
||||
price: float
|
||||
source: str
|
||||
url: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -89,6 +94,7 @@ class SensorSpec:
|
||||
source: str
|
||||
sensitivity_v_per_mps: float | None = None
|
||||
threshold_v: float | None = None
|
||||
url: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -102,3 +108,4 @@ class ProjectileMaterialSpec:
|
||||
# электрическое удельное сопротивление — для расчёта вихревых потерь в снаряде
|
||||
# (сплошной проводник в импульсном поле). Дефолт ~ конструкционная сталь.
|
||||
resistivity_ohm_m: float = 1.6e-7
|
||||
url: str | None = None
|
||||
|
||||
@@ -131,27 +131,37 @@ def build_detail(config, coilgun_result: CoilgunResult, db: ComponentDatabase, i
|
||||
"wire": stage.wire.part_id,
|
||||
"wire_material": stage.wire.material,
|
||||
"wire_gauge_mm": stage.wire.gauge_mm,
|
||||
"wire_insulation_od_mm": stage.wire.insulation_od_mm,
|
||||
"wire_url": stage.wire.url,
|
||||
"switch": stage.switch.part_number,
|
||||
"switch_kind": stage.switch.kind,
|
||||
"switch_max_current_a": stage.switch.max_current_a,
|
||||
"switch_max_voltage_v": stage.switch.max_voltage_v,
|
||||
"switch_url": stage.switch.url,
|
||||
"sensor": stage.sensor.part_number,
|
||||
"sensor_kind": stage.sensor.kind,
|
||||
"sensor_url": stage.sensor.url,
|
||||
},
|
||||
"capacitor_bank": {
|
||||
"base_part": cap_base,
|
||||
"n_series": n_series,
|
||||
"n_parallel": n_parallel,
|
||||
"count": n_series * n_parallel,
|
||||
"single_capacitance_uf": getattr(cap, "capacitance_uf", 0) * n_series / max(n_parallel, 1),
|
||||
"single_voltage_rating_v": getattr(cap, "voltage_v", 0) / max(n_series, 1),
|
||||
"total_capacitance_uf": cap.capacitance_uf,
|
||||
"total_voltage_rating_v": cap.voltage_v,
|
||||
"total_esr_ohm": cap.esr_ohm,
|
||||
"max_current_a": cap.max_current_a,
|
||||
"url": getattr(cap, "url", None),
|
||||
},
|
||||
"winding": {
|
||||
"turns_per_layer": stage.turns_per_layer,
|
||||
"layers": stage.layers,
|
||||
"total_turns": geometry.total_turns,
|
||||
"coil_length_m": geometry.coil_length_m,
|
||||
"coil_inner_diameter_m": stage.tube_od_m, # = внешний диаметр трубы
|
||||
"coil_outer_diameter_m": stage.tube_od_m + 2 * geometry.radial_depth_m,
|
||||
"mean_radius_m": geometry.mean_radius_m,
|
||||
"radial_depth_m": geometry.radial_depth_m,
|
||||
"total_wire_length_m": geometry.total_wire_length_m,
|
||||
@@ -214,7 +224,9 @@ def build_detail(config, coilgun_result: CoilgunResult, db: ComponentDatabase, i
|
||||
"mass_g": projectile.mass_kg * 1000,
|
||||
"mu_r": projectile.material.mu_r,
|
||||
"b_sat_tesla": projectile.material.b_sat_tesla,
|
||||
"resistivity_ohm_m": projectile.material.resistivity_ohm_m,
|
||||
"fits_in_bore": (tube_inner_d_m is None) or (projectile.diameter_m < tube_inner_d_m),
|
||||
"url": projectile.material.url,
|
||||
},
|
||||
"launch": {"initial_x_m": initial_x_m, "initial_v_mps": initial_v_mps},
|
||||
"n_stages": len(config.stages),
|
||||
|
||||
@@ -21,44 +21,57 @@ from gausse.sim.coilgun import CoilgunConfig, CoilgunResult
|
||||
|
||||
|
||||
def _build_global_timeline(result: CoilgunResult, config: CoilgunConfig, fps: int):
|
||||
"""Возвращает (times, positions, per_stage_current_at_time) с равномерным шагом."""
|
||||
segments_t = []
|
||||
segments_x = []
|
||||
segments_i = [] # ток КАЖДОЙ катушки в момент времени (список массивов той же длины, что t)
|
||||
"""Непрерывная траектория снаряда: коаст (по инерции) + разряды по ступеням.
|
||||
|
||||
Строится ПОСЛЕДОВАТЕЛЬНО (без сортировки по времени, которая рвала
|
||||
траекторию): между разрядами снаряд летит по инерции от конца прошлого
|
||||
разряда до начала следующего; во время разряда берём точно посчитанные
|
||||
discharge_x/v/i. Глобальная координата = центр катушки ступени + локальный
|
||||
discharge_x. Ток каждой катушки задан только в окне её собственного разряда.
|
||||
"""
|
||||
n_stages = len(config.stages)
|
||||
seg_t, seg_x = [], []
|
||||
seg_i = [[] for _ in range(n_stages)]
|
||||
|
||||
t_cursor = 0.0
|
||||
prev_global_x = None
|
||||
prev_v = None
|
||||
|
||||
for outcome in result.stage_outcomes:
|
||||
r = outcome.result
|
||||
# Баллистический подлёт к датчику: постоянная скорость, восстанавливается аналитически
|
||||
# (в модели v1 нет трения на этом участке — см. sim/stage.py::_ballistic_derivatives).
|
||||
t_sensor = r.t_sensor_s if r.t_sensor_s is not None else 0.0
|
||||
flight_t = np.linspace(0.0, t_sensor, max(int(t_sensor * fps) + 2, 2))
|
||||
flight_x = outcome.entry_x_m + outcome.entry_v_mps * flight_t
|
||||
flight_global_t = outcome.time_offset_s + flight_t
|
||||
flight_global_x = outcome.global_coil_center_m + flight_x
|
||||
flight_currents = [np.zeros_like(flight_t) for _ in range(n_stages)]
|
||||
flight_currents[outcome.stage_index] = np.zeros_like(flight_t)
|
||||
segments_t.append(flight_global_t)
|
||||
segments_x.append(flight_global_x)
|
||||
segments_i.append(flight_currents)
|
||||
if r.discharge_t is None or r.discharge_x is None:
|
||||
continue
|
||||
disch_global_x = outcome.global_coil_center_m + r.discharge_x
|
||||
start_global_x = float(disch_global_x[0])
|
||||
|
||||
if r.discharge_t is not None:
|
||||
discharge_global_t = outcome.time_offset_s + (r.t_fire_s or 0.0) + r.discharge_t
|
||||
discharge_global_x = outcome.global_coil_center_m + r.discharge_x
|
||||
discharge_currents = [np.zeros_like(r.discharge_t) for _ in range(n_stages)]
|
||||
discharge_currents[outcome.stage_index] = r.discharge_i
|
||||
segments_t.append(discharge_global_t)
|
||||
segments_x.append(discharge_global_x)
|
||||
segments_i.append(discharge_currents)
|
||||
# коаст по инерции от конца прошлого разряда до начала этого
|
||||
if prev_global_x is not None and prev_v and prev_v > 1e-6:
|
||||
coast_dist = start_global_x - prev_global_x
|
||||
coast_dur = max(coast_dist / prev_v, 0.0)
|
||||
n_coast = max(int(coast_dur * fps) + 2, 2)
|
||||
ct = np.linspace(0.0, coast_dur, n_coast)
|
||||
seg_t.append(t_cursor + ct)
|
||||
seg_x.append(np.linspace(prev_global_x, start_global_x, n_coast))
|
||||
for s in range(n_stages):
|
||||
seg_i[s].append(np.zeros(n_coast))
|
||||
t_cursor += coast_dur
|
||||
|
||||
times = np.concatenate(segments_t)
|
||||
positions = np.concatenate(segments_x)
|
||||
currents = [np.concatenate([seg[stage] for seg in segments_i]) for stage in range(n_stages)]
|
||||
# окно разряда: точная траектория + ток именно этой катушки
|
||||
seg_t.append(t_cursor + r.discharge_t)
|
||||
seg_x.append(disch_global_x)
|
||||
for s in range(n_stages):
|
||||
seg_i[s].append(r.discharge_i if s == outcome.stage_index else np.zeros_like(r.discharge_t))
|
||||
t_cursor += float(r.discharge_t[-1])
|
||||
|
||||
order = np.argsort(times)
|
||||
times = times[order]
|
||||
positions = positions[order]
|
||||
currents = [c[order] for c in currents]
|
||||
prev_global_x = float(disch_global_x[-1])
|
||||
prev_v = float(r.discharge_v[-1]) if r.discharge_v is not None else outcome.entry_v_mps
|
||||
|
||||
if not seg_t:
|
||||
raise ValueError("нет данных разряда для анимации")
|
||||
|
||||
times = np.concatenate(seg_t)
|
||||
positions = np.concatenate(seg_x)
|
||||
currents = [np.concatenate(seg_i[s]) for s in range(n_stages)]
|
||||
return times, positions, currents
|
||||
|
||||
|
||||
@@ -81,20 +94,30 @@ def animate_run(result: CoilgunResult, config: CoilgunConfig, out_path: str, fps
|
||||
ax.set_yticks([])
|
||||
ax.set_title("Пролёт снаряда через ступени")
|
||||
|
||||
tube_line = ax.axhline(0, color="gray", linewidth=2, zorder=1)
|
||||
coil_dots = [
|
||||
ax.scatter([c * 1e3], [0], s=400, c="lightgray", edgecolors="black", zorder=2)
|
||||
for c in coil_centers
|
||||
]
|
||||
slug_dot = ax.scatter([], [], s=150, c="red", zorder=3)
|
||||
time_text = ax.text(0.02, 0.9, "", transform=ax.transAxes)
|
||||
ax.axhline(0, color="#888", linewidth=3, zorder=1) # труба
|
||||
coil_dots = []
|
||||
for k, c in enumerate(coil_centers):
|
||||
dot = ax.scatter([c * 1e3], [0], s=600, c="lightgray", edgecolors="#333", linewidths=1.5, zorder=2)
|
||||
ax.annotate(f"катушка {k}", (c * 1e3, 0), textcoords="offset points", xytext=(0, 22),
|
||||
ha="center", fontsize=8, color="#555")
|
||||
coil_dots.append(dot)
|
||||
slug_dot = ax.scatter([], [], s=180, c="#1f4e8c", edgecolors="white", linewidths=1, zorder=3)
|
||||
time_text = ax.text(0.02, 0.88, "", transform=ax.transAxes, fontsize=10)
|
||||
|
||||
def _coil_color(intensity):
|
||||
# выкл -> светло-серый; максимум тока -> яркое золото (свечение поля)
|
||||
t = min(max(intensity, 0.0), 1.0)
|
||||
off = np.array([0.83, 0.83, 0.83])
|
||||
on = np.array([1.0, 0.78, 0.0])
|
||||
return tuple(off + (on - off) * t)
|
||||
|
||||
def update(frame_i):
|
||||
idx = frame_idx[frame_i]
|
||||
slug_dot.set_offsets([[positions[idx] * 1e3, 0]])
|
||||
for stage_idx, dots in enumerate(coil_dots):
|
||||
intensity = abs(currents[stage_idx][idx]) / max_current_per_stage[stage_idx]
|
||||
dots.set_color(plt.cm.autumn(1.0 - min(intensity, 1.0)))
|
||||
dots.set_color(_coil_color(intensity))
|
||||
dots.set_sizes([600 + 400 * min(intensity, 1.0)]) # чуть раздувается при разряде
|
||||
time_text.set_text(f"t = {times[idx] * 1e3:.3f} мс")
|
||||
return [slug_dot, time_text, *coil_dots]
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class BomLine:
|
||||
unit_price_rub: float
|
||||
total_price_rub: float
|
||||
note: str = ""
|
||||
url: str | None = None # ссылка на магазин, где купить
|
||||
|
||||
|
||||
def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
@@ -30,7 +31,8 @@ def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
quantity=f"{wire_length_m:.2f} м",
|
||||
unit_price_rub=stage.wire.price_per_m,
|
||||
total_price_rub=wire_length_m * stage.wire.price_per_m,
|
||||
note=f"{geometry.total_turns} витков ({stage.turns_per_layer}x{stage.layers})",
|
||||
note=f"{geometry.total_turns} витков ({stage.turns_per_layer}x{stage.layers}), ⌀{stage.wire.gauge_mm}мм",
|
||||
url=stage.wire.url,
|
||||
)
|
||||
)
|
||||
cap = stage.capacitor
|
||||
@@ -47,6 +49,7 @@ def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
unit_price_rub=unit_price,
|
||||
total_price_rub=cap.price,
|
||||
note=f"батарея {cap.capacitance_uf:.0f}мкФ {cap.voltage_v:.0f}В, заряд {stage.charge_voltage_v:.0f}В, макс.ток {cap.max_current_a:.0f}А",
|
||||
url=getattr(cap, "url", None),
|
||||
)
|
||||
)
|
||||
lines.append(
|
||||
@@ -56,7 +59,8 @@ def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
quantity="1 шт",
|
||||
unit_price_rub=stage.switch.price,
|
||||
total_price_rub=stage.switch.price,
|
||||
note=stage.switch.kind,
|
||||
note=f"{stage.switch.kind}, {stage.switch.max_current_a:.0f}А / {stage.switch.max_voltage_v:.0f}В",
|
||||
url=stage.switch.url,
|
||||
)
|
||||
)
|
||||
lines.append(
|
||||
@@ -67,6 +71,7 @@ def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
unit_price_rub=stage.sensor.price,
|
||||
total_price_rub=stage.sensor.price,
|
||||
note=stage.sensor.kind,
|
||||
url=stage.sensor.url,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -79,6 +84,7 @@ def build_bom(config: CoilgunConfig, db: ComponentDatabase) -> list[BomLine]:
|
||||
unit_price_rub=config.projectile.material.price_per_kg,
|
||||
total_price_rub=mass_kg * config.projectile.material.price_per_kg,
|
||||
note=f"⌀{config.projectile.diameter_m * 1000:.1f}мм x {config.projectile.length_m * 1000:.1f}мм",
|
||||
url=config.projectile.material.url,
|
||||
)
|
||||
)
|
||||
return lines
|
||||
@@ -89,12 +95,12 @@ def total_cost_rub(lines: list[BomLine]) -> float:
|
||||
|
||||
|
||||
def render_bom_text(lines: list[BomLine]) -> str:
|
||||
rows = ["Ступень\tДеталь\tКол-во\tЦена/ед\tИтого\tПримечание"]
|
||||
rows = ["Ступень\tДеталь\tКол-во\tЦена/ед\tИтого\tПримечание\tКупить"]
|
||||
for line in lines:
|
||||
stage_label = "-" if line.stage_index is None else str(line.stage_index)
|
||||
rows.append(
|
||||
f"{stage_label}\t{line.part}\t{line.quantity}\t{line.unit_price_rub:.2f}₽\t"
|
||||
f"{line.total_price_rub:.2f}₽\t{line.note}"
|
||||
f"{line.total_price_rub:.2f}₽\t{line.note}\t{line.url or ''}"
|
||||
)
|
||||
rows.append(f"\t\t\t\tИТОГО: {total_cost_rub(lines):.2f}₽\t")
|
||||
rows.append(f"\t\t\t\tИТОГО: {total_cost_rub(lines):.2f}₽\t\t")
|
||||
return "\n".join(rows)
|
||||
|
||||
Reference in New Issue
Block a user