Mech-Eye API 2.5.0
API reference documentation for Mech-Eye 3D Laser Profiler
All Classes Functions Variables Typedefs Enumerations Enumerator Pages
api_util.h
1/*******************************************************************************
2 *BSD 3-Clause License
3 *
4 *Copyright (c) 2016-2025, Mech-Mind Robotics
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"
44#include "profiler/parameters/ScanParameters.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 << "........................................." << std::endl;
75 std::cout << std::endl;
76}
77
78inline void printProfilerStatus(const mmind::eye::ProfilerStatus& profilerStatus)
79{
80 std::cout << ".....Profiler temperatures....." << std::endl;
81 std::cout << "Controller CPU: " << std::setprecision(4)
82 << profilerStatus.temperature.controllerCpuTemperature << "°C" << std::endl;
83 std::cout << "Sensor CPU: " << std::setprecision(4)
84 << profilerStatus.temperature.sensorCpuTemperature << "°C" << std::endl;
85 std::cout << "..............................." << std::endl;
86 std::cout << std::endl;
87}
88
93inline bool findAndConnect(mmind::eye::Profiler& profiler)
94{
95 std::cout << "Looking for available profilers..." << std::endl;
96 std::vector<mmind::eye::ProfilerInfo> profilerInfoList =
98
99 if (profilerInfoList.empty()) {
100 std::cout << "No profilers are available." << std::endl;
101 return false;
102 }
103
104 for (int i = 0; i < profilerInfoList.size(); i++) {
105 std::cout << "Mech-Eye device index: " << i << std::endl;
106 printProfilerInfo(profilerInfoList[i]);
107 }
108
109 std::cout << "Enter the index of the device to which you want to connect: ";
110 unsigned inputIndex = 0;
111
112 while (true) {
113 std::string str;
114 std::cin >> str;
115 if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"}) &&
116 atoi(str.c_str()) < profilerInfoList.size()) {
117 inputIndex = atoi(str.c_str());
118 break;
119 }
120 std::cout << "The entered index is invalid. Please enter the device index again: ";
121 }
122
124 status = profiler.connect(profilerInfoList[inputIndex]);
125
126 if (!status.isOK()) {
127 showError(status);
128 return false;
129 }
130
131 std::cout << "Successfully connected to the profiler." << std::endl;
132 return true;
133}
134
135inline std::vector<mmind::eye::Profiler> findAndConnectMultiProfiler()
136{
137 std::cout << "Looking for available profilers..." << std::endl;
138 std::vector<mmind::eye::ProfilerInfo> profilerInfoList =
140
141 if (profilerInfoList.empty()) {
142 std::cout << "No profilers are available." << std::endl;
143 return {};
144 }
145
146 for (int i = 0; i < profilerInfoList.size(); i++) {
147 std::cout << "Mech-Eye device index: " << i << std::endl;
148 printProfilerInfo(profilerInfoList[i]);
149 }
150
151 std::string str;
152 std::set<unsigned> indices;
153
154 while (true) {
155 std::cout << "Enter the indices of the devices to which you want to connect: " << std::endl;
156 std::cout << "Enter the character \"c\" at the end of all the indices" << std::endl;
157
158 std::cin >> str;
159 if (str == "c")
160 break;
161 if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"}) &&
162 atoi(str.c_str()) < profilerInfoList.size())
163 indices.insert(atoi(str.c_str()));
164 else
165 std::cout << "The entered indices are invalid. Please enter the device indices again: ";
166 }
167
168 std::vector<mmind::eye::Profiler> profilerList{};
169
170 auto iter = indices.cbegin();
171 for (int i = 0; i < indices.size(); ++i, ++iter) {
172 mmind::eye::Profiler profiler;
173 auto status = profiler.connect(profilerInfoList[*iter]);
174 if (status.isOK())
175 profilerList.push_back(profiler);
176 else
177 showError(status);
178 }
179
180 return profilerList;
181}
182
183inline bool confirmCapture()
184{
185 std::cout
186 << "Do you want the profiler to capture image? Enter \"y\" to confirm or \"n\" to cancel: "
187 << std::endl;
188 while (true) {
189 std::string confirmStr;
190 std::cin >> confirmStr;
191 if (confirmStr == "y") {
192 return true;
193 } else if (confirmStr == "n") {
194 std::cout << "The capture command was canceled." << std::endl;
195 return false;
196 } else {
197 std::cout << "The entered character was invalid. Please enter \"y\" ot confirm or "
198 "\"n\" to cancel:"
199 << std::endl;
200 }
201 }
202}
203
204inline void savePointCloud(const mmind::eye::ProfileBatch& batch,
205 const mmind::eye::UserSet& userSet, bool savePLY = true,
206 bool saveCSV = true, bool isOrganized = false)
207{
208 if (batch.isEmpty())
209 return;
210
211 // Get the X-axis resolution
212 double xResolution{};
213 auto status = userSet.getFloatValue(mmind::eye::point_cloud_resolutions::XAxisResolution::name,
214 xResolution);
215 if (!status.isOK()) {
216 showError(status);
217 return;
218 }
219
220 // Get the Y resolution
221 double yResolution{};
222 status =
223 userSet.getFloatValue(mmind::eye::point_cloud_resolutions::YResolution::name, yResolution);
224 if (!status.isOK()) {
225 showError(status);
226 return;
227 }
228 // // Uncomment the following lines for custom Y Unit
229 // // Prompt to enter the desired encoder resolution, which is the travel distance corresponding
230 // // to
231 // // one quadrature signal.
232 // std::cout << "Please enter the desired encoder resolution (integer, unit: μm, min: "
233 // "1, max: 65535): ";
234 // while (true) {
235 // std::string str;
236 // std::cin >> str;
237 // if (std::regex_match(str.begin(), str.end(), std::regex{"[0-9]+"})) {
238 // yResolution = atoi(str.c_str());
239 // break;
240 // }
241 // std::cout << "Input invalid! Please enter the desired encoder resolution (integer, unit:
242 // "
243 // "μm, min: 1, max: 65535): ";
244 // }
245
246 int lineScanTriggerSource{};
247 status = userSet.getEnumValue(mmind::eye::trigger_settings::LineScanTriggerSource::name,
248 lineScanTriggerSource);
249 if (!status.isOK()) {
250 showError(status);
251 return;
252 }
253
254 bool useEncoderValues =
255 lineScanTriggerSource ==
256 static_cast<int>(mmind::eye::trigger_settings::LineScanTriggerSource::Value::Encoder);
257
258 int triggerInterval{};
259 status = userSet.getIntValue(mmind::eye::trigger_settings::EncoderTriggerInterval::name,
260 triggerInterval);
261 if (!status.isOK()) {
262 showError(status);
263 return;
264 }
265
266 std::cout << "Save the point cloud." << std::endl;
267 if (saveCSV)
268 showError(batch.saveUntexturedPointCloud(
269 xResolution, yResolution, useEncoderValues, triggerInterval,
270 mmind::eye::FileFormat::CSV, "PointCloud.csv", mmind::eye::CoordinateUnit::Millimeter,
271 isOrganized));
272 if (savePLY)
273 showError(batch.saveUntexturedPointCloud(
274 xResolution, yResolution, useEncoderValues, triggerInterval,
275 mmind::eye::FileFormat::PLY, "PointCloud.ply", mmind::eye::CoordinateUnit::Millimeter,
276 isOrganized));
277}
Represents a batch of profiles, which can be obtained by calling Profiler::retrieveBatchData()....
Definition ProfileData.h:42
bool isEmpty() const
Checks if the ProfileBatch object has no elements.
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...
Operates the laser profiler. Use Profiler::connect to connect an available laser profiler,...
Definition Profiler.h:68
ErrorStatus connect(const ProfilerInfo &info, unsigned int timeoutMs=5000)
Connects to a laser profiler via ProfilerInfo.
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 getIntValue(const std::string &parameterName, int &value) const
Gets the current value of an _Int-type device parameter. See Parameter for details.
ErrorStatus getFloatValue(const std::string &parameterName, double &value) const
Gets the current value of a _Float-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....
std::string toString() const
Converts a Version object to a string.
Definition Version.h:71
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.
Version hardwareVersion
The version of the hardware. The hardware cannot be upgraded.
Version firmwareVersion
The version of the firmware. The firmware can be upgraded.
std::string subnetMask
The IP subnet mask of the laser profiler.
IpAssignmentMethod ipAssignmentMethod
The IP address assignment method of the laser profiler.
std::string model
The laser profiler model.
std::string controllerSN
The controller serial number.
std::string deviceName
The device name (UTF-8 encoded).
std::string sensorSN
The sensor serial number.
std::string ipAddress
The IP address of the laser profiler.
Describes the laser profiler's statuses.
Definition Profiler.h:58
float controllerCpuTemperature
The temperature (in °C) of the controller CPU.
Definition Profiler.h:50
float sensorCpuTemperature
The temperature (in °C) of the FPGA.
Definition Profiler.h:51