Mech-Eye API 2.5.4
API reference documentation for Mech-Eye 3D Laser Profiler
Loading...
Searching...
No Matches
api_util.h
Go to the documentation of this file.
1/*******************************************************************************
2 *BSD 3-Clause License
3 *
4 *Copyright (c) 2016-2025, Mech-Mind Robotics Technologies Co., Ltd.
5 *All rights reserved.
6 *
7 *Redistribution and use in source and binary forms, with or without
8 *modification, are permitted provided that the following conditions are met:
9 *
10 *1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 *2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 *3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 *DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************************************************************/
32
33#pragma once
34#include <iomanip>
35#include <iostream>
36#include <regex>
37#include <set>
38#include <utility>
39#ifdef WIN32
40#include <windows.h>
41#endif
42#include "ErrorStatus.h"
43#include "CommonTypes.h"
45#include "Profiler.h"
46#include "ProfilerInfo.h"
47
51inline void printProfilerInfo(const mmind::eye::ProfilerInfo& profilerInfo)
52{
53 std::cout << "........................................." << std::endl;
54 std::cout << "Model: " << profilerInfo.model << std::endl;
55#ifdef WIN32
56 const auto consoleCP = GetConsoleOutputCP();
57 SetConsoleOutputCP(CP_UTF8);
58#endif
59 std::cout << "Device name: " << profilerInfo.deviceName << std::endl;
60#ifdef WIN32
61 SetConsoleOutputCP(consoleCP);
62#endif
63 std::cout << "Controller serial number: " << profilerInfo.controllerSN << std::endl;
64 std::cout << "Sensor head serial number: " << profilerInfo.sensorSN << std::endl;
65 std::cout << "IP address: " << profilerInfo.ipAddress << std::endl;
66 std::cout << "Subnet mask: " << profilerInfo.subnetMask << std::endl;
67 std::cout << "IP address assignment method: "
68 << mmind::eye::ipAssignmentMethodToString(profilerInfo.ipAssignmentMethod)
69 << std::endl;
70 std::cout << "Hardware version: "
71 << "V" << profilerInfo.hardwareVersion.toString() << std::endl;
72 std::cout << "Firmware version: "
73 << "V" << profilerInfo.firmwareVersion.toString() << std::endl;
74 std::cout << "Support status: "
75 << (profilerInfo.supported ? "Supported" : "Unsupported") << std::endl;
76 if (!profilerInfo.lastSupportedVersion.isEmpty()) {
77 std::cout << "Last supported version: "
78 << "V" << profilerInfo.lastSupportedVersion.toString() << std::endl;
79 }
80 std::cout << "........................................." << std::endl;
81 std::cout << std::endl;
82}
83
84inline void printProfilerStatus(const mmind::eye::ProfilerStatus& profilerStatus)
85{
86 std::cout << ".....Profiler temperatures....." << std::endl;
87 std::cout << std::fixed << std::setprecision(1);
88 std::cout << "Controller CPU: " << profilerStatus.temperature.controllerCpuTemperature << "°C"
89 << std::endl;
90 std::cout << "Sensor CPU: " << profilerStatus.temperature.sensorCpuTemperature << "°C"
91 << std::endl;
92 std::cout << "..............................." << std::endl;
93 std::cout << std::defaultfloat << std::setprecision(6);
94 std::cout << std::endl;
95}
96
102{
103 std::cout << "Looking for available profilers..." << std::endl;
104 std::vector<mmind::eye::ProfilerInfo> profilerInfoList =
106
107 if (profilerInfoList.empty()) {
108 std::cout << "No profilers are available." << std::endl;
109 return false;
110 }
111
112 for (size_t i = 0; i < profilerInfoList.size(); i++) {
113 std::cout << "Mech-Eye device index: " << i << std::endl;
114 printProfilerInfo(profilerInfoList[i]);
115 }
116
117 std::cout << "Enter the index of the device to which you want to connect: ";
118 unsigned inputIndex = 0;
119
120 while (true) {
121 std::string str;
122 std::cin >> str;
123 if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"}) &&
124 atoi(str.c_str()) < static_cast<int>(profilerInfoList.size())) {
125 inputIndex = atoi(str.c_str());
126 break;
127 }
128 std::cout << "The entered index is invalid. Please enter the device index again: ";
129 }
130
132 status = profiler.connect(profilerInfoList[inputIndex]);
133
134 if (!status.isOK()) {
135 showError(status);
136 return false;
137 }
138
139 std::cout << "Successfully connected to the profiler." << std::endl;
140 return true;
141}
142
143inline std::vector<mmind::eye::Profiler> findAndConnectMultiProfiler()
144{
145 std::cout << "Looking for available profilers..." << std::endl;
146 std::vector<mmind::eye::ProfilerInfo> profilerInfoList =
148
149 if (profilerInfoList.empty()) {
150 std::cout << "No profilers are available." << std::endl;
151 return {};
152 }
153
154 for (size_t i = 0; i < profilerInfoList.size(); i++) {
155 std::cout << "Mech-Eye device index: " << i << std::endl;
156 printProfilerInfo(profilerInfoList[i]);
157 }
158
159 std::string str;
160 std::set<unsigned> indices;
161
162 while (true) {
163 std::cout << "Enter the indices of the devices to which you want to connect: " << std::endl;
164 std::cout << "Enter the character \"c\" at the end of all the indices" << std::endl;
165
166 std::cin >> str;
167 if (str == "c")
168 break;
169 if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"}) &&
170 atoi(str.c_str()) < static_cast<int>(profilerInfoList.size()))
171 indices.insert(atoi(str.c_str()));
172 else
173 std::cout << "The entered indices are invalid. Please enter the device indices again: ";
174 }
175
176 std::vector<mmind::eye::Profiler> profilerList{};
177
178 for (const auto index : indices) {
179 mmind::eye::Profiler profiler;
180 const auto status = profiler.connect(profilerInfoList[index]);
181 if (status.isOK())
182 profilerList.push_back(profiler);
183 else
184 showError(status);
185 }
186
187 return profilerList;
188}
189
190inline bool confirmCapture()
191{
192 std::cout
193 << "Do you want the profiler to capture image? Enter \"y\" to confirm or \"n\" to cancel: "
194 << std::endl;
195 while (true) {
196 std::string confirmStr;
197 std::cin >> confirmStr;
198 if (confirmStr == "y") {
199 return true;
200 } else if (confirmStr == "n") {
201 std::cout << "The capture command was canceled." << std::endl;
202 return false;
203 } else {
204 std::cout << "The entered character was invalid. Please enter \"y\" ot confirm or "
205 "\"n\" to cancel:"
206 << std::endl;
207 }
208 }
209}
210
212 const mmind::eye::UserSet& userSet, bool savePLY = true,
213 bool saveCSV = true, bool isOrganized = false)
214{
215 if (batch.isEmpty())
216 return;
217
218 // Get the X-axis resolution
219 double xResolution{};
221 xResolution);
222 if (!status.isOK()) {
223 showError(status);
224 return;
225 }
226
227 // Get the Y resolution
228 double yResolution{};
229 status =
231 if (!status.isOK()) {
232 showError(status);
233 return;
234 }
235 // // Uncomment the following lines for custom Y Unit
236 // // Prompt to enter the desired encoder resolution, which is the travel distance corresponding
237 // // to
238 // // one quadrature signal.
239 // std::cout << "Please enter the desired encoder resolution (integer, unit: μm, min: "
240 // "1, max: 65535): ";
241 // while (true) {
242 // std::string str;
243 // std::cin >> str;
244 // if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"})) {
245 // yResolution = atoi(str.c_str());
246 // break;
247 // }
248 // std::cout << "Input invalid! Please enter the desired encoder resolution (integer, unit:
249 // "
250 // "μm, min: 1, max: 65535): ";
251 // }
252
253 int lineScanTriggerSource{};
255 lineScanTriggerSource);
256 if (!status.isOK()) {
257 showError(status);
258 return;
259 }
260
261 bool useEncoderValues =
262 lineScanTriggerSource ==
264
265 int triggerInterval{};
267 triggerInterval);
268 if (!status.isOK()) {
269 showError(status);
270 return;
271 }
272
273 std::cout << "Save the point cloud." << std::endl;
274 if (saveCSV)
276 xResolution, yResolution, useEncoderValues, triggerInterval,
278 isOrganized));
279 if (savePLY)
281 xResolution, yResolution, useEncoderValues, triggerInterval,
283 isOrganized));
284}
285
287 const mmind::eye::ProfileBatch& batch, const mmind::eye::UserSet& userSet)
288{
289 if (batch.isEmpty())
290 return {0};
291
292 // Get the X-axis resolution
293 double xResolution{};
295 xResolution);
296 if (!status.isOK()) {
297 showError(status);
298 return {0};
299 }
300
301 // Get the Y resolution
302 double yResolution{};
303 status =
305 if (!status.isOK()) {
306 showError(status);
307 return {0};
308 }
309 // // Uncomment the following lines for custom Y Unit
310 // // Prompt to enter the desired encoder resolution, which is the travel distance corresponding
311 // // to
312 // // one quadrature signal.
313 // std::cout << "Please enter the desired encoder resolution (integer, unit: μm, min: "
314 // "1, max: 65535): ";
315 // while (true) {
316 // std::string str;
317 // std::cin >> str;
318 // if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"})) {
319 // yResolution = atoi(str.c_str());
320 // break;
321 // }
322 // std::cout << "Input invalid! Please enter the desired encoder resolution (integer, unit:
323 // "
324 // "μm, min: 1, max: 65535): ";
325 // }
326
327 int lineScanTriggerSource{};
329 lineScanTriggerSource);
330 if (!status.isOK()) {
331 showError(status);
332 return {0};
333 }
334
335 bool useEncoderValues =
336 lineScanTriggerSource ==
338
339 int triggerInterval{};
341 triggerInterval);
342 if (!status.isOK()) {
343 showError(status);
344 return {0};
345 }
346
347 return batch.getUntexturedPointCloud(xResolution, yResolution, useEncoderValues,
349}
350
352 const mmind::eye::ProfileBatch& batch, const mmind::eye::UserSet& userSet)
353{
354 if (batch.isEmpty())
355 return {0};
356
357 // Get the X-axis resolution
358 double xResolution{};
360 xResolution);
361 if (!status.isOK()) {
362 showError(status);
363 return {0};
364 }
365
366 // Get the Y resolution
367 double yResolution{};
368 status =
370 if (!status.isOK()) {
371 showError(status);
372 return {0};
373 }
374 // // Uncomment the following lines for custom Y Unit
375 // // Prompt to enter the desired encoder resolution, which is the travel distance corresponding
376 // // to
377 // // one quadrature signal.
378 // std::cout << "Please enter the desired encoder resolution (integer, unit: μm, min: "
379 // "1, max: 65535): ";
380 // while (true) {
381 // std::string str;
382 // std::cin >> str;
383 // if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"})) {
384 // yResolution = atoi(str.c_str());
385 // break;
386 // }
387 // std::cout << "Input invalid! Please enter the desired encoder resolution (integer, unit:
388 // "
389 // "μm, min: 1, max: 65535): ";
390 // }
391
392 int lineScanTriggerSource{};
394 lineScanTriggerSource);
395 if (!status.isOK()) {
396 showError(status);
397 return {0};
398 }
399
400 bool useEncoderValues =
401 lineScanTriggerSource ==
403
404 int triggerInterval{};
406 triggerInterval);
407 if (!status.isOK()) {
408 showError(status);
409 return {0};
410 }
411
412 return batch.getTexturedPointCloud(xResolution, yResolution, useEncoderValues, triggerInterval,
414}
void savePLY(const mmind::api::PointXYZMap &pointXYZMap, const std::string &path)
Definition PclUtil.h:121
void showError(const mmind::api::ErrorStatus &status)
Definition SampleUtil.h:40
mmind::eye::ProfileBatch::TexturedPointCloud getTexturedPointCloud(const mmind::eye::ProfileBatch &batch, const mmind::eye::UserSet &userSet)
Definition api_util.h:351
bool findAndConnect(mmind::eye::Profiler &profiler)
Discovers all available laser profilers and allows the user to connect to a laser profiler by inputti...
Definition api_util.h:101
std::vector< mmind::eye::Profiler > findAndConnectMultiProfiler()
Definition api_util.h:143
bool confirmCapture()
Definition api_util.h:190
void printProfilerStatus(const mmind::eye::ProfilerStatus &profilerStatus)
Definition api_util.h:84
void printProfilerInfo(const mmind::eye::ProfilerInfo &profilerInfo)
Prints the data in the ProfilerInfo object.
Definition api_util.h:51
void savePointCloud(const mmind::eye::ProfileBatch &batch, const mmind::eye::UserSet &userSet, bool savePLY=true, bool saveCSV=true, bool isOrganized=false)
Definition api_util.h:211
mmind::eye::ProfileBatch::PointCloud getUntexturedPointCloud(const mmind::eye::ProfileBatch &batch, const mmind::eye::UserSet &userSet)
Definition api_util.h:286
Represents the data struct of the profile data.
Definition BatchArray.h:16
Represents a batch of profiles, which can be obtained by calling Profiler::retrieveBatchData()....
Definition ProfileData.h:74
TexturedPointCloud getTexturedPointCloud(double xResolution, double yResolution, bool useEncoderValues, int triggerInterval, CoordinateUnit coordinateUnit=CoordinateUnit::Millimeter) const
Gets the textured point cloud data in the batch. Each point in TexturedPointCloud contains the X,...
UntexturedPointCloud getUntexturedPointCloud(double xResolution, double yResolution, bool useEncoderValues, int triggerInterval, CoordinateUnit coordinateUnit=CoordinateUnit::Millimeter) const
Gets the untextured point cloud data in the batch. Each point in UntexturedPointCloud contains the X,...
ErrorStatus saveUntexturedPointCloud(double xResolution, double yResolution, bool useEncoderValues, int triggerInterval, FileFormat fileFormat, const std::string &fileName, CoordinateUnit coordinateUnit=CoordinateUnit::Millimeter, bool isOrganized=false) const
Saves the untextured point cloud data in the batch. Each point in UntexturedPointCloud contains the X...
bool isEmpty() const
Checks if the ProfileBatch object has no elements.
Operates the laser profiler. Use Profiler::connect to connect an available laser profiler,...
Definition Profiler.h:100
static std::vector< ProfilerInfo > discoverProfilers(unsigned int timeoutMs=5000)
Discovers all available laser profilers and returns the list of information of all available laser pr...
ErrorStatus connect(const ProfilerInfo &info, unsigned int timeoutMs=5000)
Connects to a laser profiler via ProfilerInfo.
Definition UserSet.h:13
ErrorStatus getIntValue(const std::string &parameterName, int &value) const
Gets the current value of an _Int-type device parameter. See Parameter for details.
ErrorStatus getEnumValue(const std::string &parameterName, int &value) const
Gets the current value of an _Enum-type device parameter in the form of the integer value....
ErrorStatus getFloatValue(const std::string &parameterName, double &value) const
Gets the current value of a _Float-type device parameter. See Parameter for details.
std::string toString() const
Converts a Version object to a string.
Definition Version.h:71
bool isEmpty() const
Checks if a Version object is empty.
Definition Version.h:95
static constexpr const char * name
Definition ScanParameters.h:291
static constexpr const char * name
Definition ScanParameters.h:305
static constexpr const char * name
Definition ScanParameters.h:194
static constexpr const char * name
Definition ScanParameters.h:82
Describes the types of errors.
Definition ErrorStatus.h:12
bool isOK() const
Returns true if the operation succeeded.
Definition ErrorStatus.h:85
Describes the laser profiler information.
Definition ProfilerInfo.h:44
IpAssignmentMethod ipAssignmentMethod
The IP address assignment method of the laser profiler.
Definition ProfilerInfo.h:54
std::string controllerSN
The controller serial number.
Definition ProfilerInfo.h:47
bool supported
The support status of the device.
Definition ProfilerInfo.h:56
std::string sensorSN
The sensor serial number.
Definition ProfilerInfo.h:48
std::string model
The laser profiler model.
Definition ProfilerInfo.h:45
Version lastSupportedVersion
The last supported version of the device.
Definition ProfilerInfo.h:57
Version firmwareVersion
The version of the firmware. The firmware can be upgraded.
Definition ProfilerInfo.h:50
std::string subnetMask
The IP subnet mask of the laser profiler.
Definition ProfilerInfo.h:52
Version hardwareVersion
The version of the hardware. The hardware cannot be upgraded.
Definition ProfilerInfo.h:49
std::string deviceName
The device name (UTF-8 encoded).
Definition ProfilerInfo.h:46
std::string ipAddress
The IP address of the laser profiler.
Definition ProfilerInfo.h:51
Describes the laser profiler's statuses.
Definition Profiler.h:90
ProfilerTemperature temperature
Definition Profiler.h:91
float controllerCpuTemperature
The temperature (in °C) of the controller CPU.
Definition Profiler.h:82
float sensorCpuTemperature
The temperature (in °C) of the FPGA.
Definition Profiler.h:83