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;
54 struct ScanSetupSettings
57 Vector<2, Angle<sint04>> angle_of_separation = Vector<2, Angle<sint04>>(Angle<sint04>(
DEGREES, 2.0));
58 Bounds<2, Angle<sint04>> scan_bounds = Constant<Bounds<2, Angle<sint04>>>::Max;
59 uint01 scan_mesh_reach = 3;
60 bool is_continuous =
false;
61 bool generate_mesh =
true;
62 bool records_color =
false;
63 bool records_distance =
true;
64 bool records_polar =
true;
65 bool records_intensity =
true;
66 bool records_timestamp =
true;
67 bool is_child_of_station =
true;
68 RasterInfo raster_info;
73 enum ScanTargetBitFlags
85 template<
class t_type>
86 struct PolarScanRecord
88 Vertex<3, t_type> position = Vector<3, t_type>(0.0);
89 Vector<4, t_type> color = Vector<4, t_type>(0.0);
90 Vector<2, Angle<sint04>> coord;
92 t_type intensity = 0.0;
93 t_type total_weight = 0.0;
94 t_type max_distance = Constant<t_type>::Min;
95 t_type min_distance = Constant<t_type>::Max;
96 t_type scan_time = 0.0;
97 t_type scan_sweep = 0.0;
101 PolarScanRecord(Angle<sint04> roll, Angle<sint04> pitch)
104 PolarScanRecord(
const Vector<2, Angle<sint04>>& roll_pitch)
107 void updateWeight(t_type weight)
109 t_type weight_conv = weight / total_weight;
110 position *= weight_conv;
112 intensity *= weight_conv;
113 scan_time *= weight_conv;
114 color *= weight_conv;
115 total_weight = weight;
117 template<
class t_other_type>
118 void updateAverage(
const PolarScanRecord<t_other_type>& record)
122 position += (record.total_weight * record.position).
template as<3, t_type>();
123 distance += cast<t_type>(record.total_weight * record.distance);
124 intensity += cast<t_type>(record.total_weight * record.intensity);
125 scan_time += cast<t_type>(record.total_weight * record.scan_time);
126 scan_sweep += cast<t_type>(record.total_weight * record.scan_sweep);
127 color += (record.total_weight * record.color).
template as<4, t_type>();
128 total_weight += cast<t_type>(record.total_weight);
132 max_distance =
getMax(max_distance, cast<t_type>(record.distance));
133 min_distance =
getMin(min_distance, cast<t_type>(record.distance));
141 position = Vector<3, t_type>(0.0);
143 max_distance = Constant<t_type>::Min;
144 min_distance = Constant<t_type>::Max;
148 void autoCalcPositionH(Angle<sint04> roll = Angle<sint04>(DEGREES, 0.0f))
150 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<sint04>>(roll, coord[PITCH], coord[ROLL]));
151 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
153 void autoCalcPositionR(Angle<sint04> yaw = Angle<sint04>(DEGREES, 0.0f))
155 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<sint04>>(coord, yaw));
156 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
158 constexpr fltp08 operator[](uint01 dim)
const
160 return position[dim];
165 struct ObjectInfo<PolarScanRecord<
fltp04>, false, false>
167 static const uint01 Dimensions = 0;
168 static const bool Vector =
false;
169 static const bool Buffer =
false;
170 static const bool Primitive =
true;
171 static const bool Pointer =
false;
172 static const bool Unsigned =
false;
173 static const bool Float =
false;
174 static const bool Integer =
false;
175 static const bool Number =
false;
176 static const bool Enum =
false;
177 static const bool String =
false;
178 static const bool Color =
false;
179 static const bool Boolean =
false;
180 static constexpr ObjectInfo<PolarScanRecord<fltp04>,
false,
false> VectorSub() {
return ObjectInfo<PolarScanRecord<fltp04>,
false,
false>(); }
183 class MaterialRasterBase;
191 struct ScanCalibration
194 fltp08 emitter_offset = 0.0;
196 Angle<fltp08> beam_angle = Angle<fltp08>(0);
197 Angle<fltp08> head_tilt_angle = Angle<fltp08>(0);
198 Angle<fltp08> laser_tilt_angle = Angle<fltp08>(0);
202 explicit Scan(
const Model& model);
203 Scan(
const Model& model,
const ScanSetupSettings& settings);
204 void updateScanModel(
const void* lock);
205 void updateScanProperties(
bool scan_ended =
false);
206 void updateScanModel(
bool scan_ended,
bool force_calculate_mesh,
const void* lock);
207 void cacheChannels();
208 Model scanMesh()
const;
209 Model scanCloud()
const;
210 bool hasCalibrationRing(uint04 index)
const;
211 Scan& createCalibrationRing(uint04 index);
212 Scan& calibrationRing(uint04 index);
213 const Scan& calibrationRing(uint04 index)
const;
214 void reserveRecordSpace(uint04 space);
215 void addToRecordQueue(
const PolarScanRecord<fltp04>& record);
217 void splitScan(
const Vector<3, fltp08>& distance,
const void* lock);
218 void finishMoveScan(
const void* lock_ptr);
219 void addSweep(
const void* lock_ptr);
220 void moveScan(
const Vector<3, fltp08>& distance, fltp08 vertex_epsilon, fltp08 motion_only_max_difference,
bool filter_by_direction,
const void* lock_ptr);
221 void setupMesh(
bool add_new_structure,
const void* lock_ptr);
222 void setScannerOrientation(
const Vector<3, Angle<fltp08>>& orientation);
223 void setDeploymentOrientation(
const Vector<3, Angle<fltp08>>& orientation);
224 void setScannerInfo(
const TranslatedString& scanner_info);
225 TranslatedString scannerInfo()
const;
226 void createImageRaster(
const RasterInfo& info);
227 void addImageToRaster(
const ImageData& data,
const Vector<2, Angle<sint04>>& fov,
const Matrix<fltp08>& camera_matrix);
228 bool scanCalibrated()
const;
229 void removeShadowTriangles(fltp04 cuttoff_ratio);
230 Vector<3, Angle<fltp08>> scannerOrientation()
const;
231 Vector<3, Angle<fltp08>> deploymentOrientation()
const;
232 Angle<fltp08> calculateCalibrationConstant(
bool global_yaw,
const void* lock)
const;
233 void calibrateScan(
bool global_yaw, InterpolationValues value = InterpolationValues::e_linear,
const void* lock =
nullptr);
234 void calibrateScan(Angle<fltp08> angle,
bool global_yaw, InterpolationValues value = InterpolationValues::e_linear,
const void* lock =
nullptr);
235 void decalibrateScan();
236 void ensureModelFormat();
237 void updateOlderAngles();
238 Model pointsLayer()
const;
239 Model meshLayer()
const;
240 Model circleScanLayer()
const;
241 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);
242 void createMeshFromScan(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
243 Bounds<2, Angle<sint04>> scanBounds()
const;
244 Angle<sint04> primaryAngleOfSeparation()
const;
245 Vector<2, Angle<sint04>> anglesOfSeparation()
const;
246 void setAnglesOfSeperation(Vector<2, Angle<sint04>>& angle);
247 void setScanBounds(
const Bounds<2, Angle<sint04>>& bounds);
248 Vector<3, Angle<fltp08>> angleCalibrationOffset()
const;
249 void setCalibration(
const ScanCalibration& calibration,
const void* lock =
nullptr);
250 ScanCalibration getCalibration()
const;
252 static constexpr const char* TypeName() {
return "scan"; }
253 static constexpr const char* CalibrationRingTypeName() {
return "calibration_ring"; }
254 TimeSpan scanDuration()
const;
255 void setScanDuration(
const TimeSpan& span);
256 void setIsDynamic(
bool is_dynamic);
257 void setMotionOnlyReference();
258 bool isScanValid()
const;
259 void setValid(
bool is_valid);
260 Buffer<PolarScanRecord<fltp04>> generatePolarRecords(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
262 void setupScanRecordsFromExisting(
const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0),
const void* lock =
nullptr);
263 void addMeshRasterRecord(
const PolarScanRecord<fltp04>& record, sint04 range);
264 void addMeshRasterRecord(
const ZippedRadialMeshOptions& options, Vector<2, Angle<sint04>> delta,
const PolarScanRecord<fltp04>& record);
265 void blurMeshRecords(sint04 range);
266 void addCloudRecord(
const PolarScanRecord<fltp04>& record);
268 void updateScanColors();
270 [[nodiscard]] TranslatedString createDescription(
bool is_finished);
271 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);
272 static Angle<fltp08> GetBestRotation_2DAffine(
const Buffer<Vertex<3, fltp08>>& v_a,
const Buffer<Vertex<3, fltp08>>& v_b,
const Matrix<fltp08>& mat);
274 mutable Vector<3, Angle<fltp08>> m_scanner_orientation = Constant<Vector<3, Angle<fltp08>>>::Invalid;
275 mutable Vector<3, Angle<fltp08>> m_deployment_orientation = Constant<Vector<3, Angle<fltp08>>>::Invalid;
276 MaterialRasterBase* m_image_raster =
nullptr;
277 Bounds<1, uint04> m_mesh_write_update_bounds = Constant<Bounds<1, uint04>>::Min;
278 Bounds<3, fltp04> m_scan_record_bounds = Constant<Bounds<3, fltp04>>::Min;
279 PolarScanRecord<fltp08> m_total_avg;
280 Buffer<PolarScanRecord<fltp04>> m_cloud_write_queue;
281 Buffer<PolarScanRecord<fltp04>> m_mesh_write_queue;
282 Buffer<uint04> m_mesh_locations;
283 mutable Buffer<Scan, uint04, ObjectAllocator<false>> m_reference_scans;
284 uint04 m_cloud_intensity_channel = Constant<uint04>::Invalid;
285 uint04 m_cloud_roll_channel = Constant<uint04>::Invalid;
286 uint04 m_cloud_pitch_channel = Constant<uint04>::Invalid;
287 uint04 m_cloud_distance_channel = Constant<uint04>::Invalid;
288 uint04 m_scan_time_channel = Constant<uint04>::Invalid;
289 uint04 m_scan_sweep_channel = Constant<uint04>::Invalid;
290 uint04 m_scan_original_channel = Constant<uint04>::Invalid;
291 uint04 m_scan_sweeps = Constant<uint04>::Invalid;
292 uint04 m_mesh_write_offset = 0;
293 Vertex<3, fltp04> m_split_offset = Vertex<3, fltp04>(0.0);
294 Vertex<3, fltp04> m_last_min_mid_max;
295 bool m_is_dynamic_scan =
false;
296 bool m_needs_raster_update =
false;
297 bool m_needs_channel_update =
true;
298 mutable ScanSetupSettings m_settings;
301 static const uint04 s_scan_mesh = 0;
302 static const uint04 s_scan_cloud = 1;
303 static const uint04 s_calibration_circle_start_ring = 2;
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator The only requirement is that t_type have > ...
Definition BaseFunctions.hpp:94
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
Definition BaseValues.hpp:127
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
@ DEGREES
Definition Angle.h:58
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
constexpr t_type distance(const t_vertex &vertex, const LineSegment< t_dims, t_type, t_vertex > &line)
Definition Distance.hpp:171
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
ScanMode
The mode that a scanner will collect data in.
Definition ScanMode.h:8
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
Definition BaseFunctions.hpp:56