Skip to content

Commit dc8605e

Browse files
committed
pr updates
1 parent 99e41ca commit dc8605e

107 files changed

Lines changed: 1289 additions & 1167 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ smooth parametric descriptions of heliostats.
2727

2828
**Our contributions include:**
2929

30-
- **Efficient heliostat calibration:** We develop a parallelized geometric kinematic model that enables efficient
30+
- **Efficient heliostat calibration:** We develop a parallelized geometric kinematics model that enables efficient
3131
calibration via either ray tracing-based or motor position data. This offers a flexible and robust approach to
3232
heliostat calibration.
3333

artist/core/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
HeliostatRayTracer,
66
RestrictedDistributedSampler,
77
)
8-
from artist.core.kinematic_reconstructor import KinematicReconstructor
8+
from artist.core.kinematics_reconstructor import KinematicsReconstructor
99
from artist.core.motor_position_optimizer import MotorPositionsOptimizer
1010
from artist.core.surface_reconstructor import SurfaceReconstructor
1111

1212
__all__ = [
1313
"HeliostatRayTracer",
1414
"DistortionsDataset",
1515
"RestrictedDistributedSampler",
16-
"KinematicReconstructor",
16+
"KinematicsReconstructor",
1717
"SurfaceReconstructor",
1818
"MotorPositionsOptimizer",
1919
]

