scanner_v2.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020-2021 Pilz GmbH & Co. KG
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU Lesser General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program. If not, see <https://www.gnu.org/licenses/>.
15 
17 
18 #include <cassert>
19 #include <stdexcept>
20 
22 
24 {
26 
27 // clang-format off
28 #define BIND_EVENT(event_name)\
29  std::bind(&ScannerV2::triggerEvent<event_name>, this)
30 
31 #define BIND_RAW_DATA_EVENT(event_name)\
32  [this](const data_conversion_layer::RawDataConstPtr& data, const std::size_t& num_bytes, const int64_t& timestamp){ triggerEventWithParam(event_name(data, num_bytes, timestamp)); }
33 // clang-format on
34 
35 std::unique_ptr<util::Watchdog> WatchdogFactory::create(const util::Watchdog::Timeout& timeout,
36  const std::function<void()>& timeout_callback)
37 {
38  return std::unique_ptr<util::Watchdog>(new util::Watchdog(timeout, timeout_callback));
39 }
40 
41 ScannerV2::ScannerV2(const ScannerConfiguration& scanner_config, const LaserScanCallback& laser_scan_callback)
42  : IScanner(scanner_config, laser_scan_callback)
43  , sm_(new ScannerStateMachine(IScanner::config(),
44  // LCOV_EXCL_START
45  // The following includes calls to std::bind which are not marked correctly
46  // by some gcc versions, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96006
49  std::bind(&ScannerV2::scannerStartErrorCallback, this, std::placeholders::_1),
50  std::bind(&ScannerV2::scannerStopErrorCallback, this, std::placeholders::_1),
53  std::bind(&ScannerV2::scannerStartedCallback, this),
54  std::bind(&ScannerV2::scannerStoppedCallback, this),
56  BIND_EVENT(scanner_events::StartTimeout),
57  BIND_EVENT(scanner_events::MonitoringFrameTimeout)))
58 // LCOV_EXCL_STOP
59 {
60  const std::lock_guard<std::mutex> lock(member_mutex_);
61  sm_->start();
62 }
63 
65 {
66  PSENSCAN_DEBUG("Scanner", "Destruction called.");
67 
68  const std::lock_guard<std::mutex> lock(member_mutex_);
69  sm_->stop();
70 }
71 
72 std::future<void> ScannerV2::start()
73 {
74  PSENSCAN_INFO("Scanner", "Start scanner called.");
75 
76  const std::lock_guard<std::mutex> lock(member_mutex_);
78  {
79  return std::future<void>();
80  }
81 
82  // No call to triggerEvent() because lock already taken
83  sm_->process_event(scanner_events::StartRequest());
84  // Due to the fact that the getting of the future should always succeed (because of the
85  // protected check and replacement of the promise), the std::future_error exception is not caught here.
86  scanner_has_started_ = std::promise<void>();
87  return scanner_has_started_.value().get_future();
88 }
89 
90 std::future<void> ScannerV2::stop()
91 {
92  PSENSCAN_INFO("Scanner", "Stop scanner called.");
93 
94  const std::lock_guard<std::mutex> lock(member_mutex_);
96  {
97  return std::future<void>();
98  }
99 
100  // No call to triggerEvent() because lock already taken
101  sm_->process_event(scanner_events::StopRequest());
102  // Due to the fact that the getting of the future should always succeed (because of the
103  // protected check and replacement of the promise), the std::future_error exception is not caught here.
104  scanner_has_stopped_ = std::promise<void>();
105  return scanner_has_stopped_.value().get_future();
106 }
107 
108 // PLEASE NOTE:
109 // The callback does not take a member lock because the callback is always called
110 // via call to triggerEvent() or triggerEventWithParam() which already take the mutex.
112 {
113  PSENSCAN_INFO("ScannerController", "Scanner started successfully.");
114  scanner_has_started_.value().set_value();
115  scanner_has_started_ = boost::none;
116 }
117 
118 // PLEASE NOTE:
119 // The callback does not take a member lock because the callback is always called
120 // via call to triggerEvent() or triggerEventWithParam() which already take the mutex.
122 {
123  PSENSCAN_INFO("ScannerController", "Scanner stopped successfully.");
124  scanner_has_stopped_.value().set_value();
125  scanner_has_stopped_ = boost::none;
126 }
127 
128 void ScannerV2::scannerStartErrorCallback(const std::string& error_msg)
129 {
130  PSENSCAN_INFO("ScannerController", "Scanner start failed.");
131  scanner_has_started_.value().set_exception(std::make_exception_ptr(std::runtime_error(error_msg)));
132  scanner_has_started_ = boost::none;
133 }
134 
135 void ScannerV2::scannerStopErrorCallback(const std::string& error_msg)
136 {
137  PSENSCAN_INFO("ScannerController", "Scanner stop failed.");
138  scanner_has_stopped_.value().set_exception(std::make_exception_ptr(std::runtime_error(error_msg)));
139  scanner_has_stopped_ = boost::none;
140 }
141 
142 } // namespace psen_scan_v2_standalone
std::mutex member_mutex_
This Mutex protects ALL members of the Scanner against concurrent access. So far there exist at least...
Definition: scanner_v2.h:97
std::unique_ptr< util::Watchdog > create(const util::Watchdog::Timeout &timeout, const TimeoutCallback &timeout_callback) override
Definition: scanner_v2.cpp:35
void laserScanCallback(const LaserScan &scan)
Definition: main.cpp:36
msm::back::state_machine< ScannerProtocolDef > ScannerStateMachine
State machine handling all events according to the scanner protocol and error handling specification...
const std::chrono::high_resolution_clock::duration Timeout
Definition: watchdog.h:42
config
Contains the events needed to define and implement the scanner protocol.
ScannerV2(const ScannerConfiguration &scanner_config, const LaserScanCallback &laser_scan_callback)
Definition: scanner_v2.cpp:41
Triggered whenever the receiving of a reply message failes.
OptionalPromise scanner_has_started_
Definition: scanner_v2.h:89
#define PSENSCAN_DEBUG(name,...)
Definition: logging.h:63
Higher level data type storing the configuration details of the scanner like scanner IP...
OptionalPromise scanner_has_stopped_
Definition: scanner_v2.h:90
#define PSENSCAN_INFO(name,...)
Definition: logging.h:61
Root namespace in which the software components to communicate with the scanner (firmware-version: 2)...
Definition: udp_client.h:41
Received Start- or Stop-Reply message from scanner device.
void scannerStopErrorCallback(const std::string &error_msg)
Definition: scanner_v2.cpp:135
#define BIND_RAW_DATA_EVENT(event_name)
Definition: scanner_v2.cpp:31
This is the implementation of the Scanner API defined by IScanner.
Definition: scanner_v2.h:60
std::function< void(const LaserScan &)> LaserScanCallback
Represents the user-provided callback for processing incoming scan data.
std::future< void > start() override
An exception is set in the returned future if the scanner start was not successful.
Definition: scanner_v2.cpp:72
Timeout while waiting for scanner device to start.
Watchdog which continuously calls the specified timeout callback.
Definition: watchdog.h:39
void scannerStartErrorCallback(const std::string &error_msg)
Definition: scanner_v2.cpp:128
This is the API definition for external interaction with the scanner driver.
#define BIND_EVENT(event_name)
Definition: scanner_v2.cpp:28
std::unique_ptr< ScannerStateMachine > sm_
Definition: scanner_v2.h:99
Triggered whenever the receiving of a monitoring frame failes.
std::future< void > stop() override
An exception is set in the returned future if the scanner stop was not successful.
Definition: scanner_v2.cpp:90


psen_scan_v2
Author(s): Pilz GmbH + Co. KG
autogenerated on Sat Nov 5 2022 02:13:36