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 \brief Setup information for a Scan outlining how the data shall be formatted.
53 **/
54 struct ScanSetupSettings
55 {
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;
69 };
70 /**--------------------------------------------------------------------------------------------------
71 \brief Outlines where a given datapoint sent to a Scan object should go.
72 **/
73 enum ScanTargetBitFlags
74 {
75 e_cloud
76 , e_mesh
77 , e_calibration_a
78 , e_calibration_b
79 , e_color_raster
80 };
81
82 /**--------------------------------------------------------------------------------------------------
83 \brief A single datapoint in a 3DScan.
84 **/
85 template<class t_type>
86 struct PolarScanRecord
87 {
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;
91 t_type distance = 0.0;
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;
98 BitFlag target_bit_flags = BitFlag(0);
99 PolarScanRecord()
100 {}
101 PolarScanRecord(Angle<sint04> roll, Angle<sint04> pitch)
102 : coord(roll, pitch)
103 {}
104 PolarScanRecord(const Vector<2, Angle<sint04>>& roll_pitch)
105 : coord(roll_pitch)
106 {}
107 void updateWeight(t_type weight)
108 {
109 t_type weight_conv = weight / total_weight;
110 position *= weight_conv;
111 distance *= weight_conv;
112 intensity *= weight_conv;
113 scan_time *= weight_conv;
114 color *= weight_conv;
115 total_weight = weight;
116 }
117 template<class t_other_type>
118 void updateAverage(const PolarScanRecord<t_other_type>& record)
119 {
120 if (!IsInvalid(record.position))
121 {
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);
129 }
130 if (!IsInvalid(record.distance))
131 {
132 max_distance = getMax(max_distance, cast<t_type>(record.distance));
133 min_distance = getMin(min_distance, cast<t_type>(record.distance));
134 }
135 }
136 void clearAverage()
137 {
138 color = 0.0;
139 distance = 0.0;
140 intensity = 0.0;
141 position = Vector<3, t_type>(0.0);
142 total_weight = 0.0;
143 max_distance = Constant<t_type>::Min;
144 min_distance = Constant<t_type>::Max;
145 scan_time = 0.0;
146 scan_sweep = 0.0;
147 }
148 void autoCalcPositionH(Angle<sint04> roll = Angle<sint04>(DEGREES, 0.0f))
149 {
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>();
152 }
153 void autoCalcPositionR(Angle<sint04> yaw = Angle<sint04>(DEGREES, 0.0f))
154 {
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>();
157 }
158 constexpr fltp08 operator[](uint01 dim) const
159 {
160 return position[dim];
161 }
162 };
163
164 template<>
165 struct ObjectInfo<PolarScanRecord<fltp04>, false, false>
166 {
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>(); }
181 };
182
183 class MaterialRasterBase;
184 /**--------------------------------------------------------------------------------------------------
185 \brief A Model which contains a point cloud and a generated mesh based upon scanned polar data.
186 **/
187 class NDEVR_DESIGN_API Scan : public Model
188 {
189 public:
190
191 struct ScanCalibration
192 {
193 fltp08 head_offset = 0.0;
194 fltp08 emitter_offset = 0.0;
195 fltp08 lens_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);
199 };
200 public:
201 Scan();//Invalid
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);
216
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();//For older scans
237 void updateOlderAngles();//Need to convert older models degrees to internal units
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;
251 ScanMode scanMode() 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);
261 protected:
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);
267 void init();
268 void updateScanColors();
269 void initMaterial();
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);
273 protected:
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;//Used to check to see if auto-updated
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;
299
300 protected:
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;
304 };
305
306}
307#endif
#define NDEVR_DESIGN_API
Definition DLLInfo.h:55
#define NDEVR_DESIGN_T_API
Definition DLLInfo.h:56
Definition ACIColor.h:37
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