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 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-07-07 22:19:32 +05:00
parent 7803e147a7
commit 4cfa946315
2 changed files with 15 additions and 1 deletions

View File

@@ -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,

View File

@@ -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