33#include <NDEVR/Model.h>
35#include <NDEVR/ScanMode.h>
36#include <NDEVR/MaterialRaster.h>
37#include <NDEVR/Angle.h>
38#include <NDEVR/Vertex.h>
39#include <NDEVR/Buffer.h>
40#include <NDEVR/Bounds.h>
41#include <NDEVR/VectorFunctions.h>
42#include <NDEVR/MatrixFunctions.h>
48 struct ZippedRadialMeshOptions;
52 struct ScanSetupSettings
55 Vector<2, Angle<sint04>> angle_of_separation = Vector<2, Angle<sint04>>(Angle<sint04>(
DEGREES, 2.0));
56 Bounds<2, Angle<sint04>> scan_bounds = Constant<Bounds<2, Angle<sint04>>>::Max;
57 uint01 scan_mesh_reach = 3;
58 bool is_continuous =
false;
59 bool generate_mesh =
true;
60 bool records_color =
false;
61 bool records_distance =
true;
62 bool records_polar =
true;
63 bool records_intensity =
true;
64 bool records_timestamp =
true;
65 bool is_child_of_station =
true;
66 RasterInfo raster_info;
69 enum ScanTargetBitFlags
78 template<
class t_type>
79 struct PolarScanRecord
81 Vertex<3, t_type> position = Vector<3, t_type>(0.0);
82 Vector<4, t_type> color = Vector<4, t_type>(0.0);
83 Vector<2, Angle<sint04>> coord;
85 t_type intensity = 0.0;
86 t_type total_weight = 0.0;
87 t_type max_distance = Constant<t_type>::Min;
88 t_type min_distance = Constant<t_type>::Max;
89 t_type scan_time = 0.0;
90 t_type scan_sweep = 0.0;
94 PolarScanRecord(Angle<sint04> roll, Angle<sint04> pitch)
97 PolarScanRecord(
const Vector<2, Angle<sint04>>& roll_pitch)
100 void updateWeight(t_type weight)
102 t_type weight_conv = weight / total_weight;
103 position *= weight_conv;
105 intensity *= weight_conv;
106 scan_time *= weight_conv;
107 color *= weight_conv;
108 total_weight = weight;
110 template<
class t_other_type>
111 void updateAverage(
const PolarScanRecord<t_other_type>& record)
113 if (!
isNaN(record.position))
115 position += (record.total_weight * record.position).
template as<3, t_type>();
116 distance += cast<t_type>(record.total_weight * record.distance);
117 intensity += cast<t_type>(record.total_weight * record.intensity);
118 scan_time += cast<t_type>(record.total_weight * record.scan_time);
119 scan_sweep += cast<t_type>(record.total_weight * record.scan_sweep);
120 color += (record.total_weight * record.color).
template as<4, t_type>();
121 total_weight += cast<t_type>(record.total_weight);
123 if (!
isNaN(record.distance))
125 max_distance =
getMax(max_distance, cast<t_type>(record.distance));
126 min_distance =
getMin(min_distance, cast<t_type>(record.distance));
134 position = Vector<3, t_type>(0.0);
136 max_distance = Constant<t_type>::Min;
137 min_distance = Constant<t_type>::Max;
141 void autoCalcPositionH(Angle<sint04> roll = Angle<sint04>(DEGREES, 0.0f))
143 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<sint04>>(roll, coord[PITCH], coord[ROLL]));
144 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
146 void autoCalcPositionR(Angle<sint04> yaw = Angle<sint04>(DEGREES, 0.0f))
148 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<sint04>>(coord, yaw));
149 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
151 constexpr fltp08 operator[](uint01 dim)
const
153 return position[dim];
158 struct ObjectInfo<PolarScanRecord<
fltp04>, false, false>
160 static const uint01 Dimensions = 0;
161 static const bool Vector =
false;
162 static const bool Buffer =
false;
163 static const bool Primitive =
true;
164 static const bool Pointer =
false;
165 static const bool Unsigned =
false;
166 static const bool Float =
false;
167 static const bool Integer =
false;
168 static const bool Number =
false;
169 static const bool Enum =
false;
170 static const bool String =
false;
171 static const bool Color =
false;
172 static const bool Boolean =
false;
173 static constexpr ObjectInfo<PolarScanRecord<fltp04>,
false,
false> VectorSub() {
return ObjectInfo<PolarScanRecord<fltp04>,
false,
false>(); }
177 class MaterialRasterBase;
182 struct ScanCalibration
185 fltp08 emitter_offset = 0.0;
187 Angle<fltp08> beam_angle = Angle<fltp08>(0);
188 Angle<fltp08> head_tilt_angle = Angle<fltp08>(0);
189 Angle<fltp08> laser_tilt_angle = Angle<fltp08>(0);
193 explicit Scan(
const Model& model);
194 Scan(
const Model& model,
const ScanSetupSettings& settings);
195 void updateScanModel(
const void* lock);
196 void updateScanProperties(
bool scan_ended =
false);
197 void updateScanModel(
bool scan_ended,
bool force_calculate_mesh,
const void* lock);
198 void cacheChannels();
199 Model scanMesh()
const;
200 Model scanCloud()
const;
201 bool hasCalibrationRing(uint04 index)
const;
202 Scan& createCalibrationRing(uint04 index);
203 Scan& calibrationRing(uint04 index);
204 const Scan& calibrationRing(uint04 index)
const;
205 void reserveRecordSpace(uint04 space);
206 void addToRecordQueue(
const PolarScanRecord<fltp04>& record);
208 void splitScan(
const Vector<3, fltp08>& distance,
const void* lock);
209 void finishMoveScan(
const void* lock_ptr);
210 void addSweep(
const void* lock_ptr);
211 void moveScan(
const Vector<3, fltp08>& distance, fltp08 vertex_epsilon, fltp08 motion_only_max_difference,
bool filter_by_direction,
const void* lock_ptr);
212 void setupMesh(
bool add_new_structure,
const void* lock_ptr);
213 void setScannerOrientation(
const Vector<3, Angle<fltp08>>& orientation);
214 void setDeploymentOrientation(
const Vector<3, Angle<fltp08>>& orientation);
215 void setScannerInfo(
const TranslatedString& scanner_info);
216 TranslatedString scannerInfo()
const;
217 void createImageRaster(
const RasterInfo& info);
218 void addImageToRaster(
const ImageData& data,
const Vector<2, Angle<sint04>>& fov,
const Matrix<fltp08>& camera_matrix);
219 bool scanCalibrated()
const;
220 void removeShadowTriangles(fltp04 cuttoff_ratio);
221 Vector<3, Angle<fltp08>> scannerOrientation()
const;
222 Vector<3, Angle<fltp08>> deploymentOrientation()
const;
223 Angle<fltp08> calculateCalibrationConstant(
bool global_yaw,
const void* lock)
const;
224 void calibrateScan(
bool global_yaw, InterpolationValues value = InterpolationValues::e_linear,
const void* lock =
nullptr);
225 void calibrateScan(Angle<fltp08> angle,
bool global_yaw, InterpolationValues value = InterpolationValues::e_linear,
const void* lock =
nullptr);
226 void decalibrateScan();
227 void ensureModelFormat();
228 void updateOlderAngles();
229 Model pointsLayer()
const;
230 Model meshLayer()
const;
231 Model circleScanLayer()
const;
232 void addRecords(
const Buffer<Vertex<3, fltp08>>& positions,
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
bool add_to_cloud =
true,
bool add_to_mesh =
true);
233 void createMeshFromScan(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
234 Bounds<2, Angle<sint04>> scanBounds()
const;
235 Angle<sint04> primaryAngleOfSeparation()
const;
236 Vector<2, Angle<sint04>> anglesOfSeparation()
const;
237 void setAnglesOfSeperation(Vector<2, Angle<sint04>>& angle);
238 void setScanBounds(
const Bounds<2, Angle<sint04>>& bounds);
239 Vector<3, Angle<fltp08>> angleCalibrationOffset()
const;
240 void setCalibration(
const ScanCalibration& calibration,
const void* lock =
nullptr);
241 ScanCalibration getCalibration()
const;
243 static constexpr const char* TypeName() {
return "scan"; }
244 static constexpr const char* CalibrationRingTypeName() {
return "calibration_ring"; }
245 TimeSpan scanDuration()
const;
246 void setScanDuration(
const TimeSpan& span);
247 void setIsDynamic(
bool is_dynamic);
248 void setMotionOnlyReference();
249 bool isScanValid()
const;
250 void setValid(
bool is_valid);
251 Buffer<PolarScanRecord<fltp04>> generatePolarRecords(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
253 void setupScanRecordsFromExisting(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
254 void addMeshRasterRecord(
const PolarScanRecord<fltp04>& record, sint04 range);
255 void addMeshRasterRecord(
const ZippedRadialMeshOptions& options, Vector<2, Angle<sint04>> delta,
const PolarScanRecord<fltp04>& record);
256 void blurMeshRecords(sint04 range);
257 void addCloudRecord(
const PolarScanRecord<fltp04>& record);
259 void updateScanColors();
261 [[nodiscard]] TranslatedString createDescription(
bool is_finished);
262 static Angle<fltp08> GetBestRotation(Angle<fltp08> increment,
const Buffer<Vertex<3, fltp08>>& v_a,
const Buffer<Vertex<3, fltp08>>& v_b,
const Matrix<fltp08>& mat,
const Vector<3, fltp08>& up);
263 static Angle<fltp08> GetBestRotation_2DAffine(
const Buffer<Vertex<3, fltp08>>& v_a,
const Buffer<Vertex<3, fltp08>>& v_b,
const Matrix<fltp08>& mat);
265 mutable Vector<3, Angle<fltp08>> m_scanner_orientation = Constant<Vector<3, Angle<fltp08>>>::NaN;
266 mutable Vector<3, Angle<fltp08>> m_deployment_orientation = Constant<Vector<3, Angle<fltp08>>>::NaN;
267 MaterialRasterBase* m_image_raster =
nullptr;
268 Bounds<1, uint04> m_mesh_write_update_bounds = Constant<Bounds<1, uint04>>::Min;
269 Bounds<3, fltp04> m_scan_record_bounds = Constant<Bounds<3, fltp04>>::Min;
270 PolarScanRecord<fltp08> m_total_avg;
271 Buffer<PolarScanRecord<fltp04>> m_cloud_write_queue;
272 Buffer<PolarScanRecord<fltp04>> m_mesh_write_queue;
273 Buffer<uint04> m_mesh_locations;
274 mutable Buffer<Scan, uint04, ObjectAllocator<false>> m_reference_scans;
275 uint04 m_cloud_intensity_channel = Constant<uint04>::NaN;
276 uint04 m_cloud_roll_channel = Constant<uint04>::NaN;
277 uint04 m_cloud_pitch_channel = Constant<uint04>::NaN;
278 uint04 m_cloud_distance_channel = Constant<uint04>::NaN;
279 uint04 m_scan_time_channel = Constant<uint04>::NaN;
280 uint04 m_scan_sweep_channel = Constant<uint04>::NaN;
281 uint04 m_scan_original_channel = Constant<uint04>::NaN;
282 uint04 m_scan_sweeps = Constant<uint04>::NaN;
283 uint04 m_mesh_write_offset = 0;
284 Vertex<3, fltp04> m_split_offset = Vertex<3, fltp04>(0.0);
285 Vertex<3, fltp04> m_last_min_mid_max;
286 bool m_is_dynamic_scan =
false;
287 bool m_needs_raster_update =
false;
288 bool m_needs_channel_update =
true;
289 mutable ScanSetupSettings m_settings;
292 static const uint04 s_scan_mesh = 0;
293 static const uint04 s_scan_cloud = 1;
294 static const uint04 s_calibration_circle_start_ring = 2;
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator.
Definition BaseFunctions.hpp:116
float fltp04
Defines an alias representing a 4 byte floating-point number.
Definition BaseValues.hpp:157
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:98
@ DEGREES
Definition Angle.h:66
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr t_type distance(const t_vertex &vertex, const LineSegment< t_dims, t_type, t_vertex > &line)
Definition Distance.hpp:250
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:181
ScanMode
Definition ScanMode.h:5
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator.
Definition BaseFunctions.hpp:67