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:
@@ -127,6 +127,8 @@ def build_detail(config, coilgun_result: CoilgunResult, db: ComponentDatabase, i
|
|||||||
"coil_center_position_m": coil_centers_m[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),
|
"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_to_coil_distance_m": stage.sensor_to_coil_distance_m,
|
||||||
|
# абсолютная позиция ЭТОГО датчика вдоль трубы (у каждой катушки свой)
|
||||||
|
"sensor_position_m": coil_centers_m[i] - stage.sensor_to_coil_distance_m,
|
||||||
"components": {
|
"components": {
|
||||||
"wire": stage.wire.part_id,
|
"wire": stage.wire.part_id,
|
||||||
"wire_material": stage.wire.material,
|
"wire_material": stage.wire.material,
|
||||||
|
|||||||
@@ -140,10 +140,13 @@ def sample_genome(db: ComponentDatabase, bounds: SearchBounds, rng: random.Rando
|
|||||||
for _ in range(n_stages - 1)
|
for _ in range(n_stages - 1)
|
||||||
]
|
]
|
||||||
projectile = ProjectileGene(material_idx=material_idx, diameter_m=diameter_m, length_m=length_m)
|
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,
|
tube_inner_d_m=tube_inner_d_m, tube_wall_m=tube_wall_m,
|
||||||
stages=stages, inter_stage_gaps_m=gaps, projectile=projectile,
|
stages=stages, inter_stage_gaps_m=gaps, projectile=projectile,
|
||||||
)
|
)
|
||||||
|
# прогоняем через repair, чтобы применились все физические ограничения
|
||||||
|
# (в т.ч. датчик каждой ступени должен стоять в зазоре перед своей катушкой)
|
||||||
|
return repair(genome, db, bounds)
|
||||||
|
|
||||||
|
|
||||||
def repair(genome: Genome, db: ComponentDatabase, bounds: SearchBounds) -> Genome:
|
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(
|
genome.inter_stage_gaps_m.append(
|
||||||
(bounds.inter_stage_gap_m_min + bounds.inter_stage_gap_m_max) / 2
|
(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
|
return genome
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user