From 4cfa946315e9ba6f111df4bd0d82102ff44a2454 Mon Sep 17 00:00:00 2001 From: jze9 Date: Tue, 7 Jul 2026 22:19:32 +0500 Subject: [PATCH] Enforce per-stage sensor placement in the gap; report absolute sensor position The model already gave every coil its own sensor, its own sensor->coil distance, and searched inter-coil gaps (all of which set when each later coil fires) -- confirmed on a 3-stage run. Two refinements from user feedback: - Each stage's sensor must sit in the gap BEFORE its coil, not overlap the previous coil: repair() now clamps sensor_to_coil_distance < gap for stages > 0. sample_genome now also routes through repair() (it didn't before, so freshly sampled genomes skipped every physical constraint). Verified: 161/780 previously-overlapping sensors -> 0. - build_detail now records each sensor's absolute position along the tube (sensor_position_m), not just the relative distance, so it's clear where every stage's sensor physically sits. Co-Authored-By: Claude Sonnet 5 --- src/gausse/optim/objective.py | 2 ++ src/gausse/optim/search_space.py | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/gausse/optim/objective.py b/src/gausse/optim/objective.py index 551614c..e59f6cf 100644 --- a/src/gausse/optim/objective.py +++ b/src/gausse/optim/objective.py @@ -127,6 +127,8 @@ def build_detail(config, coilgun_result: CoilgunResult, db: ComponentDatabase, i "coil_center_position_m": coil_centers_m[i], "gap_before_stage_m": (config.inter_stage_gaps_m[i - 1] if i > 0 else None), "sensor_to_coil_distance_m": stage.sensor_to_coil_distance_m, + # абсолютная позиция ЭТОГО датчика вдоль трубы (у каждой катушки свой) + "sensor_position_m": coil_centers_m[i] - stage.sensor_to_coil_distance_m, "components": { "wire": stage.wire.part_id, "wire_material": stage.wire.material, diff --git a/src/gausse/optim/search_space.py b/src/gausse/optim/search_space.py index 1d79c04..d7060fe 100644 --- a/src/gausse/optim/search_space.py +++ b/src/gausse/optim/search_space.py @@ -140,10 +140,13 @@ def sample_genome(db: ComponentDatabase, bounds: SearchBounds, rng: random.Rando for _ in range(n_stages - 1) ] projectile = ProjectileGene(material_idx=material_idx, diameter_m=diameter_m, length_m=length_m) - return Genome( + genome = Genome( tube_inner_d_m=tube_inner_d_m, tube_wall_m=tube_wall_m, stages=stages, inter_stage_gaps_m=gaps, projectile=projectile, ) + # прогоняем через repair, чтобы применились все физические ограничения + # (в т.ч. датчик каждой ступени должен стоять в зазоре перед своей катушкой) + return repair(genome, db, bounds) def repair(genome: Genome, db: ComponentDatabase, bounds: SearchBounds) -> Genome: @@ -188,6 +191,15 @@ def repair(genome: Genome, db: ComponentDatabase, bounds: SearchBounds) -> Genom genome.inter_stage_gaps_m.append( (bounds.inter_stage_gap_m_min + bounds.inter_stage_gap_m_max) / 2 ) + # Датчик ступени i>0 должен стоять В ЗАЗОРЕ перед своей катушкой, а не + # залезать на предыдущую: расстояние датчик→катушка < зазор до пред.катушки. + # (у первой катушки датчик перед ней в свободном пространстве — без ограничения.) + for i in range(1, len(genome.stages)): + gap = genome.inter_stage_gaps_m[i - 1] + max_s2c = max(gap * 0.9, bounds.sensor_to_coil_distance_m_min) + genome.stages[i].sensor_to_coil_distance_m = min( + genome.stages[i].sensor_to_coil_distance_m, max_s2c + ) return genome