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 
47 namespace 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  {
65  LaserScannerInfo info;
66  std::shared_ptr<std::mutex> mutex;
67  LaserScan scan;
68  std::vector<Eigen::Vector2f> points;
69  std::vector<ExtractedEdge> edges;
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  {
92  defineOptionalProperty<std::string>("ReportTopicName",
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");
99  defineOptionalProperty<std::string>("PlatformName",
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");
109  defineOptionalProperty<std::string>(
110  "LongtermMemoryName", "LongtermMemory", "Name of the LongtermMemory component");
111  defineOptionalProperty<bool>(
112  "UpdateWorkingMemory",
113  true,
114  "Update the working memory with the corrected position (disable in simulation)");
115  defineOptionalProperty<std::string>("MapFilename",
116  "RobotComponents/maps/building-5020-kitchen.json",
117  "Floor map (2D) used for global localisation");
118  defineOptionalProperty<std::string>("AgentName",
119  "",
120  "Name of the agent instance. If empty, the robot "
121  "name of the RobotStateComponent will be used");
122  defineOptionalProperty<std::string>(
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 
130  defineOptionalProperty<int>(
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",
152  defineOptionalProperty<int>(
153  "SmoothMergeDistance",
154  160,
155  "Distance in mm up to which laser scanner points are merged",
157  defineOptionalProperty<float>(
158  "MatchingMaxDistance",
159  300.0f,
160  "Maximal distance in mm up to which points are matched against edges of the map",
162  defineOptionalProperty<float>(
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.",
168  defineOptionalProperty<float>(
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]",
178  defineOptionalProperty<float>(
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)",
192  defineOptionalProperty<int>(
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",
206  defineOptionalProperty<bool>(
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 
216  defineOptionalProperty<float>(
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",
230  defineOptionalProperty<bool>(
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 
237  defineOptionalProperty<std::string>(
238  "PlatformRectangleMin",
239  "0, 0",
240  "Ignores points within the platform rectangle (this is the min x/y point)");
241  defineOptionalProperty<std::string>(
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
324  Ice::Float velY,
325  Ice::Float velTheta,
326  const Ice::Current&) override;
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
armarx::LaserScanData::scan
LaserScan scan
Definition: LaserScannerSelfLocalisation.h:67
armarx::LineSegment2Df::end
Eigen::Vector2f end
Definition: LaserScannerSelfLocalisation.h:52
armarx::LaserScanData
Definition: LaserScannerSelfLocalisation.h:62
armarx::LaserScannerSelfLocalisation
The class LaserScannerSelfLocalisation implements a self localisation strategy.
Definition: LaserScannerSelfLocalisation.h:267
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
armarx::LaserScanData::mutex
std::shared_ptr< std::mutex > mutex
Definition: LaserScannerSelfLocalisation.h:66
armarx::LaserScanData::points
std::vector< Eigen::Vector2f > points
Definition: LaserScannerSelfLocalisation.h:68
armarx::LaserScannerSelfLocalisationPropertyDefinitions::LaserScannerSelfLocalisationPropertyDefinitions
LaserScannerSelfLocalisationPropertyDefinitions(std::string prefix)
Definition: LaserScannerSelfLocalisation.h:89
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::LaserScanData::info
LaserScannerInfo info
Definition: LaserScannerSelfLocalisation.h:65
armarx::PropertyDefinitionContainer::prefix
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
Definition: PropertyDefinitionContainer.h:345
PeriodicTask.h
armarx::ReportedVelocity::x
float x
Definition: LaserScannerSelfLocalisation.h:76
armarx::LaserScannerSelfLocalisation::getDefaultName
std::string getDefaultName() const override
Definition: LaserScannerSelfLocalisation.h:278
armarx::ExtractedEdge::pointsEnd
Eigen::Vector2f * pointsEnd
Definition: LaserScannerSelfLocalisation.h:59
armarx::LaserScannerSelfLocalisation::onDisconnectComponent
void onDisconnectComponent() override
Definition: LaserScannerSelfLocalisation.cpp:527
armarx::LaserScannerSelfLocalisationPropertyDefinitions
Definition: LaserScannerSelfLocalisation.h:85
armarx::ReportedVelocity::dt
float dt
Definition: LaserScannerSelfLocalisation.h:75
armarx::LineSegment2Df::start
Eigen::Vector2f start
Definition: LaserScannerSelfLocalisation.h:51
armarx::PeriodicTask::pointer_type
IceUtil::Handle< PeriodicTask< T > > pointer_type
Shared pointer type for convenience.
Definition: PeriodicTask.h:68
armarx::LaserScannerSelfLocalisation::LaserScannerSelfLocalisation
LaserScannerSelfLocalisation()
Definition: LaserScannerSelfLocalisation.cpp:369
armarx::LaserScannerSelfLocalisation::componentPropertiesUpdated
void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
Implement this function if you would like to react to changes in the properties.
Definition: LaserScannerSelfLocalisation.cpp:1368
armarx::LaserScannerSelfLocalisation::setAbsolutePose
void setAbsolutePose(Ice::Float x, Ice::Float y, Ice::Float theta, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:560
PlatformKalmanFilter.h
armarx::ReportedVelocity
Definition: LaserScannerSelfLocalisation.h:73
IceInternal::Handle< AgentInstance >
armarx::PropertyUser::updateProperties
void updateProperties()
Definition: PropertyUser.cpp:151
armarx::LineSegment2Df
Definition: LaserScannerSelfLocalisation.h:49
armarx::LaserScannerSelfLocalisation::reportPlatformVelocity
void reportPlatformVelocity(Ice::Float velX, Ice::Float velY, Ice::Float velTheta, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:618
armarx::LaserScannerSelfLocalisation::getReportTopicName
std::string getReportTopicName(const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:554
armarx::LaserScannerSelfLocalisation::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: LaserScannerSelfLocalisation.cpp:543
IceReportSkipper.h
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
Component.h
armarx::Component
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition: Component.h:91
KalmanFilter.h
armarx::LaserScannerSelfLocalisation::reportSensorValues
void reportSensorValues(const std::string &device, const std::string &name, const LaserScan &scan, const TimestampBasePtr &timestamp, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:573
armarx::LaserScannerSelfLocalisation::onExitComponent
void onExitComponent() override
Definition: LaserScannerSelfLocalisation.cpp:538
memoryx::PlatformKalmanFilterPtr
std::shared_ptr< PlatformKalmanFilter > PlatformKalmanFilterPtr
Definition: PlatformKalmanFilter.h:104
armarx::ReportedVelocity::y
float y
Definition: LaserScannerSelfLocalisation.h:77
armarx::ExtractedEdge::pointsBegin
Eigen::Vector2f * pointsBegin
Definition: LaserScannerSelfLocalisation.h:58
armarx::LaserScannerSelfLocalisation::onInitComponent
void onInitComponent() override
Definition: LaserScannerSelfLocalisation.cpp:375
SimpleEntity.h
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::LaserScanData::measurementTime
IceUtil::Time measurementTime
Definition: LaserScannerSelfLocalisation.h:70
IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface >
AgentInstance.h
armarx::ReportedVelocity::theta
float theta
Definition: LaserScannerSelfLocalisation.h:78
armarx::LaserScannerSelfLocalisation::reportPlatformOdometryPose
void reportPlatformOdometryPose(Ice::Float, Ice::Float, Ice::Float, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:642
armarx::LaserScanData::pose
Eigen::Matrix4f pose
Definition: LaserScannerSelfLocalisation.h:64
armarx::LaserScanData::edges
std::vector< ExtractedEdge > edges
Definition: LaserScannerSelfLocalisation.h:69
armarx::PropertyDefinitionBase::eModifiable
@ eModifiable
Definition: PropertyDefinitionInterface.h:57
armarx::LaserScannerSelfLocalisation::onConnectComponent
void onConnectComponent() override
Definition: LaserScannerSelfLocalisation.cpp:416
armarx::ExtractedEdge::segment
LineSegment2Df segment
Definition: LaserScannerSelfLocalisation.h:57
armarx::ExtractedEdge
Definition: LaserScannerSelfLocalisation.h:55
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::LaserScannerSelfLocalisation::getMap
LineSegment2DSeq getMap(const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:1355