API Documentation
Loading...
Searching...
No Matches
Scan.h
Go to the documentation of this file.
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 struct RasterInfo;
47 class ImageData;
48 struct ZippedRadialMeshOptions;
49 NDEVR_DESIGN_T_API template class NDEVR_DESIGN_API StringStream<ScanMode>;
50
51
52 struct ScanSetupSettings
53 {
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;
67 };
68
69 enum ScanTargetBitFlags
70 {
71 e_cloud
72 , e_mesh
73 , e_calibration_a
74 , e_calibration_b
75 , e_color_raster
76 };
77
78 template<class t_type>
79 struct PolarScanRecord
80 {
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;
84 t_type distance = 0.0;
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;
91 BitFlag target_bit_flags = BitFlag(0);
92 PolarScanRecord()
93 {}
94 PolarScanRecord(Angle<sint04> roll, Angle<sint04> pitch)
95 : coord(roll, pitch)
96 {}
97 PolarScanRecord(const Vector<2, Angle<sint04>>& roll_pitch)
98 : coord(roll_pitch)
99 {}
100 void updateWeight(t_type weight)
101 {
102 t_type weight_conv = weight / total_weight;
103 position *= weight_conv;
104 distance *= weight_conv;
105 intensity *= weight_conv;
106 scan_time *= weight_conv;
107 color *= weight_conv;
108 total_weight = weight;
109 }
110 template<class t_other_type>
111 void updateAverage(const PolarScanRecord<t_other_type>& record)
112 {
113 if (!isNaN(record.position))
114 {
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);
122 }
123 if (!isNaN(record.distance))
124 {
125 max_distance = getMax(max_distance, cast<t_type>(record.distance));
126 min_distance = getMin(min_distance, cast<t_type>(record.distance));
127 }
128 }
129 void clearAverage()
130 {
131 color = 0.0;
132 distance = 0.0;
133 intensity = 0.0;
134 position = Vector<3, t_type>(0.0);
135 total_weight = 0.0;
136 max_distance = Constant<t_type>::Min;
137 min_distance = Constant<t_type>::Max;
138 scan_time = 0.0;
139 scan_sweep = 0.0;
140 }
141 void autoCalcPositionH(Angle<sint04> roll = Angle<sint04>(DEGREES, 0.0f))
142 {
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>();
145 }
146 void autoCalcPositionR(Angle<sint04> yaw = Angle<sint04>(DEGREES, 0.0f))
147 {
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>();
150 }
151 constexpr fltp08 operator[](uint01 dim) const
152 {
153 return position[dim];
154 }
155 };
156
157 template<>
158 struct ObjectInfo<PolarScanRecord<fltp04>, false, false>
159 {
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>(); }
174 };
175
176
177 class MaterialRasterBase;
178 class NDEVR_DESIGN_API Scan : public Model
179 {
180 public:
181
182 struct ScanCalibration
183 {
184 fltp08 head_offset = 0.0;
185 fltp08 emitter_offset = 0.0;
186 fltp08 lens_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);
190 };
191 public:
192 Scan();//Invalid
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);
207
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();//For older scans
228 void updateOlderAngles();//Need to convert older models degrees to internal units
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;
242 ScanMode scanMode() 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);
252 protected:
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);
258 void init();
259 void updateScanColors();
260 void initMaterial();
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);
264 protected:
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;//Used to check to see if auto-updated
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;
290
291 protected:
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;
295 };
296
297}
298#endif
#define NDEVR_DESIGN_API
Definition DLLInfo.h:77
#define NDEVR_DESIGN_T_API
Definition DLLInfo.h:78
Definition ACIColor.h:37
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