LaserScannerSelfLocalisation.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotComponents::ArmarXObjects::LaserScannerSelfLocalisation
17 * @author Fabian Paus ( fabian dot paus at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <atomic>
26#include <optional>
27
28#include <Eigen/Eigen>
29
33#include <ArmarXCore/interface/components/EmergencyStopInterface.h>
34
35#include <RobotAPI/interface/units/LaserScannerUnit.h>
36
37#include <RobotComponents/interface/components/LaserScannerSelfLocalisation.h>
38
39#include <MemoryX/interface/components/LongtermMemoryInterface.h>
40#include <MemoryX/interface/components/WorkingMemoryInterface.h>
41#include <MemoryX/interface/memorytypes/MemorySegments.h>
46
47namespace armarx
48{
50 {
51 Eigen::Vector2f start;
52 Eigen::Vector2f end;
53 };
54
56 {
58 Eigen::Vector2f* pointsBegin;
59 Eigen::Vector2f* pointsEnd;
60 };
61
63 {
64 Eigen::Matrix4f pose;
65 LaserScannerInfo info;
66 std::shared_ptr<std::mutex> mutex;
67 LaserScan scan;
68 std::vector<Eigen::Vector2f> points;
69 std::vector<ExtractedEdge> edges;
70 IceUtil::Time measurementTime;
71 };
72
74 {
75 float dt;
76 float x;
77 float y;
78 float theta;
79 };
80
81 /**
82 * @class LaserScannerSelfLocalisationPropertyDefinitions
83 * @brief
84 */
87 {
88 public:
91 {
93 "LaserScannerSelfLocalisationTopic",
94 "The name of the report topic.");
95 defineOptionalProperty<std::string>("RobotStateComponentName",
96 "RobotStateComponent",
97 "The name of the RobotStateComponent. Used to get "
98 "local transformation of laser scanners");
100 "Platform",
101 "Name of the platform to use. This property is "
102 "used to listen to the platform topic");
103 defineOptionalProperty<std::string>("LaserScannerUnitName",
104 "LaserScannerSimulation",
105 "Name of the laser scanner unit to use.");
106 defineOptionalProperty<std::string>("WorkingMemoryName",
107 "WorkingMemory",
108 "Name of the WorkingMemory that should be used");
110 "LongtermMemoryName", "LongtermMemory", "Name of the LongtermMemory component");
112 "UpdateWorkingMemory",
113 true,
114 "Update the working memory with the corrected position (disable in simulation)");
116 "RobotComponents/maps/building-5020-kitchen.json",
117 "Floor map (2D) used for global localisation");
119 "",
120 "Name of the agent instance. If empty, the robot "
121 "name of the RobotStateComponent will be used");
123 "EmergencyStopMasterName",
124 "EmergencyStopMaster",
125 "The name used to register as an EmergencyStopMaster");
126 defineOptionalProperty<std::string>("DebugObserverName",
127 "DebugObserver",
128 "Name of the topic the DebugObserver listens on");
129
131 "UpdatePeriodInMs", 5, "Update period used for the map localisation");
132 defineOptionalProperty<int>("UpdatePeriodWorkingMemoryInMs",
133 30,
134 "Update period used for updating the working memory");
135 defineOptionalProperty<int>("UpdatePeriodLongtermMemoryInMs",
136 30,
137 "Update period used for updating the longterm memory");
138 defineOptionalProperty<float>("RobotPositionZ",
139 0.0f,
140 "The z-coordinate of the reported postion. Laser "
141 "scanners can only self localize in x,y.");
142
143 defineOptionalProperty<float>("MaximalLaserScannerDelay",
144 0.1,
145 "If no new sensor values have been reported for this "
146 "amound of seconds, we emit a soft emergency stop");
147
148 defineOptionalProperty<int>("SmoothFrameSize",
149 7,
150 "Frame size used for smoothing of laser scanner input",
153 "SmoothMergeDistance",
154 160,
155 "Distance in mm up to which laser scanner points are merged",
158 "MatchingMaxDistance",
159 300.0f,
160 "Maximal distance in mm up to which points are matched against edges of the map",
163 "MatchingMinPoints",
164 0.01f,
165 "Minimum percentage of points which need to be matched (range [0, 1]). If less "
166 "points are matched no global correction is applied.",
169 "MatchingCorrectionFactor",
170 0.01f,
171 "This factor is used to apply the calculated map correction (range [0, 1])",
173 defineOptionalProperty<float>("EdgeMaxDistance",
174 600.0f,
175 "Maximum distance between adjacent points up to which "
176 "they are merged into one edge [mm]",
179 "EdgeMaxDeltaAngle",
180 0.10472f,
181 "Maximum angle delta up to which adjacent points are merged into one edge [rad]",
183 defineOptionalProperty<float>("EdgePointAddingThreshold",
184 10.0f,
185 "Maximum least square error up to which points are added "
186 "to an edge (extension at the front and back)",
188 defineOptionalProperty<int>("EdgeEpsilon",
189 4,
190 "Half frame size for line regression (angle calculation)",
193 "EdgeMinPoints",
194 30,
195 "Minimum number of points per edge (no edges with less points will be extracted)",
197
198 defineOptionalProperty<bool>("UseOdometry",
199 true,
200 "Enable or disable odometry for pose estimation",
202 defineOptionalProperty<bool>("UseMapCorrection",
203 true,
204 "Enable or disable map localisation for pose correction",
207 "ReportPoints",
208 false,
209 "Enable or disable the reports of (post-processed) laser scan points",
211 defineOptionalProperty<bool>("ReportEdges",
212 true,
213 "Enable or disable the reports of extracted edges",
215
217 "SensorStdDev",
218 100,
219 "Standard deviation in position of the localization result",
221 defineOptionalProperty<float>("VelSensorStdDev",
222 0.1f,
223 "Standard deviation of the reported velocity",
225
226 defineOptionalProperty<std::string>("LoggingFilePath",
227 "",
228 "Path to sensor data log file",
231 "RecordData",
232 false,
233 "If true, data is logged. Can be changed online. When set to false online, data is "
234 "written to file. Otherwise on disconnect.",
236
238 "PlatformRectangleMin",
239 "0, 0",
240 "Ignores points within the platform rectangle (this is the min x/y point)");
242 "PlatformRectangleMax",
243 "0, 0",
244 "Ignores points within the platform rectangle (this is the max x/y point)");
245 }
246 };
247
248 /**
249 * @defgroup Component-LaserScannerSelfLocalisation LaserScannerSelfLocalisation
250 * @ingroup RobotComponents-Components
251 * The component LaserScannerSelfLocalisation is responsible for self localisation of a
252 * platform in a predefined two dimensional map.
253 *
254 * The odometry is used as a primary source for determining the current position of the
255 * platform. Since this method leads to unbounded errors, we also use the laser scanners
256 * to correct the estimated position. This is done by matching the laser scan input to
257 * edges of a predefined map.
258 *
259 * This method requires a good estimate of the initial position at startup because the
260 * correction by the laser scans can only correct small errors.
261 *
262 *
263 * @class LaserScannerSelfLocalisation
264 * @ingroup Component-LaserScannerSelfLocalisation
265 * @brief The class LaserScannerSelfLocalisation implements a self localisation strategy.
266 */
268 virtual public armarx::Component,
269 virtual public armarx::LaserScannerSelfLocalisationInterface
270 {
271 public:
273
274 /**
275 * @see armarx::ManagedIceObject::getDefaultName()
276 */
277 std::string
278 getDefaultName() const override
279 {
280 return "LaserScannerSelfLocalisation";
281 }
282
283 protected:
284 /**
285 * @see armarx::ManagedIceObject::onInitComponent()
286 */
287 void onInitComponent() override;
288
289 /**
290 * @see armarx::ManagedIceObject::onConnectComponent()
291 */
292 void onConnectComponent() override;
293
294 /**
295 * @see armarx::ManagedIceObject::onDisconnectComponent()
296 */
297 void onDisconnectComponent() override;
298
299 /**
300 * @see armarx::ManagedIceObject::onExitComponent()
301 */
302 void onExitComponent() override;
303
304 /**
305 * @see PropertyUser::createPropertyDefinitions()
306 */
308
309 // LaserScannerSelfLocalisationInterface interface
310 std::string getReportTopicName(const Ice::Current&) override;
311 void
312 setAbsolutePose(Ice::Float x, Ice::Float y, Ice::Float theta, const Ice::Current&) override;
313 LineSegment2DSeq getMap(const Ice::Current&) override;
314
315 // LaserScannerUnitListener interface
316 void reportSensorValues(const std::string& device,
317 const std::string& name,
318 const LaserScan& scan,
319 const TimestampBasePtr& timestamp,
320 const Ice::Current&) override;
321
322 // PlatformUnitListener interface
323 void reportPlatformVelocity(Ice::Float velX,
324 Ice::Float velY,
325 Ice::Float velTheta,
326 const Ice::Current&) override;
327 void reportPlatformOdometryPose(Ice::Float,
328 Ice::Float,
329 Ice::Float,
330 const Ice::Current&) override;
331
332 // Component interface
333 void componentPropertiesUpdated(const std::set<std::string>& changedProperties) override;
334
335 private:
336 void updateLocalisation();
337
338 void updateProperties(bool initial = false);
339
340 void resetKalmanFilter(const Eigen::Vector3f& pose);
341 Eigen::Vector3f filterPose(const Eigen::Vector3f& pose);
342 void writeLogFile();
343
344 private:
345 std::string reportTopicName;
346 std::string robotStateComponentName;
347 std::string platformName;
348 std::string laserScannerUnitName;
349 std::string workingMemoryName;
350 std::string longtermMemoryName;
351 std::string mapFilename;
352 std::string agentName;
353 std::string robotRootFrame;
354
355 std::string emergencyStopMasterName;
356 std::string debugObserverName;
357 float workingMemoryUpdateFrequency;
358 float longtermMemoryUpdateFrequency;
359 float robotPositionZ = 0.0f;
360 float maximalLaserScannerDelay = 0.1f;
361
362 std::mutex propertyMutex;
363 int propSmoothFrameSize;
364 int propSmoothMergeDistance;
365 float propMatchingMaxDistance;
366 float propMatchingMinPoints;
367 float propMatchingCorrectionFactor;
368 float propEdgeMaxDistance;
369 float propEdgeMaxDeltaAngle;
370 float propEdgePointAddingThreshold;
371 int propEdgeEpsilon;
372 int propEdgeMinPoints;
373 bool propReportPoints;
374 bool propReportEdges;
375 bool propUseOdometry;
376 bool propUseMapCorrection;
377 float propSensorStdDev;
378 float propVelSensorStdDev;
379 std::string propLoggingFilePath;
380 bool propRecordData = false;
381
382 std::atomic<bool> useOdometry;
383
384 std::vector<LineSegment2Df> map;
385
387 LaserScannerUnitInterfacePrx laserScannerUnit;
388 LaserScannerSelfLocalisationListenerPrx reportTopic;
389 PlatformUnitListenerPrx platformUnitTopic;
390
391 GlobalRobotPoseLocalizationListenerPrx globalRobotPoseTopic;
392
393 DebugObserverInterfacePrx debugObserver;
394 memoryx::WorkingMemoryInterfacePrx workingMemory;
395 memoryx::AgentInstancesSegmentBasePrx agentsMemory;
396 memoryx::AgentInstancePtr agentInstance;
397 bool updateWorkingMemory = false;
398 memoryx::LongtermMemoryInterfacePrx longtermMemory;
399 memoryx::PersistentEntitySegmentBasePrx selfLocalisationSegment;
400 std::string poseEntityId;
401
402 std::vector<LaserScanData> scanData;
403
404 std::mutex setPoseMutex;
405 std::optional<Eigen::Vector3f> setPose;
406
407 std::mutex odometryMutex;
408 std::vector<ReportedVelocity> reportedVelocities;
409 Eigen::Vector3f lastVelocity;
410 IceUtil::Time lastVelocityUpdate;
411
412 Eigen::Vector3f estimatedPose;
413
414 Eigen::Vector2f platformRectMin{0, 0};
415 Eigen::Vector2f platformRectMax{0, 0};
416
418 IceReportSkipper s;
419
421 std::mutex kalmanMutex;
422
423 // Filelogging
424 struct LaserScannerFileLoggingData
425 {
426 std::mutex loggingMutex;
427 std::string filePath;
428
429 std::map<IceUtil::Time, std::vector<LaserScanData>> scanDataHistory;
430 };
431
432 std::unique_ptr<LaserScannerFileLoggingData> laserScannerFileLoggingData;
433 };
434} // namespace armarx
std::string timestamp()
Default component property definition container.
Definition Component.h:70
ComponentPropertyDefinitions(std::string prefix, bool hasObjectNameParameter=true)
Definition Component.cpp:46
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition Component.h:94
void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
Implement this function if you would like to react to changes in the properties.
std::string getReportTopicName(const Ice::Current &) override
void reportPlatformVelocity(Ice::Float velX, Ice::Float velY, Ice::Float velTheta, const Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
LineSegment2DSeq getMap(const Ice::Current &) override
void reportPlatformOdometryPose(Ice::Float, Ice::Float, Ice::Float, const Ice::Current &) override
void setAbsolutePose(Ice::Float x, Ice::Float y, Ice::Float theta, const Ice::Current &) override
void reportSensorValues(const std::string &device, const std::string &name, const LaserScan &scan, const TimestampBasePtr &timestamp, const Ice::Current &) override
IceUtil::Handle< PeriodicTask< T > > pointer_type
Shared pointer type for convenience.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
IceInternal::Handle< AgentInstance > AgentInstancePtr
Typedef of AgentEntityPtr as IceInternal::Handle<AgentEntity> for convenience.
std::shared_ptr< PlatformKalmanFilter > PlatformKalmanFilterPtr
std::vector< Eigen::Vector2f > points
std::shared_ptr< std::mutex > mutex
std::vector< ExtractedEdge > edges