artist/core/blocking.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
def create_blocking_primitives_rectangle(
1111
blocking_heliostats_surface_points: torch.Tensor,
1212
blocking_heliostats_active_surface_points: torch.Tensor,
13-
epsilon: float = 0.05,
1413
device: torch.device | None = None,
1514
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
1615
"""
@@ -40,8 +39,6 @@ def create_blocking_primitives_rectangle(
4039
blocking_heliostats_active_surface_points : torch.Tensor
4140
The aligned surface points of all heliostats that might block other heliostats.
4241
Tensor of shape [number_of_heliostats, number_of_combined_surface_points_all_facets, 4].
43-
epsilon : float
44-
A small value (default is 0.05).
4542
device : torch.device | None
4643
The device on which to perform computations or load tensors and models (default is None).
4744
If None, ``ARTIST`` will automatically select the most appropriate
@@ -263,6 +260,7 @@ def soft_ray_blocking_mask(
263260
A soft blocking mask.
264261
Shape is [number_of_blocking_primitives, number_of_rays, number_of_combined_surface_points_all_facets].
265262
"""
263+
# Dimensions [#heliostats, #rays, #surface_points, #blocking_primitives, 3D coordinates].
266264
ray_origins = ray_origins[:, None, :, None, :3]
267265
ray_directions = ray_directions[:, :, :, None, :3]
268266

@@ -271,6 +269,7 @@ def soft_ray_blocking_mask(
271269
span_v = blocking_primitives_spans[None, None, None, :, 1, :3]
272270
blocking_primitives_normals = blocking_primitives_normals[None, None, None, :, :3]
273271

272+
# Solve the plane equation.
274273
denominator = torch.sum(ray_directions * blocking_primitives_normals, dim=-1)
275274
distances_to_blocking_planes = torch.sum(
276275
(corner_0 - ray_origins) * blocking_primitives_normals, dim=-1
@@ -408,14 +407,14 @@ def morton_codes(
408407
# Normalize coordinates to [0,1 - epsilon).
409408
spans = bounding_box_max - bounding_box_min
410409
spans[spans == 0] = 1.0
411-
norm = (coordinates - bounding_box_min[None, :]) / spans[None, :]
412-
norm = norm.clamp(0.0, 1.0 - epsilon)
410+
coordinates_normed = (coordinates - bounding_box_min[None, :]) / spans[None, :]
411+
coordinates_normed = coordinates_normed.clamp(0.0, 1.0 - epsilon)
413412

414413
# Determine number of discrete positions along each axis (1024).
415414
scale = float(1 << bits)
416415

417416
# Scale normalized coordinates to integer values from 0 to 1024.
418-
qi = (norm * scale).to(torch.int64)
417+
qi = (coordinates_normed * scale).to(torch.int64)
419418
xi = qi[:, 0].to(torch.int64)
420419
yi = qi[:, 1].to(torch.int64)
421420
zi = qi[:, 2].to(torch.int64)
@@ -573,7 +572,7 @@ def build_linear_bounding_volume_hierarchies(
573572
blocking_primitives_corners: torch.Tensor, device: torch.device | None = None
574573
) -> dict[str, torch.Tensor]:
575574
"""
576-
Build linear bounding volume heirachies (LBVHs).
575+
Build linear bounding volume hierarchies (LBVHs).
577576
578577
Reference: Tero Karras. Maximizing Parallelism in the Construction of BVHs, Octrees, and k‑d Trees.
579578
In Proceedings of the Fourth ACM SIGGRAPH / Eurographics Symposium on High‑Performance Graphics (HPG 2012)
@@ -591,10 +590,10 @@ def build_linear_bounding_volume_hierarchies(
591590
Returns
592591
-------
593592
dict[str, torch.Tensor]
594-
- left, right: Indices of the left and right child of each LBVH node (-1 if leave).
595-
- aabb_min, aabb_max: axis aligned bounding boxes.
596-
- is_leaf: boolean, indicating whether a node is a leaf node.
597-
- primitive_index: indicates which primitives are contained.
593+
- left, right: Indices of the left and right child of each LBVH node (-1 if leaf).
594+
- aabb_min, aabb_max: Axis aligned bounding boxes.
595+
- is_leaf: Boolean, indicating whether a node is a leaf node.
596+
- primitive_index: Indicates which primitives are contained.
598597
"""
599598
device = get_device(device=device)
600599

@@ -627,8 +626,9 @@ def build_linear_bounding_volume_hierarchies(
627626
codes = morton_codes(coordinates=centroids, epsilon=1e-6, device=device)
628627
sorted_codes, sorted_primitive_indices = torch.sort(codes)
629628

630-
# Analyse similarities between Morton codes and determine the direction to the more similar Morton codes, in the sorted array: -1 = to the left, +1 = to the right.
631-
# The similarity is evaluated by computing leading common prefix lengths for all neighboring pairs of Morton codes.
629+
# Analyze similarities between Morton codes and determine the direction to the more similar Morton codes,
630+
# in the sorted array: -1 = to the left, +1 = to the right. The similarity is evaluated by computing leading
631+
# common prefix lengths for all neighboring pairs of Morton codes.
632632
if number_of_blocking_primitives > 1:
633633
lcp_right = longest_common_prefix(
634634
codes=sorted_codes,
@@ -654,10 +654,9 @@ def build_linear_bounding_volume_hierarchies(
654654
-torch.ones(number_of_blocking_primitives, dtype=torch.int64, device=device),
655655
)
656656

657-
# Find threshold (delta_min) for node expansion by determining how similar the next Morton code in the chosen direction is.
658-
# Find the range of blocking primitives that share a common prefix larger than delta_min.
659657
# Find the contiguous range of Morton codes that belong together.
660-
# In the exponential search (the step size doubles in each iteration), find the farthest index j along direction d[i] where LCP > delta_min[i].
658+
# Find threshold (delta_min) for node expansion by determining how different the next Morton code in the direction of the less similar neighbor is.
659+
# Find the range of blocking primitives that share a common prefix larger than delta_min.
661660
neighbor_indices = blocker_ids - direction_to_similar_codes
662661
mask_out_of_bounds = (neighbor_indices >= 0) & (
663662
neighbor_indices < number_of_blocking_primitives
@@ -673,16 +672,16 @@ def build_linear_bounding_volume_hierarchies(
673672
mask_out_of_bounds, delta_min, torch.full_like(delta_min, -1, device=device)
674673
)
675674

676-
max = (
675+
# In the exponential search (the step size doubles in each iteration), find the farthest index j along direction d[i] where LCP > delta_min[i].
676+
max_index = (
677677
math.ceil(math.log2(number_of_blocking_primitives))
678678
if number_of_blocking_primitives > 1
679679
else 1
680680
)
681681
farthest_expansion = torch.zeros(
682682
number_of_blocking_primitives, dtype=torch.int64, device=device
683683
)
684-
685-
for k in range(0, max + 1):
684+
for k in range(0, max_index + 1):
686685
step = 1 << k
687686
candidate_indices = blocker_ids + direction_to_similar_codes * (
688687
farthest_expansion + step

artist/core/heliostat_ray_tracer.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,14 @@ def __init__(
318318
)
319319
blocking_heliostat_surfaces_active_list = []
320320
for group in self.scenario.heliostat_field.heliostat_groups:
321-
if group.active_heliostats_mask.sum() <= 0:
321+
if group.active_heliostats_mask.sum() == 0:
322322
blocking_heliostat_surfaces_active_list.append(
323323
group.surface_points + group.positions.unsqueeze(1)
324324
)
325+
log.warning(
326+
"Not all heliostat groups have been aligned yet."
327+
"Use unaligned, i.e., horizontal heliostats as approximated blocking planes in raytracing."
328+
)
325329
if group.active_heliostats_mask.sum() > 0:
326330
heliostat_mask = torch.cumsum(group.active_heliostats_mask, dim=0)
327331
start_indices = heliostat_mask - group.active_heliostats_mask
@@ -423,6 +427,7 @@ def trace_rays(
423427
)
424428

425429
if self.blocking_active:
430+
# Compute the heliostat blocking primitives.
426431
(
427432
blocking_primitives_corners,
428433
blocking_primitives_spans,
@@ -485,6 +490,7 @@ def trace_rays(
485490
number_of_heliostats, device=device
486491
).repeat_interleave(number_of_rays * number_of_points)
487492

493+
# Filter out the blocking primitives that are relevant for blocking.
488494
filtered_blocking_primitive_indices = (
489495
blocking.lbvh_filter_blocking_planes(
490496
points_at_ray_origins=points_at_ray_origins,
@@ -497,7 +503,7 @@ def trace_rays(
497503
device=device,
498504
)
499505
)
500-
506+
# Create the blocked ray mask based on the relevant blocking primitive indices.
501507
if filtered_blocking_primitive_indices.numel() > 0:
502508
blocked = blocking.soft_ray_blocking_mask(
503509
ray_origins=self.heliostat_group.active_surface_points[
Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
"""A logger for the kinematic reconstructor."""
1919

2020

21-
class KinematicReconstructor:
21+
class KinematicsReconstructor:
2222
"""
23-
An optimizer used to reconstruct real-world kinematic deviation parameters.
23+
An optimizer used to reconstruct real-world kinematics deviation parameters.
2424
25-
The kinematic reconstructor learns kinematic parameters. These parameters are
26-
specific to a certain kinematic type and can for example include the four
27-
kinematic rotation deviation parameters as well as the two initial actuator parameters
28-
for each actuator of a rigid body kinematic.
25+
The kinematics reconstructor learns kinematics parameters. These parameters are
26+
specific to a certain kinematics type and can for example include the four
27+
kinematics rotation deviation parameters as well as the two initial actuator parameters
28+
for each actuator of a rigid body kinematics.
2929
3030
Attributes
3131
----------
@@ -48,8 +48,8 @@ class KinematicReconstructor:
4848
4949
Methods
5050
-------
51-
reconstruct_kinematic()
52-
Reconstruct the kinematic parameters.
51+
reconstruct_kinematics()
52+
Reconstruct the kinematics parameters.
5353
"""
5454

5555
def __init__(
@@ -62,10 +62,10 @@ def __init__(
6262
| list[tuple[str, list[pathlib.Path], list[pathlib.Path]]],
6363
],
6464
optimization_configuration: dict[str, Any],
65-
reconstruction_method: str = config_dictionary.kinematic_reconstruction_raytracing,
65+
reconstruction_method: str = config_dictionary.kinematics_reconstruction_raytracing,
6666
) -> None:
6767
"""
68-
Initialize the kinematic optimizer.
68+
Initialize the kinematics optimizer.
6969
7070
Parameters
7171
----------
@@ -82,7 +82,7 @@ def __init__(
8282
"""
8383
rank = ddp_setup[config_dictionary.rank]
8484
if rank == 0:
85-
log.info("Create a kinematic reconstructor.")
85+
log.info("Create a kinematics reconstructor.")
8686

8787
self.ddp_setup = ddp_setup
8888
self.scenario = scenario
@@ -92,15 +92,15 @@ def __init__(
9292

9393
if (
9494
reconstruction_method
95-
== config_dictionary.kinematic_reconstruction_raytracing
95+
== config_dictionary.kinematics_reconstruction_raytracing
9696
):
9797
self.reconstruction_method = reconstruction_method
9898
else:
9999
raise ValueError(
100-
f"ARTIST currently only supports the {config_dictionary.kinematic_reconstruction_raytracing} reconstruction method. The reconstruction method {reconstruction_method} is not recognized. Please select another reconstruction method and try again!"
100+
f"ARTIST currently only supports the {config_dictionary.kinematics_reconstruction_raytracing} reconstruction method. The reconstruction method {reconstruction_method} is not recognized. Please select another reconstruction method and try again!"
101101
)
102102

103-
def reconstruct_kinematic(
103+
def reconstruct_kinematics(
104104
self,
105105
loss_definition: Loss,
106106
device: torch.device | None = None,
@@ -120,31 +120,31 @@ def reconstruct_kinematic(
120120
Returns
121121
-------
122122
torch.Tensor
123-
The final loss of the kinematic reconstruction for each heliostat in each group.
123+
The final loss of the kinematics reconstruction for each heliostat in each group.
124124
Tensor of shape [total_number_of_heliostats_in_scenario].
125125
"""
126126
device = get_device(device=device)
127127

128128
if (
129129
self.reconstruction_method
130-
== config_dictionary.kinematic_reconstruction_raytracing
130+
== config_dictionary.kinematics_reconstruction_raytracing
131131
):
132-
loss = self._reconstruct_kinematic_parameters_with_raytracing(
132+
loss = self._reconstruct_kinematics_parameters_with_raytracing(
133133
loss_definition=loss_definition,
134134
device=device,
135135
)
136136

137137
return loss
138138

139-
def _reconstruct_kinematic_parameters_with_raytracing(
139+
def _reconstruct_kinematics_parameters_with_raytracing(
140140
self,
141141
loss_definition: Loss,
142142
device: torch.device | None = None,
143143
) -> torch.Tensor:
144144
"""
145-
Reconstruct the kinematic parameters using ray tracing.
145+
Reconstruct the kinematics parameters using ray tracing.
146146
147-
This reconstruction method optimizes the kinematic parameters by extracting the focal points
147+
This reconstruction method optimizes the kinematics parameters by extracting the focal points
148148
of calibration images and using heliostat-tracing.
149149
150150
Parameters
@@ -159,15 +159,15 @@ def _reconstruct_kinematic_parameters_with_raytracing(
159159
Returns
160160
-------
161161
torch.Tensor
162-
The final loss of the kinematic reconstruction for each heliostat in each group.
162+
The final loss of the kinematics reconstruction for each heliostat in each group.
163163
Tensor of shape [total_number_of_heliostats_in_scenario].
164164
"""
165165
device = get_device(device=device)
166166

167167
rank = self.ddp_setup[config_dictionary.rank]
168168

169169
if rank == 0:
170-
log.info("Beginning kinematic reconstruction with ray tracing.")
170+
log.info("Beginning kinematics reconstruction with ray tracing.")
171171

172172
final_loss_per_heliostat = torch.full(
173173
(self.scenario.heliostat_field.number_of_heliostats_per_group.sum(),),
@@ -214,8 +214,8 @@ def _reconstruct_kinematic_parameters_with_raytracing(
214214
# Create the optimizer.
215215
optimizer = torch.optim.Adam(
216216
[
217-
heliostat_group.kinematic.rotation_deviation_parameters.requires_grad_(),
218-
heliostat_group.kinematic.actuators.optimizable_parameters.requires_grad_(),
217+
heliostat_group.kinematics.rotation_deviation_parameters.requires_grad_(),
218+
heliostat_group.kinematics.actuators.optimizable_parameters.requires_grad_(),
219219
],
220220
lr=float(
221221
self.optimizer_dict[config_dictionary.initial_learning_rate]
@@ -342,12 +342,12 @@ def _reconstruct_kinematic_parameters_with_raytracing(
342342
]
343343

344344
torch.nn.utils.clip_grad_norm_(
345-
[heliostat_group.kinematic.rotation_deviation_parameters],
345+
[heliostat_group.kinematics.rotation_deviation_parameters],
346346
max_norm=1.0,
347347
)
348348

349349
torch.nn.utils.clip_grad_norm_(
350-
[heliostat_group.kinematic.actuators.optimizable_parameters],
350+
[heliostat_group.kinematics.actuators.optimizable_parameters],
351351
max_norm=1.0,
352352
)
353353

@@ -391,7 +391,7 @@ def _reconstruct_kinematic_parameters_with_raytracing(
391391

392392
final_loss_per_heliostat[final_indices] = loss_per_heliostat
393393

394-
log.info(f"Rank: {rank}, Kinematic reconstructed.")
394+
log.info(f"Rank: {rank}, Kinematics reconstructed.")
395395

396396
if self.ddp_setup[config_dictionary.is_distributed]:
397397
for index, heliostat_group in enumerate(
@@ -401,17 +401,17 @@ def _reconstruct_kinematic_parameters_with_raytracing(
401401
index
402402
]
403403
torch.distributed.broadcast(
404-
heliostat_group.kinematic.rotation_deviation_parameters,
404+
heliostat_group.kinematics.rotation_deviation_parameters,
405405
src=source[index_mapping.first_rank_from_group],
406406
)
407407
torch.distributed.broadcast(
408-
heliostat_group.kinematic.actuators.optimizable_parameters,
408+
heliostat_group.kinematics.actuators.optimizable_parameters,
409409
src=source[index_mapping.first_rank_from_group],
410410
)
411411
torch.distributed.all_reduce(
412412
final_loss_per_heliostat, op=torch.distributed.ReduceOp.MIN
413413
)
414414

415-
log.info(f"Rank: {rank}, synchronized after kinematic reconstruction.")
415+
log.info(f"Rank: {rank}, synchronized after kinematics reconstruction.")
416416

417417
return final_loss_per_heliostat

0 commit comments

Comments
 (0)