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 
28 #include <ArmarXCore/interface/components/EmergencyStopInterface.h>
29 
30 #include <RobotAPI/interface/units/LaserScannerUnit.h>
31 
32 #include <MemoryX/interface/components/LongtermMemoryInterface.h>
33 #include <MemoryX/interface/components/WorkingMemoryInterface.h>
34 #include <MemoryX/interface/memorytypes/MemorySegments.h>
39 
40 #include <RobotComponents/interface/components/LaserScannerSelfLocalisation.h>
41 
42 #include <Eigen/Eigen>
43 #include <optional>
44 #include <atomic>
45 
46 namespace armarx
47 {
49  {
50  Eigen::Vector2f start;
51  Eigen::Vector2f end;
52  };
53 
55  {
57  Eigen::Vector2f* pointsBegin;
58  Eigen::Vector2f* pointsEnd;
59  };
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", "LaserScannerSelfLocalisationTopic", "The name of the report topic.");
93  defineOptionalProperty<std::string>("RobotStateComponentName", "RobotStateComponent", "The name of the RobotStateComponent. Used to get local transformation of laser scanners");
94  defineOptionalProperty<std::string>("PlatformName", "Platform", "Name of the platform to use. This property is used to listen to the platform topic");
95  defineOptionalProperty<std::string>("LaserScannerUnitName", "LaserScannerSimulation", "Name of the laser scanner unit to use.");
96  defineOptionalProperty<std::string>("WorkingMemoryName", "WorkingMemory", "Name of the WorkingMemory that should be used");
97  defineOptionalProperty<std::string>("LongtermMemoryName", "LongtermMemory", "Name of the LongtermMemory component");
98  defineOptionalProperty<bool>("UpdateWorkingMemory", true, "Update the working memory with the corrected position (disable in simulation)");
99  defineOptionalProperty<std::string>("MapFilename", "RobotComponents/maps/building-5020-kitchen.json", "Floor map (2D) used for global localisation");
100  defineOptionalProperty<std::string>("AgentName", "", "Name of the agent instance. If empty, the robot name of the RobotStateComponent will be used");
101  defineOptionalProperty<std::string>("EmergencyStopMasterName", "EmergencyStopMaster", "The name used to register as an EmergencyStopMaster");
102  defineOptionalProperty<std::string>("DebugObserverName", "DebugObserver", "Name of the topic the DebugObserver listens on");
103 
104  defineOptionalProperty<int>("UpdatePeriodInMs", 5, "Update period used for the map localisation");
105  defineOptionalProperty<int>("UpdatePeriodWorkingMemoryInMs", 30, "Update period used for updating the working memory");
106  defineOptionalProperty<int>("UpdatePeriodLongtermMemoryInMs", 30, "Update period used for updating the longterm memory");
107  defineOptionalProperty<float>("RobotPositionZ", 0.0f, "The z-coordinate of the reported postion. Laser scanners can only self localize in x,y.");
108 
109  defineOptionalProperty<float>("MaximalLaserScannerDelay", 0.1, "If no new sensor values have been reported for this amound of seconds, we emit a soft emergency stop");
110 
111  defineOptionalProperty<int>("SmoothFrameSize", 7, "Frame size used for smoothing of laser scanner input", PropertyDefinitionBase::eModifiable);
112  defineOptionalProperty<int>("SmoothMergeDistance", 160, "Distance in mm up to which laser scanner points are merged", PropertyDefinitionBase::eModifiable);
113  defineOptionalProperty<float>("MatchingMaxDistance", 300.0f, "Maximal distance in mm up to which points are matched against edges of the map", PropertyDefinitionBase::eModifiable);
114  defineOptionalProperty<float>("MatchingMinPoints", 0.01f, "Minimum percentage of points which need to be matched (range [0, 1]). If less points are matched no global correction is applied.", PropertyDefinitionBase::eModifiable);
115  defineOptionalProperty<float>("MatchingCorrectionFactor", 0.01f, "This factor is used to apply the calculated map correction (range [0, 1])", PropertyDefinitionBase::eModifiable);
116  defineOptionalProperty<float>("EdgeMaxDistance", 600.0f, "Maximum distance between adjacent points up to which they are merged into one edge [mm]", PropertyDefinitionBase::eModifiable);
117  defineOptionalProperty<float>("EdgeMaxDeltaAngle", 0.10472f, "Maximum angle delta up to which adjacent points are merged into one edge [rad]", PropertyDefinitionBase::eModifiable);
118  defineOptionalProperty<float>("EdgePointAddingThreshold", 10.0f, "Maximum least square error up to which points are added to an edge (extension at the front and back)", PropertyDefinitionBase::eModifiable);
119  defineOptionalProperty<int>("EdgeEpsilon", 4, "Half frame size for line regression (angle calculation)", PropertyDefinitionBase::eModifiable);
120  defineOptionalProperty<int>("EdgeMinPoints", 30, "Minimum number of points per edge (no edges with less points will be extracted)", PropertyDefinitionBase::eModifiable);
121 
122  defineOptionalProperty<bool>("UseOdometry", true, "Enable or disable odometry for pose estimation", PropertyDefinitionBase::eModifiable);
123  defineOptionalProperty<bool>("UseMapCorrection", true, "Enable or disable map localisation for pose correction", PropertyDefinitionBase::eModifiable);
124  defineOptionalProperty<bool>("ReportPoints", false, "Enable or disable the reports of (post-processed) laser scan points", PropertyDefinitionBase::eModifiable);
125  defineOptionalProperty<bool>("ReportEdges", true, "Enable or disable the reports of extracted edges", PropertyDefinitionBase::eModifiable);
126 
127  defineOptionalProperty<float>("SensorStdDev", 100, "Standard deviation in position of the localization result", PropertyDefinitionBase::eModifiable);
128  defineOptionalProperty<float>("VelSensorStdDev", 0.1f, "Standard deviation of the reported velocity", PropertyDefinitionBase::eModifiable);
129 
130  defineOptionalProperty<std::string>("LoggingFilePath", "", "Path to sensor data log file", PropertyDefinitionBase::eModifiable);
131  defineOptionalProperty<bool>("RecordData", false, "If true, data is logged. Can be changed online. When set to false online, data is written to file. Otherwise on disconnect.", PropertyDefinitionBase::eModifiable);
132 
133  defineOptionalProperty<std::string>("PlatformRectangleMin", "0, 0", "Ignores points within the platform rectangle (this is the min x/y point)");
134  defineOptionalProperty<std::string>("PlatformRectangleMax", "0, 0", "Ignores points within the platform rectangle (this is the max x/y point)");
135 
136  }
137  };
138 
139  /**
140  * @defgroup Component-LaserScannerSelfLocalisation LaserScannerSelfLocalisation
141  * @ingroup RobotComponents-Components
142  * The component LaserScannerSelfLocalisation is responsible for self localisation of a
143  * platform in a predefined two dimensional map.
144  *
145  * The odometry is used as a primary source for determining the current position of the
146  * platform. Since this method leads to unbounded errors, we also use the laser scanners
147  * to correct the estimated position. This is done by matching the laser scan input to
148  * edges of a predefined map.
149  *
150  * This method requires a good estimate of the initial position at startup because the
151  * correction by the laser scans can only correct small errors.
152  *
153  *
154  * @class LaserScannerSelfLocalisation
155  * @ingroup Component-LaserScannerSelfLocalisation
156  * @brief The class LaserScannerSelfLocalisation implements a self localisation strategy.
157  */
159  virtual public armarx::Component,
160  virtual public armarx::LaserScannerSelfLocalisationInterface
161  {
162  public:
164 
165  /**
166  * @see armarx::ManagedIceObject::getDefaultName()
167  */
168  std::string getDefaultName() const override
169  {
170  return "LaserScannerSelfLocalisation";
171  }
172 
173  protected:
174  /**
175  * @see armarx::ManagedIceObject::onInitComponent()
176  */
177  void onInitComponent() override;
178 
179  /**
180  * @see armarx::ManagedIceObject::onConnectComponent()
181  */
182  void onConnectComponent() override;
183 
184  /**
185  * @see armarx::ManagedIceObject::onDisconnectComponent()
186  */
187  void onDisconnectComponent() override;
188 
189  /**
190  * @see armarx::ManagedIceObject::onExitComponent()
191  */
192  void onExitComponent() override;
193 
194  /**
195  * @see PropertyUser::createPropertyDefinitions()
196  */
198 
199  // LaserScannerSelfLocalisationInterface interface
200  std::string getReportTopicName(const Ice::Current&) override;
201  void setAbsolutePose(Ice::Float x, Ice::Float y, Ice::Float theta, const Ice::Current&) override;
202  LineSegment2DSeq getMap(const Ice::Current&) override;
203 
204  // LaserScannerUnitListener interface
205  void reportSensorValues(const std::string& device, const std::string& name, const LaserScan& scan,
206  const TimestampBasePtr& timestamp, const Ice::Current&) override;
207 
208  // PlatformUnitListener interface
209  void reportPlatformVelocity(Ice::Float velX, Ice::Float velY, Ice::Float velTheta, const Ice::Current&) override;
210  void reportPlatformOdometryPose(Ice::Float, Ice::Float, Ice::Float, const Ice::Current&) override;
211 
212  // Component interface
213  void componentPropertiesUpdated(const std::set<std::string>& changedProperties) override;
214 
215  private:
216  void updateLocalisation();
217 
218  void updateProperties(bool initial = false);
219 
220  void resetKalmanFilter(const Eigen::Vector3f& pose);
221  Eigen::Vector3f filterPose(const Eigen::Vector3f& pose);
222  void writeLogFile();
223  private:
224  std::string reportTopicName;
225  std::string robotStateComponentName;
226  std::string platformName;
227  std::string laserScannerUnitName;
228  std::string workingMemoryName;
229  std::string longtermMemoryName;
230  std::string mapFilename;
231  std::string agentName;
232  std::string robotRootFrame;
233 
234  std::string emergencyStopMasterName;
235  std::string debugObserverName;
236  float workingMemoryUpdateFrequency;
237  float longtermMemoryUpdateFrequency;
238  float robotPositionZ = 0.0f;
239  float maximalLaserScannerDelay = 0.1f;
240 
241  std::mutex propertyMutex;
242  int propSmoothFrameSize;
243  int propSmoothMergeDistance;
244  float propMatchingMaxDistance;
245  float propMatchingMinPoints;
246  float propMatchingCorrectionFactor;
247  float propEdgeMaxDistance;
248  float propEdgeMaxDeltaAngle;
249  float propEdgePointAddingThreshold;
250  int propEdgeEpsilon;
251  int propEdgeMinPoints;
252  bool propReportPoints;
253  bool propReportEdges;
254  bool propUseOdometry;
255  bool propUseMapCorrection;
256  float propSensorStdDev;
257  float propVelSensorStdDev;
258  std::string propLoggingFilePath;
259  bool propRecordData = false;
260 
261  std::atomic<bool> useOdometry;
262 
263  std::vector<LineSegment2Df> map;
264 
266  LaserScannerUnitInterfacePrx laserScannerUnit;
267  LaserScannerSelfLocalisationListenerPrx reportTopic;
268  PlatformUnitListenerPrx platformUnitTopic;
269 
270  GlobalRobotPoseLocalizationListenerPrx globalRobotPoseTopic;
271 
272  DebugObserverInterfacePrx debugObserver;
273  memoryx::WorkingMemoryInterfacePrx workingMemory;
274  memoryx::AgentInstancesSegmentBasePrx agentsMemory;
275  memoryx::AgentInstancePtr agentInstance;
276  bool updateWorkingMemory = false;
277  memoryx::LongtermMemoryInterfacePrx longtermMemory;
278  memoryx::PersistentEntitySegmentBasePrx selfLocalisationSegment;
279  std::string poseEntityId;
280 
281  std::vector<LaserScanData> scanData;
282 
283  std::mutex setPoseMutex;
284  std::optional<Eigen::Vector3f> setPose;
285 
286  std::mutex odometryMutex;
287  std::vector<ReportedVelocity> reportedVelocities;
288  Eigen::Vector3f lastVelocity;
289  IceUtil::Time lastVelocityUpdate;
290 
291  Eigen::Vector3f estimatedPose;
292 
293  Eigen::Vector2f platformRectMin{0, 0};
294  Eigen::Vector2f platformRectMax{0, 0};
295 
297  IceReportSkipper s;
298 
300  std::mutex kalmanMutex;
301 
302  // Filelogging
303  struct LaserScannerFileLoggingData
304  {
305  std::mutex loggingMutex;
306  std::string filePath;
307 
308  std::map<IceUtil::Time, std::vector<LaserScanData>> scanDataHistory;
309  };
310  std::unique_ptr<LaserScannerFileLoggingData> laserScannerFileLoggingData;
311 
312  };
313 }
armarx::LaserScanData::scan
LaserScan scan
Definition: LaserScannerSelfLocalisation.h:67
armarx::LineSegment2Df::end
Eigen::Vector2f end
Definition: LaserScannerSelfLocalisation.h:51
armarx::LaserScanData
Definition: LaserScannerSelfLocalisation.h:62
armarx::LaserScannerSelfLocalisation
The class LaserScannerSelfLocalisation implements a self localisation strategy.
Definition: LaserScannerSelfLocalisation.h:158
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:918
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
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:333
PeriodicTask.h
armarx::ReportedVelocity::x
float x
Definition: LaserScannerSelfLocalisation.h:76
armarx::LaserScannerSelfLocalisation::getDefaultName
std::string getDefaultName() const override
Definition: LaserScannerSelfLocalisation.h:168
armarx::ExtractedEdge::pointsEnd
Eigen::Vector2f * pointsEnd
Definition: LaserScannerSelfLocalisation.h:58
armarx::LaserScannerSelfLocalisation::onDisconnectComponent
void onDisconnectComponent() override
Definition: LaserScannerSelfLocalisation.cpp:512
armarx::LaserScannerSelfLocalisationPropertyDefinitions
Definition: LaserScannerSelfLocalisation.h:85
armarx::ReportedVelocity::dt
float dt
Definition: LaserScannerSelfLocalisation.h:75
armarx::LineSegment2Df::start
Eigen::Vector2f start
Definition: LaserScannerSelfLocalisation.h:50
armarx::PeriodicTask::pointer_type
IceUtil::Handle< PeriodicTask< T > > pointer_type
Shared pointer type for convenience.
Definition: PeriodicTask.h:67
armarx::LaserScannerSelfLocalisation::LaserScannerSelfLocalisation
LaserScannerSelfLocalisation()
Definition: LaserScannerSelfLocalisation.cpp:362
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:1326
armarx::LaserScannerSelfLocalisation::setAbsolutePose
void setAbsolutePose(Ice::Float x, Ice::Float y, Ice::Float theta, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:543
PlatformKalmanFilter.h
armarx::ReportedVelocity
Definition: LaserScannerSelfLocalisation.h:73
IceInternal::Handle< AgentInstance >
armarx::PropertyUser::updateProperties
void updateProperties()
Definition: PropertyUser.cpp:154
armarx::LineSegment2Df
Definition: LaserScannerSelfLocalisation.h:48
armarx::LaserScannerSelfLocalisation::reportPlatformVelocity
void reportPlatformVelocity(Ice::Float velX, Ice::Float velY, Ice::Float velTheta, const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:592
armarx::LaserScannerSelfLocalisation::getReportTopicName
std::string getReportTopicName(const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:538
armarx::LaserScannerSelfLocalisation::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: LaserScannerSelfLocalisation.cpp:528
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:95
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:553
armarx::LaserScannerSelfLocalisation::onExitComponent
void onExitComponent() override
Definition: LaserScannerSelfLocalisation.cpp:523
memoryx::PlatformKalmanFilterPtr
std::shared_ptr< PlatformKalmanFilter > PlatformKalmanFilterPtr
Definition: PlatformKalmanFilter.h:98
armarx::ReportedVelocity::y
float y
Definition: LaserScannerSelfLocalisation.h:77
armarx::ExtractedEdge::pointsBegin
Eigen::Vector2f * pointsBegin
Definition: LaserScannerSelfLocalisation.h:57
armarx::LaserScannerSelfLocalisation::onInitComponent
void onInitComponent() override
Definition: LaserScannerSelfLocalisation.cpp:367
SimpleEntity.h
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
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:615
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:407
armarx::ExtractedEdge::segment
LineSegment2Df segment
Definition: LaserScannerSelfLocalisation.h:56
armarx::ExtractedEdge
Definition: LaserScannerSelfLocalisation.h:54
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::LaserScannerSelfLocalisation::getMap
LineSegment2DSeq getMap(const Ice::Current &) override
Definition: LaserScannerSelfLocalisation.cpp:1313