NDEVR
API Documentation
Scan.h
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Design
28File: Scan
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Model.h>
34#if NDEVR_SCAN
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>
43
44namespace NDEVR
45{
46 class Scan;
47 typedef AlocatingAlignedBuffer<Scan, 64> ScanBuffer;
48 struct RasterInfo;
49 class ImageData;
51 NDEVR_DESIGN_T_API template class NDEVR_DESIGN_API StringStream<ScanMode>;
52
56 struct ScanSetupSettings
57 {
61 uint01 scan_mesh_reach = 3;
62 bool is_continuous = false;
63 bool generate_mesh = true;
64 bool records_color = false;
65 bool records_distance = true;
66 bool records_polar = true;
67 bool records_intensity = true;
68 bool records_timestamp = true;
69 bool is_child_of_station = true;
70 RasterInfo raster_info;
71 };
75 enum ScanTargetBitFlags
76 {
77 e_cloud
78 , e_mesh
79 , e_calibration_a
80 , e_calibration_b
81 , e_color_raster
82 };
83
89 template<class t_type>
90 struct PolarScanRecord
91 {
92 Vertex<3, t_type> position = Vector<3, t_type>(0.0);
93 Vector<4, t_type> color = Vector<4, t_type>(0.0);
94 Vector<2, Angle<t_type>> coord;
95 Vector<2, Angle<t_type>> raw_coord;
96 t_type distance = 0.0;
97 t_type intensity = 0.0;
98 t_type total_weight = 0.0;
99 t_type max_distance = Constant<t_type>::Min;
100 t_type min_distance = Constant<t_type>::Max;
101 t_type scan_time = 0.0;
102 t_type scan_sweep = 0.0;
103 BitFlag target_bit_flags = BitFlag(0);
104
106 PolarScanRecord()
107 {}
108
112 PolarScanRecord(Angle<t_type> roll, Angle<t_type> pitch)
113 : coord(roll, pitch)
114 {}
115
118 PolarScanRecord(const Vector<2, Angle<t_type>>& roll_pitch)
119 : coord(roll_pitch)
120 {}
121
124 void updateWeight(t_type weight)
125 {
126 t_type weight_conv = weight / total_weight;
127 position *= weight_conv;
128 distance *= weight_conv;
129 intensity *= weight_conv;
130 scan_time *= weight_conv;
131 color *= weight_conv;
132 total_weight = weight;
133 }
134
138 template<class t_other_type>
139 void updateAverage(const PolarScanRecord<t_other_type>& record)
140 {
141 if (IsValid(record.position))
142 {
143 position += (record.total_weight * record.position).template as<3, t_type>();
144 distance += cast<t_type>(record.total_weight * record.distance);
145 intensity += cast<t_type>(record.total_weight * record.intensity);
146 scan_time += cast<t_type>(record.total_weight * record.scan_time);
147 scan_sweep += cast<t_type>(record.total_weight * record.scan_sweep);
148 color += (record.total_weight * record.color).template as<4, t_type>();
149 total_weight += cast<t_type>(record.total_weight);
150 }
151 if (IsValid(record.distance))
152 {
153 max_distance = getMax(max_distance, cast<t_type>(record.distance));
154 min_distance = getMin(min_distance, cast<t_type>(record.distance));
155 }
156 }
157
159 void clearAverage()
160 {
161 color = 0.0;
162 distance = 0.0;
163 intensity = 0.0;
164 position = Vector<3, t_type>(0.0);
165 total_weight = 0.0;
166 max_distance = Constant<t_type>::Min;
167 min_distance = Constant<t_type>::Max;
168 scan_time = 0.0;
169 scan_sweep = 0.0;
170 }
171
175 void autoCalcPositionH(Angle<t_type> roll = Angle<t_type>(DEGREES, 0.0f))
176 {
177 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<t_type>>(roll, coord[PITCH], coord[ROLL]));
178 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
179 }
180
183 void autoCalcPositionR(Angle<t_type> yaw = Angle<t_type>(DEGREES, 0.0f))
184 {
185 Matrix<fltp08> mat = Matrix<fltp08>::RotationMatrix(Vector<3, Angle<t_type>>(coord, yaw));
186 position = (mat * Vertex<3, fltp08>(0.0, 0.0, distance)).as<3, fltp04>();
187 }
188
192 constexpr fltp08 operator[](uint01 dim) const
193 {
194 return position[dim];
195 }
196 };
197
201 template<>
202 struct ObjectInfo<PolarScanRecord<fltp04>, false, false>
203 {
204 static const uint01 Dimensions = 0;
205 static const bool Vector = false;
206 static const bool Buffer = false;
207 static const bool Primitive = true;
208 static const bool Pointer = false;
209 static const bool Unsigned = false;
210 static const bool Float = false;
211 static const bool Integer = false;
212 static const bool Number = false;
213 static const bool Enum = false;
214 static const bool String = false;
215 static const bool Color = false;
216 static const bool Boolean = false;
217
220 static constexpr ObjectInfo<PolarScanRecord<fltp04>, false, false> VectorSub() { return ObjectInfo<PolarScanRecord<fltp04>, false, false>(); }
221 };
222
223 class MaterialRasterBase;
233 class NDEVR_DESIGN_API Scan : public Model
234 {
235 public:
236
238 struct ScanCalibration
239 {
240 fltp08 head_offset = 0.0;
241 fltp08 emitter_offset = -0.1335;
242 fltp08 lens_offset = 0.0;
243 Angle<fltp08> beam_angle = Angle<fltp08>(0);
244 Angle<fltp08> head_tilt_angle = Angle<fltp08>(0);
245 Angle<fltp08> laser_tilt_angle = Angle<fltp08>(0);
246 };
247 public:
249 Scan();//Invalid
250
253 explicit Scan(const Model& model);
254
258 Scan(const Model& model, const ScanSetupSettings& settings);
259
263 bool needsMeshUpdate(const void* lock);
264
267 void clearNeedsMeshUpdate(const void* lock);
268
271 void updateScanProperties(bool scan_ended = false);
272
277 void updateScanModel(bool scan_ended, bool force_calculate_mesh, const void* lock);
278
280 void cacheChannels();
281
284 Model scanMesh() const;
285
288 Model scanCloud() const;
289
293 bool hasCalibrationRing(uint04 index) const;
294
298 Scan& createCalibrationRing(uint04 index);
299
303 Scan& calibrationRing(uint04 index);
304
308 const Scan& calibrationRing(uint04 index) const;
309
312 void reserveRecordSpace(uint04 space);
313
316 void addToRecordQueue(const PolarScanRecord<fltp04>& record);
317
321 void splitScan(const Vector<3, fltp08>& distance, const void* lock);
322
325 void finishMoveScan(const void* lock_ptr);
326
329 void addSweep(const void* lock_ptr = nullptr);
330
337 void moveScan(const Vector<3, fltp08>& distance, fltp08 vertex_epsilon, fltp08 motion_only_max_difference, bool filter_by_direction, const void* lock_ptr);
338
342 void setupMesh(bool add_new_structure, const void* lock_ptr);
343
346 void setScannerOrientation(const Vector<3, Angle<fltp08>>& orientation);
347
350 void setDeploymentOrientation(const Vector<3, Angle<fltp08>>& orientation);
351
354 void setScannerInfo(const TranslatedString& scanner_info);
355
358 TranslatedString scannerInfo() const;
359
362 void createImageRaster(const RasterInfo& info);
363
368 void addImageToRaster(const ImageData& data, const Vector<2, Angle<sint04>>& fov, const Matrix<fltp08>& camera_matrix);
369
372 bool scanCalibrated() const;
373
376 void removeShadowTriangles(fltp04 cuttoff_ratio);
377
380 Vector<3, Angle<fltp08>> scannerOrientation() const;
381
384 Vector<3, Angle<fltp08>> deploymentOrientation() const;
385
390 Angle<fltp08> calculateCalibrationConstant(bool global_yaw, const void* lock) const;
391
396 void calibrateScan(bool global_yaw, InterpolationValues value = InterpolationValues::e_linear, const void* lock = nullptr);
397
403 void calibrateScan(Angle<fltp08> angle, bool global_yaw, InterpolationValues value = InterpolationValues::e_linear, const void* lock = nullptr);
404
406 void decalibrateScan();
407
409 void ensureModelFormat();//For older scans
410
412 void updateOlderAngles();//Need to convert older models degrees to internal units
413
416 Model pointsLayer() const;
417
420 Model meshLayer() const;
421
424 Model circleScanLayer() const;
425
431 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);
432
436 void createMeshFromScan(const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0), const void* lock = nullptr);
437
440 Bounds<2, Angle<fltp08>> scanBounds() const;
441
444 Angle<fltp08> primaryAngleOfSeparation() const;
445
448 Vector<2, Angle<fltp08>> anglesOfSeparation() const;
449
452 void setAnglesOfSeperation(Vector<2, Angle<fltp08>>& angle);
453
456 void setScanBounds(const Bounds<2, Angle<fltp08>>& bounds);
457
460 Vector<3, Angle<fltp08>> angleCalibrationOffset() const;
461
465 void setCalibration(const ScanCalibration& calibration, const void* lock = nullptr);
466
469 ScanCalibration getCalibration() const;
470
473 ScanMode scanMode() const;
474
477 static constexpr StringView TypeName() { return "scan"; }
478
481 static constexpr StringView CalibrationRingTypeName() { return "calibration_ring"; }
482
485 TimeSpan scanDuration() const;
486
489 void setScanDuration(const TimeSpan& span);
490
493 void setIsDynamic(bool is_dynamic);
494
496 void setMotionOnlyReference();
497
500 bool isScanValid() const;
501
504 void setValid(bool is_valid);
505
510 Buffer<PolarScanRecord<fltp04>> generatePolarRecords(const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0), const void* lock = nullptr);
511 protected:
515 void setupScanRecordsFromExisting(const Vertex<3, fltp08>& scan_center = Vertex<3, fltp08>(0.0), const void* lock = nullptr);
516
520 void addMeshRasterRecord(const PolarScanRecord<fltp04>& record, sint04 range);
521
526 void addMeshRasterRecord(const ZippedRadialMeshOptions& options, Vector<2, Angle<fltp08>> delta, const PolarScanRecord<fltp04>& record);
527
530 void blurMeshRecords(sint04 range);
531
534 void addCloudRecord(const PolarScanRecord<fltp04>& record);
535
537 void init();
538
540 void updateScanColors();
541
543 void initMaterial();
544
548 [[nodiscard]] TranslatedString createDescription(bool is_finished);
549
558 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, InfoPipe* pipe = nullptr);
559
565 static Angle<fltp08> GetBestRotation_2DAffine(const Buffer<Vertex<3, fltp08>>& v_a, const Buffer<Vertex<3, fltp08>>& v_b, const Matrix<fltp08>& mat);
566 protected:
567 mutable Vector<3, Angle<fltp08>> m_scanner_orientation = Constant<Vector<3, Angle<fltp08>>>::Invalid;
568 mutable Vector<3, Angle<fltp08>> m_deployment_orientation = Constant<Vector<3, Angle<fltp08>>>::Invalid;
569 MaterialRasterBase* m_image_raster = nullptr;
570 Bounds<1, uint04> m_mesh_write_update_bounds = Constant<Bounds<1, uint04>>::Min;
571 Bounds<3, fltp04> m_scan_record_bounds = Constant<Bounds<3, fltp04>>::Min;
572 PolarScanRecord<fltp08> m_total_avg;
573 Buffer<PolarScanRecord<fltp04>> m_cloud_write_queue;
574 Buffer<PolarScanRecord<fltp04>> m_mesh_write_queue;
575 Buffer<uint04> m_mesh_locations;
576 mutable ScanBuffer m_reference_scans;
577 uint04 m_cloud_intensity_channel = Constant<uint04>::Invalid;
578 uint04 m_cloud_roll_channel = Constant<uint04>::Invalid;
579 uint04 m_cloud_pitch_channel = Constant<uint04>::Invalid;
580 uint04 m_cloud_distance_channel = Constant<uint04>::Invalid;
581 uint04 m_scan_time_channel = Constant<uint04>::Invalid;
582 uint04 m_scan_sweep_channel = Constant<uint04>::Invalid;
583 uint04 m_scan_original_channel = Constant<uint04>::Invalid;
584 uint04 m_scan_sweeps = Constant<uint04>::Invalid;
585 uint04 m_mesh_write_offset = 0;
586 Vertex<3, fltp04> m_split_offset = Vertex<3, fltp04>(0.0);
587 Vertex<3, fltp04> m_last_min_mid_max;
588 bool m_is_dynamic_scan = false;
589 bool m_needs_raster_update = false;
590 bool m_needs_channel_update = true;
591 mutable ScanSetupSettings m_settings;
592
593 protected:
594 static const uint04 s_scan_mesh = 0;
595 static const uint04 s_scan_cloud = 1;
596 static const uint04 s_calibration_circle_start_ring = 2;
597 };
598
599}
600#endif
Stores an angle in an optimized internal format with support for efficient trigonometric operations.
Definition Angle.h:83
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:54
A container for Images managed by the ImageFactory.
Base class for painting pixels at a time into a 2D texture.
A core class that represents a node on model hierarchy.
Definition Model.h:292
Logic for reading or writing to a string or a user friendly, TranslatedString.
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
The primary namespace for the NDEVR SDK.
@ BitFlag
Per-vertex bit flags (selected, hidden, etc.).
@ Color
Per-vertex RGBA color.
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...
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
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 > ...
ScanMode
The mode that a scanner will collect data in.
Definition ScanMode.h:8
@ e_undefined
Scan mode has not been specified.
Definition ScanMode.h:16
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
double fltp08
Defines an alias representing an 8 byte floating-point number.
@ DEGREES
Angle measured in degrees (0 to 360 for a full circle).
Definition Angle.h:58
constexpr HSLColor Constant< HSLColor >::Max
The maximum HSLColor constant with all components at their maximum values.
Definition HSLColor.h:265
@ e_mesh
Perform a mesh operation on the selected object.
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Information about the object.
Definition ObjectInfo.h:55
Stores information for painting pixels at a time into a 2D texture used with MaterialRaster.
Logic for setting up a mesh that is broken apart by latitude and longitude lines with a set angle dif...