From ae9dd08e4a755f4468bb1d38e7590bfbbe564b99 Mon Sep 17 00:00:00 2001 From: Niklas Yann Wettengel <niyawe@uni-koblenz.de> Date: Fri, 27 Nov 2015 15:30:19 +0100 Subject: [PATCH] Trimmed the branch to only the homer_map_manager sub directory --- .../CHANGELOG.rst => CHANGELOG.rst | 0 .../CMakeLists.txt => CMakeLists.txt | 0 README.md | 279 +--- .../config => config}/custom.xml | 0 .../config => config}/default.xml | 0 .../config => config}/merged.xml | 0 homer_map_manager/README.md | 42 - homer_mapnav_msgs/CHANGELOG.rst | 27 - homer_mapnav_msgs/CMakeLists.txt | 33 - homer_mapnav_msgs/README.md | 244 --- homer_mapnav_msgs/mainpage.dox | 14 - homer_mapnav_msgs/manifest.xml | 16 - .../msg/DeletePointOfInterest.msg | 1 - homer_mapnav_msgs/msg/DoMapping.msg | 1 - homer_mapnav_msgs/msg/MapLayers.msg | 7 - homer_mapnav_msgs/msg/ModifyMap.msg | 17 - homer_mapnav_msgs/msg/ModifyPOI.msg | 2 - homer_mapnav_msgs/msg/NavigateToPOI.msg | 3 - homer_mapnav_msgs/msg/PointOfInterest.msg | 13 - homer_mapnav_msgs/msg/PointsOfInterest.msg | 1 - homer_mapnav_msgs/msg/RegionOfInterest.msg | 12 - homer_mapnav_msgs/msg/RegionsOfInterest.msg | 1 - homer_mapnav_msgs/msg/StartNavigation.msg | 4 - homer_mapnav_msgs/msg/StopNavigation.msg | 0 homer_mapnav_msgs/msg/TargetUnreachable.msg | 9 - homer_mapnav_msgs/package.xml | 27 - homer_mapnav_msgs/readme.pdf | Bin 121801 -> 0 bytes homer_mapnav_msgs/srv/GetPointsOfInterest.srv | 2 - .../srv/GetRegionsOfInterest.srv | 2 - homer_mapnav_msgs/srv/LoadMap.srv | 2 - homer_mapnav_msgs/srv/SaveMap.srv | 2 - homer_mapping/CHANGELOG.rst | 28 - homer_mapping/CMakeLists.txt | 44 - homer_mapping/README.md | 67 - homer_mapping/config/homer_mapping.yaml | 30 - .../config/homer_mapping_followme.yaml | 8 - homer_mapping/launch/homer_mapping.launch | 5 - .../launch/homer_mapping_followme.launch | 5 - homer_mapping/launch/homer_mapping_ros.launch | 5 - .../launch/homer_mapping_rviz.launch | 6 - homer_mapping/mainpage.dox | 26 - homer_mapping/manifest.xml | 23 - homer_mapping/package.xml | 38 - homer_mapping/readme.pdf | Bin 113506 -> 0 bytes homer_mapping/src/CMakeLists.txt | 2 - homer_mapping/src/OccupancyMap/CMakeLists.txt | 31 - homer_mapping/src/OccupancyMap/Math/Box2D.h | 184 --- .../src/OccupancyMap/Math/CMakeLists.txt | 17 - .../src/OccupancyMap/Math/Circle2D.cpp | 84 - .../src/OccupancyMap/Math/Circle2D.h | 53 - .../src/OccupancyMap/Math/Homography.cpp | 109 -- .../src/OccupancyMap/Math/Homography.h | 49 - .../src/OccupancyMap/Math/Line2D.cpp | 99 -- homer_mapping/src/OccupancyMap/Math/Line2D.h | 223 --- homer_mapping/src/OccupancyMap/Math/Math.cpp | 135 -- homer_mapping/src/OccupancyMap/Math/Math.h | 129 -- .../src/OccupancyMap/Math/Matrix.cpp | 23 - homer_mapping/src/OccupancyMap/Math/Matrix.h | 116 -- homer_mapping/src/OccupancyMap/Math/Obb2D.cpp | 149 -- homer_mapping/src/OccupancyMap/Math/Obb2D.h | 33 - homer_mapping/src/OccupancyMap/Math/Pixel.h | 59 - .../src/OccupancyMap/Math/Point2D.cpp | 33 - homer_mapping/src/OccupancyMap/Math/Point2D.h | 312 ---- .../src/OccupancyMap/Math/Polygon2D.cpp | 131 -- .../src/OccupancyMap/Math/Polygon2D.h | 76 - homer_mapping/src/OccupancyMap/Math/Pose.cpp | 117 -- homer_mapping/src/OccupancyMap/Math/Pose.h | 74 - .../OccupancyMap/Math/Transformation2D.cpp | 308 ---- .../src/OccupancyMap/Math/Transformation2D.h | 144 -- .../src/OccupancyMap/Math/Vector3D.cpp | 58 - .../src/OccupancyMap/Math/Vector3D.h | 82 - homer_mapping/src/OccupancyMap/Math/mat2.h | 77 - .../src/OccupancyMap/Math/mat2_inl.h | 86 - homer_mapping/src/OccupancyMap/Math/mat3.cpp | 189 --- homer_mapping/src/OccupancyMap/Math/mat3.h | 76 - homer_mapping/src/OccupancyMap/Math/mat3.inl | 44 - homer_mapping/src/OccupancyMap/Math/misc.cpp | 390 ----- homer_mapping/src/OccupancyMap/Math/misc.h | 32 - homer_mapping/src/OccupancyMap/Math/vec2.h | 189 --- .../src/OccupancyMap/Math/vec3_inl.h | 179 --- .../src/OccupancyMap/OccupancyMap.cpp | 931 ----------- homer_mapping/src/OccupancyMap/OccupancyMap.h | 379 ----- .../src/ParticleFilter/CMakeLists.txt | 18 - .../src/ParticleFilter/HyperSlamFilter.cpp | 191 --- .../src/ParticleFilter/HyperSlamFilter.h | 163 -- homer_mapping/src/ParticleFilter/Particle.cpp | 10 - homer_mapping/src/ParticleFilter/Particle.h | 64 - .../src/ParticleFilter/ParticleFilter.h | 310 ---- .../src/ParticleFilter/SlamFilter.cpp | 653 -------- homer_mapping/src/ParticleFilter/SlamFilter.h | 314 ---- .../src/ParticleFilter/SlamParticle.cpp | 30 - .../src/ParticleFilter/SlamParticle.h | 72 - homer_mapping/src/slam_node.cpp | 318 ---- homer_mapping/src/slam_node.h | 186 --- homer_nav_libs/CHANGELOG.rst | 38 - homer_nav_libs/CMakeLists.txt | 28 - homer_nav_libs/README.md | 13 - homer_nav_libs/package.xml | 32 - homer_nav_libs/readme.pdf | Bin 79468 -> 0 bytes homer_nav_libs/src/Explorer/CMakeLists.txt | 5 - homer_nav_libs/src/Explorer/Explorer.cpp | 1426 ----------------- homer_nav_libs/src/Explorer/Explorer.h | 355 ---- homer_nav_libs/src/Explorer/GridMap.h | 575 ------- homer_nav_libs/src/Math/Box2D.h | 184 --- homer_nav_libs/src/Math/CMakeLists.txt | 9 - homer_nav_libs/src/Math/Line2D.cpp | 99 -- homer_nav_libs/src/Math/Line2D.h | 223 --- homer_nav_libs/src/Math/Math.cpp | 135 -- homer_nav_libs/src/Math/Math.h | 129 -- homer_nav_libs/src/Math/Pixel.h | 59 - homer_nav_libs/src/Math/Point2D.cpp | 33 - homer_nav_libs/src/Math/Point2D.h | 312 ---- homer_nav_libs/src/Math/Pose.cpp | 117 -- homer_nav_libs/src/Math/Pose.h | 74 - homer_nav_libs/src/Math/Transformation2D.cpp | 308 ---- homer_nav_libs/src/Math/Transformation2D.h | 144 -- homer_nav_libs/src/Math/mat2.h | 77 - homer_nav_libs/src/Math/mat2_inl.h | 86 - homer_nav_libs/src/Math/vec2.h | 189 --- .../src/SpeedControl/CMakeLists.txt | 5 - .../src/SpeedControl/SpeedControl.cpp | 177 -- .../src/SpeedControl/SpeedControl.h | 71 - homer_nav_libs/src/tools/loadRosConfig.h | 46 - homer_nav_libs/src/tools/tools.h | 258 --- homer_navigation/CHANGELOG.rst | 34 - homer_navigation/CMakeLists.txt | 28 - homer_navigation/README.md | 79 - homer_navigation/config/homer_navigation.yaml | 48 - .../config/homer_navigation_followme.yaml | 14 - .../homer_navigation/homer_navigation_node.h | 372 ----- .../launch/homer_navigation.launch | 4 - .../launch/homer_navigation_followme.launch | 4 - .../launch/homer_navigation_ros.launch | 6 - homer_navigation/package.xml | 42 - homer_navigation/readme.pdf | Bin 118724 -> 0 bytes .../src/homer_navigation_node.cpp | 1069 ------------ .../images => images}/rosgraph.png | Bin .../images => images}/rosgraph.svg | 0 .../mainpage.dox => mainpage.dox | 0 .../manifest.xml => manifest.xml | 0 homer_map_manager/package.xml => package.xml | 0 homer_map_manager/readme.pdf => readme.pdf | Bin .../src => src}/Managers/CMakeLists.txt | 0 .../src => src}/Managers/MapManager.cpp | 0 .../src => src}/Managers/MapManager.h | 0 .../src => src}/Managers/MaskingManager.cpp | 0 .../src => src}/Managers/MaskingManager.h | 0 .../src => src}/Managers/PoiManager.cpp | 0 .../src => src}/Managers/PoiManager.h | 0 .../src => src}/Managers/RoiManager.cpp | 0 .../src => src}/Managers/RoiManager.h | 0 .../src => src}/MapIO/CMakeLists.txt | 0 .../src => src}/MapIO/image_loader.cpp | 0 .../src => src}/MapIO/image_loader.h | 0 .../src => src}/MapIO/map_loader.cpp | 0 .../src => src}/MapIO/map_loader.h | 0 .../src => src}/MapIO/map_saver.cpp | 0 .../src => src}/MapIO/map_saver.h | 0 .../Workers/PointOfInterest/CMakeLists.txt | 0 .../Workers/PointOfInterest/PointOfInterest.h | 0 {homer_map_manager/src => src}/main.cpp | 0 .../src => src}/map_manager_node.cpp | 0 .../src => src}/map_manager_node.h | 0 tracks.yaml | 23 - 164 files changed, 42 insertions(+), 15665 deletions(-) rename homer_map_manager/CHANGELOG.rst => CHANGELOG.rst (100%) rename homer_map_manager/CMakeLists.txt => CMakeLists.txt (100%) rename {homer_map_manager/config => config}/custom.xml (100%) rename {homer_map_manager/config => config}/default.xml (100%) rename {homer_map_manager/config => config}/merged.xml (100%) delete mode 100644 homer_map_manager/README.md delete mode 100644 homer_mapnav_msgs/CHANGELOG.rst delete mode 100644 homer_mapnav_msgs/CMakeLists.txt delete mode 100644 homer_mapnav_msgs/README.md delete mode 100644 homer_mapnav_msgs/mainpage.dox delete mode 100644 homer_mapnav_msgs/manifest.xml delete mode 100644 homer_mapnav_msgs/msg/DeletePointOfInterest.msg delete mode 100644 homer_mapnav_msgs/msg/DoMapping.msg delete mode 100644 homer_mapnav_msgs/msg/MapLayers.msg delete mode 100644 homer_mapnav_msgs/msg/ModifyMap.msg delete mode 100644 homer_mapnav_msgs/msg/ModifyPOI.msg delete mode 100644 homer_mapnav_msgs/msg/NavigateToPOI.msg delete mode 100644 homer_mapnav_msgs/msg/PointOfInterest.msg delete mode 100644 homer_mapnav_msgs/msg/PointsOfInterest.msg delete mode 100644 homer_mapnav_msgs/msg/RegionOfInterest.msg delete mode 100644 homer_mapnav_msgs/msg/RegionsOfInterest.msg delete mode 100644 homer_mapnav_msgs/msg/StartNavigation.msg delete mode 100644 homer_mapnav_msgs/msg/StopNavigation.msg delete mode 100644 homer_mapnav_msgs/msg/TargetUnreachable.msg delete mode 100644 homer_mapnav_msgs/package.xml delete mode 100644 homer_mapnav_msgs/readme.pdf delete mode 100644 homer_mapnav_msgs/srv/GetPointsOfInterest.srv delete mode 100644 homer_mapnav_msgs/srv/GetRegionsOfInterest.srv delete mode 100644 homer_mapnav_msgs/srv/LoadMap.srv delete mode 100644 homer_mapnav_msgs/srv/SaveMap.srv delete mode 100644 homer_mapping/CHANGELOG.rst delete mode 100644 homer_mapping/CMakeLists.txt delete mode 100644 homer_mapping/README.md delete mode 100644 homer_mapping/config/homer_mapping.yaml delete mode 100644 homer_mapping/config/homer_mapping_followme.yaml delete mode 100644 homer_mapping/launch/homer_mapping.launch delete mode 100644 homer_mapping/launch/homer_mapping_followme.launch delete mode 100644 homer_mapping/launch/homer_mapping_ros.launch delete mode 100644 homer_mapping/launch/homer_mapping_rviz.launch delete mode 100644 homer_mapping/mainpage.dox delete mode 100644 homer_mapping/manifest.xml delete mode 100644 homer_mapping/package.xml delete mode 100644 homer_mapping/readme.pdf delete mode 100644 homer_mapping/src/CMakeLists.txt delete mode 100644 homer_mapping/src/OccupancyMap/CMakeLists.txt delete mode 100644 homer_mapping/src/OccupancyMap/Math/Box2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/CMakeLists.txt delete mode 100644 homer_mapping/src/OccupancyMap/Math/Circle2D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Circle2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Homography.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Homography.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Line2D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Line2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Math.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Math.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Matrix.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Matrix.h delete mode 100755 homer_mapping/src/OccupancyMap/Math/Obb2D.cpp delete mode 100755 homer_mapping/src/OccupancyMap/Math/Obb2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Pixel.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Point2D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Point2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Polygon2D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Polygon2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Pose.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Pose.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Transformation2D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Transformation2D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/Vector3D.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/Vector3D.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/mat2.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/mat2_inl.h delete mode 100755 homer_mapping/src/OccupancyMap/Math/mat3.cpp delete mode 100755 homer_mapping/src/OccupancyMap/Math/mat3.h delete mode 100755 homer_mapping/src/OccupancyMap/Math/mat3.inl delete mode 100644 homer_mapping/src/OccupancyMap/Math/misc.cpp delete mode 100644 homer_mapping/src/OccupancyMap/Math/misc.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/vec2.h delete mode 100644 homer_mapping/src/OccupancyMap/Math/vec3_inl.h delete mode 100644 homer_mapping/src/OccupancyMap/OccupancyMap.cpp delete mode 100644 homer_mapping/src/OccupancyMap/OccupancyMap.h delete mode 100644 homer_mapping/src/ParticleFilter/CMakeLists.txt delete mode 100755 homer_mapping/src/ParticleFilter/HyperSlamFilter.cpp delete mode 100755 homer_mapping/src/ParticleFilter/HyperSlamFilter.h delete mode 100644 homer_mapping/src/ParticleFilter/Particle.cpp delete mode 100644 homer_mapping/src/ParticleFilter/Particle.h delete mode 100644 homer_mapping/src/ParticleFilter/ParticleFilter.h delete mode 100644 homer_mapping/src/ParticleFilter/SlamFilter.cpp delete mode 100644 homer_mapping/src/ParticleFilter/SlamFilter.h delete mode 100644 homer_mapping/src/ParticleFilter/SlamParticle.cpp delete mode 100644 homer_mapping/src/ParticleFilter/SlamParticle.h delete mode 100644 homer_mapping/src/slam_node.cpp delete mode 100644 homer_mapping/src/slam_node.h delete mode 100644 homer_nav_libs/CHANGELOG.rst delete mode 100644 homer_nav_libs/CMakeLists.txt delete mode 100644 homer_nav_libs/README.md delete mode 100644 homer_nav_libs/package.xml delete mode 100644 homer_nav_libs/readme.pdf delete mode 100644 homer_nav_libs/src/Explorer/CMakeLists.txt delete mode 100644 homer_nav_libs/src/Explorer/Explorer.cpp delete mode 100644 homer_nav_libs/src/Explorer/Explorer.h delete mode 100644 homer_nav_libs/src/Explorer/GridMap.h delete mode 100644 homer_nav_libs/src/Math/Box2D.h delete mode 100644 homer_nav_libs/src/Math/CMakeLists.txt delete mode 100644 homer_nav_libs/src/Math/Line2D.cpp delete mode 100644 homer_nav_libs/src/Math/Line2D.h delete mode 100644 homer_nav_libs/src/Math/Math.cpp delete mode 100644 homer_nav_libs/src/Math/Math.h delete mode 100644 homer_nav_libs/src/Math/Pixel.h delete mode 100644 homer_nav_libs/src/Math/Point2D.cpp delete mode 100644 homer_nav_libs/src/Math/Point2D.h delete mode 100644 homer_nav_libs/src/Math/Pose.cpp delete mode 100644 homer_nav_libs/src/Math/Pose.h delete mode 100644 homer_nav_libs/src/Math/Transformation2D.cpp delete mode 100644 homer_nav_libs/src/Math/Transformation2D.h delete mode 100644 homer_nav_libs/src/Math/mat2.h delete mode 100644 homer_nav_libs/src/Math/mat2_inl.h delete mode 100644 homer_nav_libs/src/Math/vec2.h delete mode 100644 homer_nav_libs/src/SpeedControl/CMakeLists.txt delete mode 100644 homer_nav_libs/src/SpeedControl/SpeedControl.cpp delete mode 100644 homer_nav_libs/src/SpeedControl/SpeedControl.h delete mode 100644 homer_nav_libs/src/tools/loadRosConfig.h delete mode 100644 homer_nav_libs/src/tools/tools.h delete mode 100644 homer_navigation/CHANGELOG.rst delete mode 100644 homer_navigation/CMakeLists.txt delete mode 100644 homer_navigation/README.md delete mode 100644 homer_navigation/config/homer_navigation.yaml delete mode 100644 homer_navigation/config/homer_navigation_followme.yaml delete mode 100644 homer_navigation/include/homer_navigation/homer_navigation_node.h delete mode 100644 homer_navigation/launch/homer_navigation.launch delete mode 100644 homer_navigation/launch/homer_navigation_followme.launch delete mode 100644 homer_navigation/launch/homer_navigation_ros.launch delete mode 100644 homer_navigation/package.xml delete mode 100644 homer_navigation/readme.pdf delete mode 100644 homer_navigation/src/homer_navigation_node.cpp rename {homer_map_manager/images => images}/rosgraph.png (100%) rename {homer_map_manager/images => images}/rosgraph.svg (100%) rename homer_map_manager/mainpage.dox => mainpage.dox (100%) rename homer_map_manager/manifest.xml => manifest.xml (100%) rename homer_map_manager/package.xml => package.xml (100%) rename homer_map_manager/readme.pdf => readme.pdf (100%) rename {homer_map_manager/src => src}/Managers/CMakeLists.txt (100%) rename {homer_map_manager/src => src}/Managers/MapManager.cpp (100%) rename {homer_map_manager/src => src}/Managers/MapManager.h (100%) rename {homer_map_manager/src => src}/Managers/MaskingManager.cpp (100%) rename {homer_map_manager/src => src}/Managers/MaskingManager.h (100%) rename {homer_map_manager/src => src}/Managers/PoiManager.cpp (100%) rename {homer_map_manager/src => src}/Managers/PoiManager.h (100%) rename {homer_map_manager/src => src}/Managers/RoiManager.cpp (100%) rename {homer_map_manager/src => src}/Managers/RoiManager.h (100%) rename {homer_map_manager/src => src}/MapIO/CMakeLists.txt (100%) rename {homer_map_manager/src => src}/MapIO/image_loader.cpp (100%) rename {homer_map_manager/src => src}/MapIO/image_loader.h (100%) rename {homer_map_manager/src => src}/MapIO/map_loader.cpp (100%) rename {homer_map_manager/src => src}/MapIO/map_loader.h (100%) rename {homer_map_manager/src => src}/MapIO/map_saver.cpp (100%) rename {homer_map_manager/src => src}/MapIO/map_saver.h (100%) rename {homer_map_manager/src => src}/Workers/PointOfInterest/CMakeLists.txt (100%) rename {homer_map_manager/src => src}/Workers/PointOfInterest/PointOfInterest.h (100%) rename {homer_map_manager/src => src}/main.cpp (100%) rename {homer_map_manager/src => src}/map_manager_node.cpp (100%) rename {homer_map_manager/src => src}/map_manager_node.h (100%) delete mode 100644 tracks.yaml diff --git a/homer_map_manager/CHANGELOG.rst b/CHANGELOG.rst similarity index 100% rename from homer_map_manager/CHANGELOG.rst rename to CHANGELOG.rst diff --git a/homer_map_manager/CMakeLists.txt b/CMakeLists.txt similarity index 100% rename from homer_map_manager/CMakeLists.txt rename to CMakeLists.txt diff --git a/README.md b/README.md index 6aa979d3..39a46914 100644 --- a/README.md +++ b/README.md @@ -1,237 +1,42 @@ -## homer_mapnav (indigo) - 1.0.5-0 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav` on `Tue, 24 Nov 2015 13:28:24 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.4-0` -- old version: `1.0.4-0` -- new version: `1.0.5-0` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.4-0 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav` on `Fri, 20 Nov 2015 02:07:32 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.2-0` -- old version: `1.0.2-0` -- new version: `1.0.4-0` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.2-0 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav` on `Fri, 20 Nov 2015 00:10:16 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-5` -- old version: `1.0.1-5` -- new version: `1.0.2-0` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.1-5 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Tue, 17 Nov 2015 15:51:44 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-2` -- old version: `1.0.1-4` -- new version: `1.0.1-5` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.1-4 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Tue, 17 Nov 2015 15:42:59 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-2` -- old version: `1.0.1-3` -- new version: `1.0.1-4` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.1-3 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Tue, 17 Nov 2015 15:29:03 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-2` -- old version: `1.0.1-2` -- new version: `1.0.1-3` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.10` -- rosdep version: `0.11.4` -- rosdistro version: `0.4.2` -- vcstools version: `0.1.38` - - -## homer_mapnav (indigo) - 1.0.1-2 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Fri, 09 Oct 2015 09:48:20 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-1` -- old version: `1.0.1-1` -- new version: `1.0.1-2` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.7` -- rosdep version: `0.11.1` -- rosdistro version: `0.4.1` -- vcstools version: `0.1.36` - - -## homer_mapnav (indigo) - 1.0.1-1 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Fri, 25 Sep 2015 06:07:06 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- rosdistro version: `1.0.1-0` -- old version: `1.0.1-0` -- new version: `1.0.1-1` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.7` -- rosdep version: `0.11.1` -- rosdistro version: `0.4.1` -- vcstools version: `0.1.36` - - -## homer_mapnav (indigo) - 1.0.1-0 - -The packages in the `homer_mapnav` repository were released into the `indigo` distro by running `/usr/bin/bloom-release --rosdistro indigo --track indigo homer_mapnav --edit` on `Tue, 15 Sep 2015 09:11:11 -0000` - -These packages were released: -- `homer_map_manager` -- `homer_mapnav_msgs` -- `homer_mapping` -- `homer_nav_libs` -- `homer_navigation` - -Version of package(s) in repository `homer_mapnav`: -- upstream repository: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git -- release repository: unknown -- rosdistro version: `null` -- old version: `null` -- new version: `1.0.1-0` - -Versions of tools used: -- bloom version: `0.5.20` -- catkin_pkg version: `0.2.7` -- rosdep version: `0.11.1` -- rosdistro version: `0.4.1` -- vcstools version: `0.1.36` - - -# mapping and navigation - -Here you can find the homer mapping and navigation packages +# map_manager + +## Known Issues / Todo's + +Aus bisher ungeklärten Gründen kann es in seltenen Fällen passieren, dass der map_manager die Verbindung zum roscore verliert. In diesem Fall muss er durch rosrun map_manager map_manager neugestartet werden. + + +## Introduction + +Der map_manager ist der Mittelpunkt der Kommunikation zwischen homer_mapping, homer_navigation, GUI und die Spiel-Nodes. +Das Zusammenspiel dieser Nodes ist im Screenshot des rqt_graphs zu sehen. + + + +Er verwaltet die aktuell durch das mapping erstellte Karte sowie weitere Kartebenen. Aktuell sind das die SLAM-Karte, die aktuellen Laserdaten in einer weiteren Ebene und eine Masking-Ebene, in der mit Hilfe der GUI Hindernisse oder freie Flächen in die Karte gezeichnet werden können. +Jedes mal, wenn eine SLAM-Karte von der mapping-Node geschickt wird, wird diese mit allen anderen Karteneben überschrieben (in der Reihenfolge SLAM, Masking, Laserdaten) und als eine zusammengefügte Karte versendet. +Zudem verwaltet der map_manager alle erstellten Points Of Interest (POIs), die z.B. als Ziele für die Navigation verwendet werden. +Die Node ist außerdem zuständig für das Speichern und Laden der Kartenebenen und der POIs. Dabei wird die SLAM-Ebene sowie die Masking-Ebene berücksichtigt. + + + +## Topics + + +#### Publisher +* `/map`: Die aktuelle Karte, die aus allen aktivierten Kartenebenen zusammengesetzt ist. Diese wird in der GUI angezeigt und für die Navigation verwendet. +* `/map_manager/poi_list`: Verschickt einen Vektor mit allen aktuellen POIs. Dieser Publisher wird immer ausgelöst, sobald sich ein POI ändert oder ein neuer hinzugefügt wird. +* `/map_manager/loaded_map`: Wenn eine Karte geladen wird, wird über dieses Topic die geladene SLAM-Ebene an die homer_mapping-Node verschickt. +* `/map_manager/mask_slam`: Über die GUI kann die SLAM-Map verändert werden. Diese Modifizierungen werden über dieses Topic vom map_manager an das homer_mapping versendet. + +#### Subscriber + +* `/homer_mapping/slam_map (nav_msgs/OccupancyGrid)`: Hierüber wird die aktuelle SLAM-Map empfangen. +* `/map_manager/save_map (map_messages/SaveMap)`: Hierüber wird der Befehl zum Speichern der Karte inklusive des Dateinamens empfangen. +* `/map_manager/load_map (map_messages/SaveMap)`: Hiermit wird eine Karte geladen und alle bisherigen Kartenebenen durch die geladenen ersetzt. +* `/map_manager/toggle_map_visibility (map_messages/MapLayers)`: Hierüber können einzelne Kartenebenen aktiviert beziehungsweise deaktiviert werden. Deaktivierte werden nicht mehr beim Zusammenfügen der Karte berücksichtigt und dementsprechend auch nicht in der GUI angezeigt sowie für die Navigation verwendet. +* `/scan (nav_msgs/LaserScan)`: Der aktuelle Laserscan, der in die Laserscan-Ebene gezeichnet wird. +* `/map_manager/add_POI (map_messages/PointOfInterest)`: Hierüber kann ein POI hinzugefügt werden. +* `/map_manager/modify_POI (map_messages/ModifyPOI)`: Hierüber kann ein vorhandener POI verändert werden (Name, Position,...) +* `/map_manager/delete_POI (map_messages/DeletePointOfInterest)`: Hierüber kann ein vorhander POI gelöscht werden. +* `/map_manager/modify_map (map_messages/ModifyMap)`: Über dieses Topic werden die Koordinaten der Polygone verschickt, die über die GUI maskiert wurden. Außerdem wird die Kartenebene mitgeteilt, die verändet werden soll (SLAM oder Masking-Ebene). +* `/map_manager/reset_maps (std_msgs/Empty)`: Hierüber werden alle Kartenebenen zurückgesetzt. \ No newline at end of file diff --git a/homer_map_manager/config/custom.xml b/config/custom.xml similarity index 100% rename from homer_map_manager/config/custom.xml rename to config/custom.xml diff --git a/homer_map_manager/config/default.xml b/config/default.xml similarity index 100% rename from homer_map_manager/config/default.xml rename to config/default.xml diff --git a/homer_map_manager/config/merged.xml b/config/merged.xml similarity index 100% rename from homer_map_manager/config/merged.xml rename to config/merged.xml diff --git a/homer_map_manager/README.md b/homer_map_manager/README.md deleted file mode 100644 index 39a46914..00000000 --- a/homer_map_manager/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# map_manager - -## Known Issues / Todo's - -Aus bisher ungeklärten Gründen kann es in seltenen Fällen passieren, dass der map_manager die Verbindung zum roscore verliert. In diesem Fall muss er durch rosrun map_manager map_manager neugestartet werden. - - -## Introduction - -Der map_manager ist der Mittelpunkt der Kommunikation zwischen homer_mapping, homer_navigation, GUI und die Spiel-Nodes. -Das Zusammenspiel dieser Nodes ist im Screenshot des rqt_graphs zu sehen. - - - -Er verwaltet die aktuell durch das mapping erstellte Karte sowie weitere Kartebenen. Aktuell sind das die SLAM-Karte, die aktuellen Laserdaten in einer weiteren Ebene und eine Masking-Ebene, in der mit Hilfe der GUI Hindernisse oder freie Flächen in die Karte gezeichnet werden können. -Jedes mal, wenn eine SLAM-Karte von der mapping-Node geschickt wird, wird diese mit allen anderen Karteneben überschrieben (in der Reihenfolge SLAM, Masking, Laserdaten) und als eine zusammengefügte Karte versendet. -Zudem verwaltet der map_manager alle erstellten Points Of Interest (POIs), die z.B. als Ziele für die Navigation verwendet werden. -Die Node ist außerdem zuständig für das Speichern und Laden der Kartenebenen und der POIs. Dabei wird die SLAM-Ebene sowie die Masking-Ebene berücksichtigt. - - - -## Topics - - -#### Publisher -* `/map`: Die aktuelle Karte, die aus allen aktivierten Kartenebenen zusammengesetzt ist. Diese wird in der GUI angezeigt und für die Navigation verwendet. -* `/map_manager/poi_list`: Verschickt einen Vektor mit allen aktuellen POIs. Dieser Publisher wird immer ausgelöst, sobald sich ein POI ändert oder ein neuer hinzugefügt wird. -* `/map_manager/loaded_map`: Wenn eine Karte geladen wird, wird über dieses Topic die geladene SLAM-Ebene an die homer_mapping-Node verschickt. -* `/map_manager/mask_slam`: Über die GUI kann die SLAM-Map verändert werden. Diese Modifizierungen werden über dieses Topic vom map_manager an das homer_mapping versendet. - -#### Subscriber - -* `/homer_mapping/slam_map (nav_msgs/OccupancyGrid)`: Hierüber wird die aktuelle SLAM-Map empfangen. -* `/map_manager/save_map (map_messages/SaveMap)`: Hierüber wird der Befehl zum Speichern der Karte inklusive des Dateinamens empfangen. -* `/map_manager/load_map (map_messages/SaveMap)`: Hiermit wird eine Karte geladen und alle bisherigen Kartenebenen durch die geladenen ersetzt. -* `/map_manager/toggle_map_visibility (map_messages/MapLayers)`: Hierüber können einzelne Kartenebenen aktiviert beziehungsweise deaktiviert werden. Deaktivierte werden nicht mehr beim Zusammenfügen der Karte berücksichtigt und dementsprechend auch nicht in der GUI angezeigt sowie für die Navigation verwendet. -* `/scan (nav_msgs/LaserScan)`: Der aktuelle Laserscan, der in die Laserscan-Ebene gezeichnet wird. -* `/map_manager/add_POI (map_messages/PointOfInterest)`: Hierüber kann ein POI hinzugefügt werden. -* `/map_manager/modify_POI (map_messages/ModifyPOI)`: Hierüber kann ein vorhandener POI verändert werden (Name, Position,...) -* `/map_manager/delete_POI (map_messages/DeletePointOfInterest)`: Hierüber kann ein vorhander POI gelöscht werden. -* `/map_manager/modify_map (map_messages/ModifyMap)`: Über dieses Topic werden die Koordinaten der Polygone verschickt, die über die GUI maskiert wurden. Außerdem wird die Kartenebene mitgeteilt, die verändet werden soll (SLAM oder Masking-Ebene). -* `/map_manager/reset_maps (std_msgs/Empty)`: Hierüber werden alle Kartenebenen zurückgesetzt. \ No newline at end of file diff --git a/homer_mapnav_msgs/CHANGELOG.rst b/homer_mapnav_msgs/CHANGELOG.rst deleted file mode 100644 index a164dd15..00000000 --- a/homer_mapnav_msgs/CHANGELOG.rst +++ /dev/null @@ -1,27 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package mapnav_msgs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1.0.6 (2015-11-27) ------------------- - -1.0.5 (2015-11-24) ------------------- - -1.0.4 (2015-11-20) ------------------- - -1.0.3 (2015-11-20) ------------------- - -1.0.2 (2015-11-20) ------------------- -* added cmake_modules as build dependency in package.xml -* added Maintainers -* added raphael as maintainer -* Contributors: Niklas Yann Wettengel, Raphael Memmesheimer - -1.0.1 (2015-09-08) ------------------- -* init -* Contributors: Raphael Memmesheimer diff --git a/homer_mapnav_msgs/CMakeLists.txt b/homer_mapnav_msgs/CMakeLists.txt deleted file mode 100644 index c5edc11e..00000000 --- a/homer_mapnav_msgs/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -project(homer_mapnav_msgs) - -find_package(catkin REQUIRED - COMPONENTS message_generation nav_msgs geometry_msgs) - -add_message_files(FILES - DeletePointOfInterest.msg - DoMapping.msg - MapLayers.msg - ModifyMap.msg - PointOfInterest.msg - PointsOfInterest.msg - RegionOfInterest.msg - RegionsOfInterest.msg - ModifyPOI.msg - TargetUnreachable.msg - StartNavigation.msg - StopNavigation.msg - NavigateToPOI.msg -) - -add_service_files(FILES - GetPointsOfInterest.srv - GetRegionsOfInterest.srv - LoadMap.srv - SaveMap.srv -) - -generate_messages(DEPENDENCIES geometry_msgs nav_msgs) - -catkin_package(CATKIN_DEPENDS message_runtime geometry_msgs nav_msgs) diff --git a/homer_mapnav_msgs/README.md b/homer_mapnav_msgs/README.md deleted file mode 100644 index 47aeac04..00000000 --- a/homer_mapnav_msgs/README.md +++ /dev/null @@ -1,244 +0,0 @@ -# map_messages - - -## Introduction - -Dieses Package enthält alle benutzerdefinierten Messages, die neben den in ROS enthaltenen Messages für das Mapping und die Navigation verwendet werden. Das Package enthält keine Node oder Librabries. - -## Messages - - -### PointOfInterest - - -Die PointOfInterest-Message enthält alle Informationen, um einen POI zu erstellen, zu verschicken und zu speichern. - -~~~~~~ {.cpp} -PointOfInterest.msg - - - -int32 DEFAULT=100 -int32 VICTIM=200 -int32 OBJECT=300 -int32 GRIPPABLE_OBJECT=400 -int32 PERSON=600 -int32 ROOMBA=700 -int32 HAZARD_MATERIAL=800 -int32 START_POSITION=900 -int32 START_ORIENTATION=1000 - -int32 type -string name -string remarks - -geometry_msgs/Pose pose -~~~~~~ - -* `type` bezeichnet den Typ des POIs. Es kann eine der in dieser Message vorhandenen Konstanten verwendet werden. -* `name` bezeichnet den Namen des POIs. Dieser Name muss einzigartig sein, da die POIs über ihren Namen unterschieden werden. -* `remarks`: Hier können Anmerkungen reingeschrieben werden. Diese werden in der GUI angezeigt. -* `pose` bezeichnet die Position und Orientierung des POIS im /map-Frame. - - -### ModifyPOI - - -ModifyPOI ist dafür zuständig, einen vorhandenen POI zu verändern. - -~~~~~~ {.cpp} -ModifyPOI.msg - -PointOfInterest poi -string old_name -~~~~~~ - -* `poi` beinhaltet den POI, durch den der alte ersetzt werden soll. -* `old_name` bezeichnet den Namen des POIs, der verändert werden soll. - - -### TargetUnreachable - - - -TargetUnreachable wird von der Navigation versendet, sobald kein Pfad mehr zu einem Ziel geplant werden kann. - - -~~~~~~ {.cpp} -TargetUnreachable.msg - -int8 UNKNOWN=0 -int8 TILT_OCCURED=10 -int8 GRAVE_TILT_OCCURED=15 -int8 STALL_OCCURED=20 -int8 LASER_OBSTACLE=30 - -int8 reason -~~~~~~ - -* `reason` kann einen von den in dieser Message definierten Konstanten annehmen und beschreibt den Grund des Fehlers. - - -### SaveMap - -SaveMap wird versendet, wenn eine Karte gespeichert oder geladen werden soll und beinhaltet den Dateipfad zum Kartenordner. - - -~~~~~~ {.cpp} -SaveMap.msg - -string filename -~~~~~~ - -* `filename` bezeichnet den Dateipfad zum Kartenordner. - - -### PointsOfInterest - - -PointsOfInterest wird verwendet, um alle aktuellen POIs zu versenden. - - -~~~~~~ {.cpp} -PointsOfInterest.msg - -PointOfInterest[] pois -~~~~~~ - -* `pois` beinhaltet einen Vektor mit allen aktuellen POIs. - - -### StartNavigation - - -StartNavigation ist eine von zwei Methoden, um eine Navigation zu starten. Hier wird Der POI mitgegeben, zu dem der Roboter navigieren soll. - - -~~~~~~ {.cpp} -StartNavigation.msg - -geometry_msgs/Pose goal -float32 distance_to_target -bool skip_final_turn -bool fast_planning -~~~~~~ - -* `goal` beinhaltet den Ziel-POI -* `distance_to_target`: Hier kann angegeben werden, ab welcher Distanz zum Ziel die Navigation als erfolgreich abgeschlossen wird. -* `skip_final_turn`: Hier kann eingestellt werden, ob der Roboter sich am Ziel-POI in Richtund der POI-Orientierung ausrichten soll oder nicht. -* `fast_planning`: Mit dieser Option kann ein experimentelles "Schnelles Planen" eingeschaltet werden. Es werden nur Pfade geplant, die sich in einer Boundingbox zwischen Roboter und Zielposition befinden. - - -### MapLayers - -MapLayers definiert die vorhanden Kartenebenen als Konstanten und kann zudem verwendet werden, um einzelne Ebenen ein- oder auszuschalten. - - -~~~~~~ {.cpp} -MapLayers.msg - -int32 SLAM_LAYER=0 -int32 MASKING_LAYER=1 -int32 KINECT_LAYER=2 -int32 SICK_LAYER=3 - -int32 layer -bool state -~~~~~~ - -* `layer` enthält die Kartenebenen-ID und kann einen Wert dern in dieser Message definierten Konstanten annehmen. -* `state` besagt, ob die ausgewählte Kartenebene aktiviert sein soll. - - - - -### NavigateToPOI - - -NavigateToPOI ist die zweite Art eine Navigation zu starten. Anstatt das gesamte POI-Objekt mitzugeben, wird nur der Name eines bereits im map_manger vorhandenen POIs mitgegeben, der daraufhin von der Navigation nachgeschlagen wird. - -~~~~~~ {.cpp} -NavigateToPOI.msg - -string poi_name -float32 distance_to_target -bool skip_final_turn -~~~~~~ - -* `poi_name` beschreibt den Namen des POIS, zu dem navigiert werden soll. -* `distance_to_target` siehe StartNavigation -* `skip_final_turn` siehe StartNavigation - - -### ModifyMap - - -Mit dieser Message können Bereiche in einzelnen Kartenebenen verändert werden. - - -~~~~~~ {.cpp} -ModifyMap.msg - -int32 FREE = 0 -int32 BLOCKED = 100 -int32 OBSTACLE = 99 -int32 NOT_MASKED = -1 - -geometry_msgs/Point[] region -int32 maskAction -int32 mapLayer -~~~~~~ - -* `region` beschreibt die Eckpunkte des Polygons, das maskiert werden soll. -* `maskAction` kann einen Wert der in dieser Message definierten Konstanten annehmen. OBSTACLE wird in der Karte rot dargestellt. Mit NOT_MASKED können bereits maskierte Bereiche wieder gelöscht werden. -* `mapLayer` enthält die ID der zu verändernden Kartenebene. Die IDs sind in der Message MapLayers definiert. - - - -### DeletePointOfInterest - -Löscht einen vorhandenen POI. - - -~~~~~~ {.cpp} -DeletePointOfInterest.msg - -string name -~~~~~~ - -* `name` beschreibt den Namen des zu löschenden POIs. - - -### DoMapping - - - -Mit dieser Message kann das Mapping ein- oder ausgeschaltet werden. - -~~~~~~ {.cpp} -DoMapping.msg - -bool state -~~~~~~ - -* `state` beinhaltet den Zustand des Mappings (true = an, false = off). - - -## Services - -### GetPointsOfInterest - - -Über diesen Service kann die aktuelle Liste der POIs angefordert werden. - - -~~~~~~ {.cpp} -GetPointsOfInterest.srv - ---- -PointsOfInterest poi_list -~~~~~~ - -* `poi_list` beinhaltet einen Vektor mit allen aktuellen POIs. - - diff --git a/homer_mapnav_msgs/mainpage.dox b/homer_mapnav_msgs/mainpage.dox deleted file mode 100644 index 4ef2ddd8..00000000 --- a/homer_mapnav_msgs/mainpage.dox +++ /dev/null @@ -1,14 +0,0 @@ -/** -\mainpage -\htmlinclude manifest.html - -\b map_messages - -<!-- -Provide an overview of your package. ---> - ---> - - -*/ diff --git a/homer_mapnav_msgs/manifest.xml b/homer_mapnav_msgs/manifest.xml deleted file mode 100644 index 77dfdadc..00000000 --- a/homer_mapnav_msgs/manifest.xml +++ /dev/null @@ -1,16 +0,0 @@ -<package> - <description brief="map_messages"> - - map_messages - - </description> - <author>Malte Knauf</author> - <license>BSD</license> - <review status="unreviewed" notes=""/> - <url>http://ros.org/wiki/map_messages</url> - - <depend package="geometry_msgs"/> - <depend package="nav_msgs"/> -</package> - - diff --git a/homer_mapnav_msgs/msg/DeletePointOfInterest.msg b/homer_mapnav_msgs/msg/DeletePointOfInterest.msg deleted file mode 100644 index 42f2bc1c..00000000 --- a/homer_mapnav_msgs/msg/DeletePointOfInterest.msg +++ /dev/null @@ -1 +0,0 @@ -string name diff --git a/homer_mapnav_msgs/msg/DoMapping.msg b/homer_mapnav_msgs/msg/DoMapping.msg deleted file mode 100644 index 119c8395..00000000 --- a/homer_mapnav_msgs/msg/DoMapping.msg +++ /dev/null @@ -1 +0,0 @@ -bool state diff --git a/homer_mapnav_msgs/msg/MapLayers.msg b/homer_mapnav_msgs/msg/MapLayers.msg deleted file mode 100644 index 78ccd311..00000000 --- a/homer_mapnav_msgs/msg/MapLayers.msg +++ /dev/null @@ -1,7 +0,0 @@ -int32 SLAM_LAYER=0 -int32 MASKING_LAYER=1 -int32 KINECT_LAYER=2 -int32 SICK_LAYER=3 - -int32 layer # map layer name -bool state # visibility state (on/off) diff --git a/homer_mapnav_msgs/msg/ModifyMap.msg b/homer_mapnav_msgs/msg/ModifyMap.msg deleted file mode 100644 index b9a709d3..00000000 --- a/homer_mapnav_msgs/msg/ModifyMap.msg +++ /dev/null @@ -1,17 +0,0 @@ -int32 FREE = 0 # Area is free -int32 BLOCKED = 100 # Area blocked by user (use UNBLOCK to .. ) -int32 OBSTACLE = 99 # Area is occupied by an obstacle (e.g. 3d scan) -int32 NOT_MASKED = -1 # Area is not masked: use slam map -int32 HIGH_SENSITIV = -2 # Area is highly sensitiv for Obstacles -int32 KINECT = 102 # Area is blocked by Kinect Obstacle - - -int32 SET_FREE = 0 # Mark area free, area must not be BLOCKED -int32 SET_BLOCKED = 100 # Block area -int32 SET_OBSTACLE = 99 # Mark area as occupied by an obstacle (e.g. 3d scan) -int32 SET_HIGH_SENSITIV = -2 # Mark Area as highly sensitiv for Obstacles - - -geometry_msgs/Point[] region -int32 maskAction -int32 mapLayer #currently not used. modifications only take place in the masking map layer diff --git a/homer_mapnav_msgs/msg/ModifyPOI.msg b/homer_mapnav_msgs/msg/ModifyPOI.msg deleted file mode 100644 index 59786f4b..00000000 --- a/homer_mapnav_msgs/msg/ModifyPOI.msg +++ /dev/null @@ -1,2 +0,0 @@ -PointOfInterest poi -string old_name #necessary if name of poi is changed diff --git a/homer_mapnav_msgs/msg/NavigateToPOI.msg b/homer_mapnav_msgs/msg/NavigateToPOI.msg deleted file mode 100644 index 342f1d1f..00000000 --- a/homer_mapnav_msgs/msg/NavigateToPOI.msg +++ /dev/null @@ -1,3 +0,0 @@ -string poi_name -float32 distance_to_target -bool skip_final_turn diff --git a/homer_mapnav_msgs/msg/PointOfInterest.msg b/homer_mapnav_msgs/msg/PointOfInterest.msg deleted file mode 100644 index af6654c8..00000000 --- a/homer_mapnav_msgs/msg/PointOfInterest.msg +++ /dev/null @@ -1,13 +0,0 @@ -#POI types -int32 DEFAULT=100 -int32 OBJECT=300 -int32 GRIPPABLE_OBJECT=400 -int32 PERSON=600 -int32 START_POSITION=900 -int32 START_ORIENTATION=1000 - -int32 type -string name -string remarks - -geometry_msgs/Pose pose diff --git a/homer_mapnav_msgs/msg/PointsOfInterest.msg b/homer_mapnav_msgs/msg/PointsOfInterest.msg deleted file mode 100644 index a2cfa937..00000000 --- a/homer_mapnav_msgs/msg/PointsOfInterest.msg +++ /dev/null @@ -1 +0,0 @@ -PointOfInterest[] pois diff --git a/homer_mapnav_msgs/msg/RegionOfInterest.msg b/homer_mapnav_msgs/msg/RegionOfInterest.msg deleted file mode 100644 index 6b4d3058..00000000 --- a/homer_mapnav_msgs/msg/RegionOfInterest.msg +++ /dev/null @@ -1,12 +0,0 @@ -#ROI types -int32 DEFAULT=100 -int32 ROOM=200 -int32 AREA=300 -int32 FORBIDDEN_AREA=400 - -int32 type -string name -string remarks - -int32 id -geometry_msgs/Point[4] points diff --git a/homer_mapnav_msgs/msg/RegionsOfInterest.msg b/homer_mapnav_msgs/msg/RegionsOfInterest.msg deleted file mode 100644 index 73c0b1b0..00000000 --- a/homer_mapnav_msgs/msg/RegionsOfInterest.msg +++ /dev/null @@ -1 +0,0 @@ -RegionOfInterest[] rois diff --git a/homer_mapnav_msgs/msg/StartNavigation.msg b/homer_mapnav_msgs/msg/StartNavigation.msg deleted file mode 100644 index cff7a639..00000000 --- a/homer_mapnav_msgs/msg/StartNavigation.msg +++ /dev/null @@ -1,4 +0,0 @@ -geometry_msgs/Pose goal -float32 distance_to_target #default should bei 0.01 [m] -bool skip_final_turn -bool fast_planning #path planning within bounding box containing robot pose and target diff --git a/homer_mapnav_msgs/msg/StopNavigation.msg b/homer_mapnav_msgs/msg/StopNavigation.msg deleted file mode 100644 index e69de29b..00000000 diff --git a/homer_mapnav_msgs/msg/TargetUnreachable.msg b/homer_mapnav_msgs/msg/TargetUnreachable.msg deleted file mode 100644 index f69ddf67..00000000 --- a/homer_mapnav_msgs/msg/TargetUnreachable.msg +++ /dev/null @@ -1,9 +0,0 @@ -int8 UNKNOWN=0 -int8 TILT_OCCURED=10 -int8 GRAVE_TILT_OCCURED=15 -int8 STALL_OCCURED=20 -int8 LASER_OBSTACLE=30 -int8 LASER_TIMEOUT=35 -int8 NO_PATH_FOUND=40 - -int8 reason diff --git a/homer_mapnav_msgs/package.xml b/homer_mapnav_msgs/package.xml deleted file mode 100644 index e727f738..00000000 --- a/homer_mapnav_msgs/package.xml +++ /dev/null @@ -1,27 +0,0 @@ -<package> - <name>homer_mapnav_msgs</name> - <version>1.0.6</version> - <description> - - mapnav_msgs - - </description> - <maintainer email="vseib@uni-koblenz.de">Viktor Seib</maintainer> - <maintainer email="niyawe@uni-koblenz.de">Niklas Yann Wettengel</maintainer> - <maintainer email="heuer@uni-koblenz.de">Gregor Heuer</maintainer> - <author email="mknauf@uni-koblenz.de">Malte Knauf</author> - <author email="raphael@uni-koblenz.de">Raphael Memmesheimer</author> - <license>GPLv3</license> - - <buildtool_depend>catkin</buildtool_depend> - <build_depend>message_generation</build_depend> - <build_depend>genmsg</build_depend> - <build_depend>geometry_msgs</build_depend> - <build_depend>nav_msgs</build_depend> - <build_depend>cmake_modules</build_depend> - <run_depend>geometry_msgs</run_depend> - <run_depend>nav_msgs</run_depend> - <run_depend>message_runtime</run_depend> -</package> - - diff --git a/homer_mapnav_msgs/readme.pdf b/homer_mapnav_msgs/readme.pdf deleted file mode 100644 index bb76e2631376e2bda2c6ca741778247f62e4e6a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121801 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 diff --git a/homer_mapnav_msgs/srv/GetPointsOfInterest.srv b/homer_mapnav_msgs/srv/GetPointsOfInterest.srv deleted file mode 100644 index e7a3c1a7..00000000 --- a/homer_mapnav_msgs/srv/GetPointsOfInterest.srv +++ /dev/null @@ -1,2 +0,0 @@ ---- -PointsOfInterest poi_list diff --git a/homer_mapnav_msgs/srv/GetRegionsOfInterest.srv b/homer_mapnav_msgs/srv/GetRegionsOfInterest.srv deleted file mode 100644 index f98be082..00000000 --- a/homer_mapnav_msgs/srv/GetRegionsOfInterest.srv +++ /dev/null @@ -1,2 +0,0 @@ ---- -RegionsOfInterest roi_list diff --git a/homer_mapnav_msgs/srv/LoadMap.srv b/homer_mapnav_msgs/srv/LoadMap.srv deleted file mode 100644 index ef2e165e..00000000 --- a/homer_mapnav_msgs/srv/LoadMap.srv +++ /dev/null @@ -1,2 +0,0 @@ -std_msgs/String filename ---- diff --git a/homer_mapnav_msgs/srv/SaveMap.srv b/homer_mapnav_msgs/srv/SaveMap.srv deleted file mode 100644 index 67831529..00000000 --- a/homer_mapnav_msgs/srv/SaveMap.srv +++ /dev/null @@ -1,2 +0,0 @@ -std_msgs/String folder ---- diff --git a/homer_mapping/CHANGELOG.rst b/homer_mapping/CHANGELOG.rst deleted file mode 100644 index bec2c04d..00000000 --- a/homer_mapping/CHANGELOG.rst +++ /dev/null @@ -1,28 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package homer_mapping -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1.0.6 (2015-11-27) ------------------- -* removed env HOMER_DIR from CMakeLists.txt -* Contributors: Niklas Yann Wettengel - -1.0.5 (2015-11-24) ------------------- - -1.0.4 (2015-11-20) ------------------- - -1.0.3 (2015-11-20) ------------------- - -1.0.2 (2015-11-20) ------------------- -* added cmake_modules as build dependency in package.xml -* added Maintainers -* Contributors: Niklas Yann Wettengel - -1.0.1 (2015-09-08) ------------------- -* init -* Contributors: Raphael Memmesheimer diff --git a/homer_mapping/CMakeLists.txt b/homer_mapping/CMakeLists.txt deleted file mode 100644 index b794c6fa..00000000 --- a/homer_mapping/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) -project(homer_mapping) - -find_package( - catkin REQUIRED COMPONENTS - roscpp - homer_mapnav_msgs - sensor_msgs - nav_msgs - homer_nav_libs - tf - roslib -) - -set(CMAKE_BUILD_TYPE Release) - - -include_directories( - ${catkin_INCLUDE_DIRS} -) - -catkin_package( - CATKIN_DEPENDS - roscpp -) - -add_subdirectory(${PROJECT_SOURCE_DIR}/src/OccupancyMap) -add_subdirectory(${PROJECT_SOURCE_DIR}/src/ParticleFilter) - -add_executable(homer_mapping src/slam_node.cpp) - -target_link_libraries( - homer_mapping - ${catkin_LIBRARIES} - MappingMath - ParticleFilter - OccupancyMap - Explorer -) - -add_dependencies( - homer_mapping - ${catkin_EXPORTED_TARGETS} -) diff --git a/homer_mapping/README.md b/homer_mapping/README.md deleted file mode 100644 index e2781906..00000000 --- a/homer_mapping/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# homer_mapping - -## Introduction - -Das Package homer_mapping besteht aus einer gleichnamigen Node. Diese ist für die Lokalisierung und Kartierung des Roboters mit Hilfe der Odometrie des Roboters und eines Laserscanners zuständig. -Das SLAM-Problem wird durch den Partikelfilter-Algorithmus gelöst. -Die Node erwartet kontiniuierlich Odometrie-Werte und Laserdaten und verschickt in konstanten Abständen korrigierte Poseschätzungen über das Topic /pose und tf-Transformation /map -> /base_link. -Zudem kann der Roboter sich auf einer vorher geladenen Karte lokalisieren, sowie eine aktuell erstellte Karte abgespeichert werden. -Es besteht die Option, die Kartierung ein- oder auszuschalten. Beim Laden einer Karte wird die Kartierung automatisch ausgeschaltet. - -## Topics - - - - - - -#### Publisher -* `/pose (geometry_msgs/PoseStamped)`: Die aktuell ermittelte Pose relativ zu Karte (im Frame /map) des Roboters aus dem Partikelfilter. -* `/homer_mapping/slam_map (nav_msgs/OccupancyGrid)`: Das aktuelle Karte des Roboters. - - - -#### Subscriber - -* `/odom (nav_msgs/Odometry)`: Die aktuellen Odometrie-Werte vom Roboter. Diese werden für die Partikelfilter benötigt. - `/scan (sensor_msgs/LaserScan)`: Die aktuelle Lasermessung, die vom Partikelfilter benötigt wird. -* `/homer_mapping/userdef_pose (geometry_msgs/Pose)`: Mit diesem Topic kann die die aktuell vom Partikelfilter berechnete Pose auf eine benutzerdefinierte gesetzt werden. Der Partikelfilter arbeitet nun mit dieser weiter. -* `/homer_mapping/do_mapping (map_messages/DoMapping)`: Mit diesem Topic kann die Kartierung ein- oder ausgeschaltet werden. -* `/map_manager/reset_maps (std_msgs/Empty)`: Hiermit kann die aktuelle Karte zurückgesetzt werden. -* `/map_manager/loaded_map (nav_msgs/OccupancyGrid)`: Mit diesem Topic kann die aktuelle Karte durch eine andere (geladene) Karte ausgetauscht werden. -* `/map_manager/mask_slam (nav_msgs/OccupancyGrid)`: Im OccupancyGrid dieses Topics stehen Informationen, welche Teile der aktuellen Karte durch andere Werte (frei oder belegt) ersetzt werden sollen. - -## Launch Files - -* `homer_mapping.launch`: Dieses Launchfile lädt die Parameterdatei `homer_mapping.yaml` und startet die Node homer_mapping sowie die Node map_manager im gleichnamigen Package. -* `homer_mapping_rviz.launch`:`Dieses Launchfile hat die gleiche Funktionalität wie das obige, wobei es zusätzlich rviz startet. - -## Parameter - - -### homer_mapping.yaml - - - -* `/homer_mapping/size:` Size beschreibt die Größe einer Seite der Karte in Metern. Die Karte ist quadratisch -* `/homer_mapping/resolution:` Resolution ist die Länge einer (quadratischen) Zelle der Karte in Metern -* `/homer_mapping/backside_checking:` Wenn auf "true" gesetzt, wird verhindet, dass Vorder- und Rückseite einer dickeren Wand auf die gematcht werden. -* `/homer_mapping/obstacle_borders:` Wenn auf "true" gesetzt, wird um eingetragene Hindernisse ein kleiner Rand unbekanntes Gebiet gelassen. -* `/homer_mapping/measure_sampling_step:` Minimale Distanz in Metern, die zwischen zwei aufeinanderfolgenden Messpunkten im Laserscan vorhanden sein muss, um sie für die Poseberechnung zu verwenden -* `/homer_mapping/laser_scanner/free_reading_distance:` Minimale Distanz in Metern, die als hindernissfrei angenommen wird, wenn der aktuelle Messpunkt fehlerhaft ist -* `/particlefilter/error_values/rotation_error_rotating:` Rotationsfehler in Prozent, der beim Rotieren des Roboters auftritt -* `/particlefilter/error_values/rotation_error_translating:` Rotationsfehler in Grad, der beim Fahren von einem Meter auftritt -* `/particlefilter/error_values/translation_error_translating:` Translationsfehler in Prozent, der beim Geradeausfahren auftritt -* `/particlefilter/error_values/translation_error_rotating:` Translationsfehler in Metern, der beim Rotieren von einem Grad auftritt -* `/particlefilter/error_values/move_jitter_while_turning:` Streuung der neu berechneten Pose in Meter pro Grad Drehung -* `/particlefilter/hyper_slamfilter/particlefilter_num:` Anzahl der Partikelfilter im Hyperpartikelfilter (ist standardmäßig auf 1 gesetzt) -* `/particlefilter/particle_num:` Anzahl der Partikel in jedem Partikelfilter -* `/particlefilter/max_rotation_per_second:` Maximale Rotation in Radiant pro Sekunde, die der Roboter sich drehen darf, ohne dass das Mapping ausgesetzt wird -* `/particlefilter/wait_time:` Minimale Zeit, die zwischen zwei Mapping-Schritten verstrichen sein muss -* `/particlefilter/update_min_move_angle:` Minimale Rotation in Grad, die durchgeführt werden muss, damit ein Partikelfilterschritt ausgeführt wird... -* `/particlefilter/update_min_move_dist:` ...oder minimale Distanz in Metern, die der Roboter geradeaus fährt... -* `/particlefilter/max_update_interval:` ...oder minimale Wartezeit, in der der Roboter still steht. -* `/selflocalization/scatter_var_xy:` Streuung der Partikel in x/y-Richtung in Metern beim Setzen einer benutzerdefinierten Pose -* `/selflocalization/scatter_var_theta:` Streuung der Ausrichtung der Partikel in Radiant beim Setzen einer benutzerdefinierten Pose - - diff --git a/homer_mapping/config/homer_mapping.yaml b/homer_mapping/config/homer_mapping.yaml deleted file mode 100644 index 1f4abdc6..00000000 --- a/homer_mapping/config/homer_mapping.yaml +++ /dev/null @@ -1,30 +0,0 @@ -/homer_mapping/size: 35 #size of one edge of the map in m. map is quadratic -/homer_mapping/resolution: 0.05 #meter per cell - -#map config values -/homer_mapping/backside_checking: false #Enable checking to avoid matching front- and backside of obstacles, e.g. walls. Useful when creating high resolution maps -/homer_mapping/obstacle_borders: true #Leaves a small border around obstacles unchanged when inserting a laser scan. Improves stability of generated map -/homer_mapping/measure_sampling_step: 0.15 #Minimum distance in m between two samples for probability calculation - -/homer_mapping/laser_scanner/free_reading_distance: 0.8 # Minimum distance in m to be classified as free in case of errorneous measurement - -/particlefilter/error_values/rotation_error_rotating: 5.0 #percent -/particlefilter/error_values/rotation_error_translating: 0.0 #degrees per meter -/particlefilter/error_values/translation_error_translating: 5.0 #percent -/particlefilter/error_values/translation_error_rotating: 0.0 #m per degree -/particlefilter/error_values/move_jitter_while_turning: 0.05 #30.0 #m per degree - - -/particlefilter/hyper_slamfilter/particlefilter_num: 1 - -/particlefilter/particle_num: 1000 -/particlefilter/max_rotation_per_second: 1.0 #maximal rotation in radiants if mapping is performed. if rotation is bigger, mapping is interrupted -/particlefilter/wait_time: 0.08 #minimum time to wait between two slam steps in seconds - -#the map is only updated when the robot has turned a minimal angle, has moved a minimal distance or a maximal time has passed -/particlefilter/update_min_move_angle: 5 # degrees -/particlefilter/update_min_move_dist: 0.1 #m -/particlefilter/max_update_interval: 2 #seconds - -/selflocalization/scatter_var_xy: 0.05 #m -/selflocalization/scatter_var_theta: 0.2 #radiants diff --git a/homer_mapping/config/homer_mapping_followme.yaml b/homer_mapping/config/homer_mapping_followme.yaml deleted file mode 100644 index 13792fb8..00000000 --- a/homer_mapping/config/homer_mapping_followme.yaml +++ /dev/null @@ -1,8 +0,0 @@ -/homer_mapping/size: 35 #size of one edge of the map in m. map is quadratic -/homer_mapping/resolution: 0.1 #meter per cell - -/particlefilter/error_values/rotation_error_rotating: 0.05 #percent -/particlefilter/error_values/rotation_error_translating: 5.0 #degrees per meter -/particlefilter/error_values/translation_error_translating: 8.0 #percent -/particlefilter/error_values/translation_error_rotating: 0.005 #m per degree -/particlefilter/error_values/move_jitter_while_turning: 0.05 #30.0 #m per degree diff --git a/homer_mapping/launch/homer_mapping.launch b/homer_mapping/launch/homer_mapping.launch deleted file mode 100644 index e9e5c5d8..00000000 --- a/homer_mapping/launch/homer_mapping.launch +++ /dev/null @@ -1,5 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_mapping)/config/homer_mapping.yaml"/> - <node name="homer_mapping" pkg="homer_mapping" type="homer_mapping" output="screen"/> - <node name="map_manager" pkg="map_manager" type="map_manager" output="screen"/> -</launch> diff --git a/homer_mapping/launch/homer_mapping_followme.launch b/homer_mapping/launch/homer_mapping_followme.launch deleted file mode 100644 index bdc7208d..00000000 --- a/homer_mapping/launch/homer_mapping_followme.launch +++ /dev/null @@ -1,5 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_mapping)/config/homer_mapping_followme.yaml"/> - <node name="homer_mapping" pkg="homer_mapping" type="homer_mapping" output="screen"/> - <node name="map_manager" pkg="map_manager" type="map_manager" output="screen"/> -</launch> diff --git a/homer_mapping/launch/homer_mapping_ros.launch b/homer_mapping/launch/homer_mapping_ros.launch deleted file mode 100644 index e9e5c5d8..00000000 --- a/homer_mapping/launch/homer_mapping_ros.launch +++ /dev/null @@ -1,5 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_mapping)/config/homer_mapping.yaml"/> - <node name="homer_mapping" pkg="homer_mapping" type="homer_mapping" output="screen"/> - <node name="map_manager" pkg="map_manager" type="map_manager" output="screen"/> -</launch> diff --git a/homer_mapping/launch/homer_mapping_rviz.launch b/homer_mapping/launch/homer_mapping_rviz.launch deleted file mode 100644 index 8ac72e94..00000000 --- a/homer_mapping/launch/homer_mapping_rviz.launch +++ /dev/null @@ -1,6 +0,0 @@ -<launch> - <param name="use_sim_time" type="bool" value="true"/> - <node name="tf_static_publisher" pkg="homer_mapping" type="static_publisher"/> - <node name="homer_mapping" pkg="homer_mapping" type="homer_mapping" output="screen"/> - <node name="rviz" pkg="rviz" type="rviz"/> -</launch> diff --git a/homer_mapping/mainpage.dox b/homer_mapping/mainpage.dox deleted file mode 100644 index 054b63cf..00000000 --- a/homer_mapping/mainpage.dox +++ /dev/null @@ -1,26 +0,0 @@ -/** -\mainpage -\htmlinclude manifest.html - -\b homer_mapping is ... - -<!-- -Provide an overview of your package. ---> - - -\section codeapi Code API - -<!-- -Provide links to specific auto-generated API documentation within your -package that is of particular interest to a reader. Doxygen will -document pretty much every part of your code, so do your best here to -point the reader to the actual API. - -If your codebase is fairly large or has different sets of APIs, you -should use the doxygen 'group' tag to keep these APIs together. For -example, the roscpp documentation has 'libros' group. ---> - - -*/ diff --git a/homer_mapping/manifest.xml b/homer_mapping/manifest.xml deleted file mode 100644 index 2c9977b6..00000000 --- a/homer_mapping/manifest.xml +++ /dev/null @@ -1,23 +0,0 @@ -<package> - <description brief="homer_mapping"> - - homer_mapping - - </description> - <author>Malte</author> - <license>BSD</license> - <review status="unreviewed" notes=""/> - <url>http://ros.org/wiki/homer_mapping</url> - <depend package="std_msgs"/> - <depend package="roscpp"/> - <depend package="sensor_msgs"/> - <depend package="nav_msgs"/> - <depend package="tf"/> - <depend package="roslib"/> - - <depend package="robbie_architecture"/> - <depend package="BaseLib"/> - <depend package="map_messages"/> -</package> - - diff --git a/homer_mapping/package.xml b/homer_mapping/package.xml deleted file mode 100644 index 2d53b608..00000000 --- a/homer_mapping/package.xml +++ /dev/null @@ -1,38 +0,0 @@ -<package> - <name>homer_mapping</name> - <version>1.0.6</version> - <description> - - homer_mapping - - </description> - <maintainer email="vseib@uni-koblenz.de">Viktor Seib</maintainer> - <maintainer email="raphael@uni-koblenz.de">Raphael Memmesheimer</maintainer> - <maintainer email="niyawe@uni-koblenz.de">Niklas Yann Wettengel</maintainer> - <maintainer email="heuer@uni-koblenz.de">Gregor Heuer</maintainer> - <author email="mknauf@uni-koblenz.de">Malte Knauf</author> - - <license>GPLv3</license> - <buildtool_depend>catkin</buildtool_depend> - - <build_depend>roscpp</build_depend> - <build_depend>sensor_msgs</build_depend> - <build_depend>nav_msgs</build_depend> - <build_depend>tf</build_depend> - <build_depend>roslib</build_depend> - <build_depend>homer_nav_libs</build_depend> - <build_depend>cmake_modules</build_depend> - - <build_depend>homer_mapnav_msgs</build_depend> - - - <run_depend>std_msgs</run_depend> - <run_depend>roscpp</run_depend> - <run_depend>sensor_msgs</run_depend> - <run_depend>nav_msgs</run_depend> - <run_depend>tf</run_depend> - <run_depend>roslib</run_depend> - <run_depend>homer_nav_libs</run_depend> - - <run_depend>homer_mapnav_msgs</run_depend> -</package> diff --git a/homer_mapping/readme.pdf b/homer_mapping/readme.pdf deleted file mode 100644 index 07f93c8ff0f8b7c478d0e93269eb5df0febdd4ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113506 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%0A%7A7(O5Et8f3B* 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 OI9Q-aNk!$vp#BH_wC<b$ diff --git a/homer_mapping/src/CMakeLists.txt b/homer_mapping/src/CMakeLists.txt deleted file mode 100644 index e5e17710..00000000 --- a/homer_mapping/src/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(Workers) -add_subdirectory(Modules) diff --git a/homer_mapping/src/OccupancyMap/CMakeLists.txt b/homer_mapping/src/OccupancyMap/CMakeLists.txt deleted file mode 100644 index 9aaff582..00000000 --- a/homer_mapping/src/OccupancyMap/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# QT related -find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) -find_package(tf REQUIRED) -include(${QT_USE_FILE}) -add_definitions(${QT_DEFINITIONS}) - -set( - OccupancyMap_SRC - OccupancyMap.cpp -) - -include_directories( - ${QT_INCLUDE_DIR} -) - -add_library( - OccupancyMap - ${OccupancyMap_SRC} -) - -target_link_libraries( - OccupancyMap - ${QT_LIBRARIES} - ${tf_LIBRARIES} -) - -add_dependencies( - OccupancyMap - or_msgs_gencpp - homer_mapnav_msgs_gencpp -) diff --git a/homer_mapping/src/OccupancyMap/Math/Box2D.h b/homer_mapping/src/OccupancyMap/Math/Box2D.h deleted file mode 100644 index 5979b68a..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Box2D.h +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * Box2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: Box2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef Box2D_H -#define Box2D_H - -#include "Point2D.h" -#include <vector> - -/** - * @class Box2D - * @author David Gossow (RX) - * @brief Represents a box given by the upper-left and lower-right corner - */ -template<class T=float> -class Box2D -{ - - public: - - /** @brief Creates a box given by top-left (minX,minY) and lower-right (maxX,maxY) coordinates */ - Box2D(T minX=0, T minY=0, T maxX=0, T maxY=0); - - /** @brief The destructor */ - ~Box2D() {}; - - inline void setMinX(T value) { m_MinX=value; } - inline void setMaxX(T value) { m_MaxX=value; } - inline void setMinY(T value) { m_MinY=value; } - inline void setMaxY(T value) { m_MaxY=value; } - - inline T minX() const { return m_MinX; } - inline T maxX() const { return m_MaxX; } - inline T minY() const { return m_MinY; } - inline T maxY() const { return m_MaxY; } - - inline T width() const { return m_MaxX-m_MinX; } - inline T height() const { return m_MaxY-m_MinY; } - - std::vector< Point2D > vertices(); - - /** @brief Clip the box to fit into clipArea */ - void clip( Box2D<T> clipArea ); - - /** @return true if the given point is inside the box */ - bool contains( T x, T y ); - - /** @brief enlarge the box by 'size' units in all directions */ - void expand( T size ); - - /** @brief shrink the box by 'size' units in all directions */ - void shrink( T size ); - - /** @brief expand the box so that it contains the given point */ - void enclose( Point2D point ); - void enclose( T x, T y ); - - template<class OtherT> - void enclose( Box2D<OtherT> box ); - - Point2D centerPoint() - { - Point2D center; - center.setX(m_MinX + ( (m_MaxX - m_MinX) / 2 ) ); - center.setY(m_MinY + ( (m_MaxY - m_MinY) / 2 ) ); - return center; - } - - /** @brief area covered by the box */ - T area(); - - Box2D<T>& operator/= ( T div ) { m_MinX/=div; m_MinY/=div; m_MaxX/=div; m_MaxY/=div; return *this; } - Box2D<T>& operator*= ( T div ) { m_MinX*=div; m_MinY*=div; m_MaxX*=div; m_MaxY*=div; return *this; } - - private: - - T m_MinX; - T m_MaxX; - T m_MinY; - T m_MaxY; - -}; - -template<class T> -Box2D<T>::Box2D(T minX, T minY, T maxX, T maxY) -{ - m_MinX=minX; - m_MinY=minY; - m_MaxX=maxX; - m_MaxY=maxY; -} - -template<class T> -void Box2D<T>::clip( Box2D<T> clipArea ) -{ - if (m_MinX < clipArea.minX()) { m_MinX=clipArea.minX(); } - if (m_MinY < clipArea.minY()) { m_MinY=clipArea.minY(); } - if (m_MaxX > clipArea.maxX()) { m_MaxX=clipArea.maxX(); } - if (m_MaxY > clipArea.maxY()) { m_MaxY=clipArea.maxY(); } -} - -template<class T> -bool Box2D<T>::contains( T x, T y ) -{ - return ( (x>=m_MinX) && (x<=m_MaxX) && (y>=m_MinY) && (y<=m_MaxY) ); -} - -template<class T> - void Box2D<T>::expand( T size ) -{ - m_MinX-=size; - m_MaxX+=size; - m_MinY-=size; - m_MaxY+=size; -} - -template<class T> -void Box2D<T>::shrink( T size ) -{ - m_MinX+=size; - m_MaxX-=size; - m_MinY+=size; - m_MaxY-=size; -} - -template<class T> -T Box2D<T>::area() -{ - T width = m_MaxX - m_MinX; - T height = m_MaxY - m_MinY; - - T capacity = width * height; - - return (T) capacity; -} - -template<class T> -void Box2D<T>::enclose( Point2D point ) -{ - if ( m_MinX > point.x() ) { m_MinX=point.x(); } - if ( m_MinY > point.y() ) { m_MinY=point.y(); } - if ( m_MaxX < point.x() ) { m_MaxX=point.x(); } - if ( m_MaxY < point.y() ) { m_MaxY=point.y(); } -} - -template<class T> -void Box2D<T>::enclose( T x, T y ) -{ - if ( m_MinX > x ) { m_MinX=x; } - if ( m_MinY > y ) { m_MinY=y; } - if ( m_MaxX < x ) { m_MaxX=x; } - if ( m_MaxY < y ) { m_MaxY=y; } -} - -template<class T> -template<class OtherT> -void Box2D<T>::enclose( Box2D<OtherT> box ) -{ - enclose( box.minX(), box.minY() ); - enclose( box.maxX(), box.maxY() ); -} - - -template<class T> -std::vector< Point2D > Box2D<T>::vertices() -{ - std::vector<Point2D> myVertices(5); - myVertices[0]=Point2D( m_MinX-0.5, m_MinY-0.5 ); - myVertices[1]=Point2D( m_MinX-0.5, m_MaxY+0.5 ); - myVertices[2]=Point2D( m_MaxX+0.5, m_MaxY+0.5 ); - myVertices[3]=Point2D( m_MaxX+0.5, m_MinY-0.5 ); - myVertices[4]=myVertices[0]; - return myVertices; -} - - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/CMakeLists.txt b/homer_mapping/src/OccupancyMap/Math/CMakeLists.txt deleted file mode 100644 index ff84de22..00000000 --- a/homer_mapping/src/OccupancyMap/Math/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(Math_SRC - Line2D.cpp - Polygon2D.cpp - misc.cpp - Transformation2D.cpp - mat3.cpp - Circle2D.cpp - Pose.cpp - Obb2D.cpp - Matrix.cpp - Math.cpp - Point2D.cpp - Vector3D.cpp - Homography.cpp -) - -add_library(Math ${Math_SRC}) diff --git a/homer_mapping/src/OccupancyMap/Math/Circle2D.cpp b/homer_mapping/src/OccupancyMap/Math/Circle2D.cpp deleted file mode 100644 index edaadf42..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Circle2D.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Circle2D.cpp - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - *******************************************************************************/ - -#include "Circle2D.h" -#include "vec2.h" - -#include <math.h> - -#define THIS Circle2D - -using namespace std; - -THIS::THIS() { - m_Radius=0.0; -} - -THIS::THIS(double x, double y, double radius) { - m_Center=Point2D(x,y); - m_Radius=radius; -} - -THIS::THIS( Point2D center, double radius) { - m_Center=center; - m_Radius=radius; -} - -THIS::~THIS() { -} - -double THIS::x() const{ - return m_Center.x(); -} - -double THIS::y() const{ - return m_Center.y(); -} - -double THIS::radius() const -{ - return m_Radius; -} - -Point2D THIS::center() const -{ - return m_Center; -} - -void THIS::setX(double x) { - m_Center.setX(x); -} - -void THIS::setY(double y) { - m_Center.setY(y); -} - -void THIS::setCenter( Point2D center ) -{ - m_Center=center; -} - -void THIS::setRadius( double radius ) -{ - m_Radius=radius; -} - - -vector<Point2D> THIS::vertices( int steps ) -{ - vector<Point2D> myVertices; - myVertices.reserve( steps+1 ); - for( float alpha=0.0; alpha<M_PI*2; alpha+=M_PI*2/float(steps) ) { - myVertices.push_back( m_Center + CVec2( sin(alpha)*m_Radius, cos(alpha)*m_Radius ) ); - } - myVertices.push_back( m_Center + CVec2( sin(M_PI*2)*m_Radius, cos(M_PI*2)*m_Radius ) ); - return myVertices; -} - - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Circle2D.h b/homer_mapping/src/OccupancyMap/Math/Circle2D.h deleted file mode 100644 index 68f280e5..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Circle2D.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Circle2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id :$ - *******************************************************************************/ - -#ifndef Circle2D_H -#define Circle2D_H - -#include "Point2D.h" -#include <vector> - -/** - * @class Circle2D - * @author David Gossow - */ -class Circle2D { - - public: - - Circle2D(); - - /** Creates a new 2D Circle given by center and radius */ - Circle2D( double x, double y, double radius ); - Circle2D( Point2D center, double radius ); - - /** - * Destructor, does nothing. - */ - ~Circle2D(); - - double x() const; - double y() const; - double radius() const; - Point2D center() const; - - void setX(double x); - void setY(double y); - void setCenter( Point2D center ); - void setRadius( double radius ); - - std::vector<Point2D> vertices( int steps=40 ); - - protected: - - Point2D m_Center; - double m_Radius; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Homography.cpp b/homer_mapping/src/OccupancyMap/Math/Homography.cpp deleted file mode 100644 index 8a2a719e..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Homography.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Homography.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - *******************************************************************************/ - -#include "Homography.h" - -#include <math.h> -#include <string.h> -#include <sstream> - -#define THIS Homography - -THIS::THIS ( double homMat[9] ) -{ - memcpy( m_HomMat, homMat, 9*sizeof(double) ); -} - -THIS::THIS ( const THIS& other ) -{ - memcpy( m_HomMat, other.m_HomMat, 9*sizeof(double) ); -} - -THIS& THIS::operator=( const Homography& other ) -{ - memcpy( m_HomMat, other.m_HomMat, 9*sizeof(double) ); - return *this; -} - -Point2D THIS::transform ( Point2D point2 ) -{ - if ( !point2.isValid() ) - { - return point2; - } - else - { - double x = point2.x(); - double y = point2.y(); - double Z = 1. / ( m_HomMat[6] * x + m_HomMat[7] * y + m_HomMat[8] ); - double X = ( m_HomMat[0] * x + m_HomMat[1] * y + m_HomMat[2] ) * Z; - double Y = ( m_HomMat[3] * x + m_HomMat[4] * y + m_HomMat[5] ) * Z; - return Point2D( X, Y ); - } -} - -void THIS::transform ( std::vector<Point2D>& points2, std::vector<Point2D> &projPoints ) -{ - projPoints.reserve( points2.size() ); - - // Translate src_corners to dst_corners using homography - for ( unsigned i = 0; i < points2.size(); i++ ) - { - if ( !points2[i].isValid() ) - { - projPoints.push_back( points2[i] ); - } - else - { - double x = points2[i].x(); - double y = points2[i].y(); - double Z = 1. / ( m_HomMat[6] * x + m_HomMat[7] * y + m_HomMat[8] ); - double X = ( m_HomMat[0] * x + m_HomMat[1] * y + m_HomMat[2] ) * Z; - double Y = ( m_HomMat[3] * x + m_HomMat[4] * y + m_HomMat[5] ) * Z; - projPoints.push_back( Point2D( X, Y ) ); - } - } -} - -bool THIS::checkValidity ( std::vector<Point2D>& points2 ) -{ - // Translate src_corners to dst_corners using homography - for ( unsigned i = 0; i < points2.size(); i++ ) - { - if ( !points2[i].isValid() ) - { - continue; - } - else - { - double x = points2[i].x(); - double y = points2[i].y(); - double Z = 1. / ( m_HomMat[6] * x + m_HomMat[7] * y + m_HomMat[8] ); - if ( Z < 0 ) - { - return false; - } - } - } - return true; -} - -std::string THIS::toString() -{ - std::ostringstream s; - for ( int j=0; j< 3; j++ ) - { - for ( int i=0; i< 3; i++ ) - { - s << m_HomMat[i+3*j] << " "; - } - s << std::endl; - } - return s.str(); -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Homography.h b/homer_mapping/src/OccupancyMap/Math/Homography.h deleted file mode 100644 index c8829e92..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Homography.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * CvHomography.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - *******************************************************************************/ - -#ifndef Homography_H -#define Homography_H - -#include "Point2D.h" -#include <vector> - -/** - * @class Homography - * @brief Represents a homography - * @author David Gossow - */ -class Homography -{ - public: - - Homography( ) {} - - Homography( double homMat[9] ); - - Homography( const Homography& other ); - - Homography& operator=( const Homography& other ); - - /** Transform point2 using the homography */ - Point2D transform ( Point2D point2 ); - - /** Transform keyPoints2 using the homography and store them in projPoints - * @return if one of the resulting points has z<0, that means it would lie behind the camera, return false - */ - void transform ( std::vector<Point2D>& points2, std::vector<Point2D> &projPoints ); - - /// @return true if all the given points lie in front of the camera (z>0) - bool checkValidity ( std::vector<Point2D>& points2 ); - - std::string toString(); - - // private: // FIXME made public to create ROS message - - double m_HomMat[9]; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Line2D.cpp b/homer_mapping/src/OccupancyMap/Math/Line2D.cpp deleted file mode 100644 index f5807c31..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Line2D.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * Line2D.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Information on Code Review state: - * Author: SM; DevelTest: Date; Reviewer: Initials; Review: Date; State: NOK - * - * Additional information: - * $Id: Line2D.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#include "Line2D.h" -#include "vec2.h" - -#define THIS Line2D - -float THIS::gradient() const -{ - float gradient = 10000000.0; - if ( m_Vec[0] != 0.0 ) - { - gradient = m_Vec[1]/m_Vec[0]; - } - return gradient; -} - -std::vector< Point2D > THIS::vertices ( unsigned substeps ) -{ - unsigned steps = substeps+2; - std::vector<Point2D> myVertices ( steps ); - for ( unsigned i=0; i<steps; i++ ) - { - float t= float ( i ) / float ( steps-1 ); - myVertices[i] = m_Start + t*m_Vec; - } - return myVertices; -} - -Point2D THIS::getClosestPoint ( Point2D point ) const -{ - float t = ( point-m_Start ) * m_Vec; - t /= m_Vec * m_Vec; - if ( t > 1.0 ) - { - t = 1.0; - } - else if ( t < 0.0 ) - { - t = 0.0; - } - Point2D pointOnLine = m_Start + ( t * m_Vec ); - return pointOnLine; -} - -Point2D THIS::getIntersectionPoint ( Line2D line ) const -{ - Point2D intersecPoint; - double det1 = m_Vec.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * m_Vec.y(); - // lines are not parallel - if ( det1 != 0 ) - { - CVec2 startToStart = line.start() -m_Start; - // calculate intersection - double lambda = ( startToStart.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * startToStart.y() ) / det1; - intersecPoint = m_Start + lambda* m_Vec; - } - - return intersecPoint; -} - -float THIS::getIntersectionPointParameter ( Line2D line ) const -{ - double lambda = 0.0; - double det1 = m_Vec.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * m_Vec.y(); - // lines are not parallel - if ( det1 != 0 ) - { - CVec2 startToStart = line.start() -m_Start; - // calculate intersection - lambda = ( startToStart.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * startToStart.y() ) / det1; - } - - return lambda; -} - -std::string THIS::toString() const -{ - std::ostringstream str; -// str << "Startpoint: " << m_Start.x() << " " << m_Start.y() << " Endpoint: " << end().x() << " " << end().y() << -// " Vector: " << m_Vec.x() << " " << m_Vec.y() << " "; - str << m_Start.x() << " " << m_Start.y() << std::endl << end().x() << " " << end().y() << std::endl; - return str.str(); -} - diff --git a/homer_mapping/src/OccupancyMap/Math/Line2D.h b/homer_mapping/src/OccupancyMap/Math/Line2D.h deleted file mode 100644 index e8c210bb..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Line2D.h +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * Line2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Information on Code Review state: - * Author: SM; DevelTest: Date; Reviewer: Initials; Review: Date; State: NOK - * - * Additional information: - * $Id: Line2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef LINE2D_H -#define LINE2D_H - -#include "vec2.h" -#include "mat2.h" -#include "Point2D.h" -#include <vector> - -/** - * @class Line2D - * - * @author Susanne Maur - * - */ -class Line2D -{ - - public: - - /** - * Creates a new line. - * @param start Start point of the line. - * @param end End point of the line. - */ - inline Line2D ( Point2D start, Point2D end ) - { - m_Start = start; - m_Vec = end-m_Start; - } - - - /** - * Creates a new line. - * @param start Start point of the line. - * @param vec The vector from start to end point of the line. - */ - inline Line2D ( Point2D start, CVec2 vec ) - { - m_Start = start; - m_Vec = vec; - } - - /** - * Destructor does nothing. - */ - inline ~Line2D() {} - - /** - * Sets the start point of the line to a new value. - * @param start Start point of the line. - */ - inline void setStart ( const Point2D start ) - { - Point2D end = m_Start + m_Vec; - m_Start = start; - m_Vec = end-m_Start; - } - - /** - * Sets the end point of the line to a new value. - * @param end End point of the line. - */ - - inline void setEnd ( const Point2D end ) - { - m_Vec = end - m_Start; - } - - /** - * Returns the start point of the line. - * @return Start point of the line. - */ - inline Point2D start() const - { - return m_Start; - } - - /** - * Returns the end point of the line. - * @return End point of the line. - */ - inline Point2D end() const - { - return m_Start + m_Vec; - } - - /** - * Returns a vector from the start to the end of the line. - * @return Vector to the end point of the line. - */ - inline CVec2 vec() const - { - return m_Vec; - } - - inline bool operator== ( const Line2D& line ) const - { - return ( m_Start == line.start() && end() == line.end() ); - } - - /** - * Returns the gradient of the line. - * @return Gradient of the line. - */ - float gradient() const ; - - /** - * Returns the length of the line. - * @return Length of the line. - */ - inline float length() const { - return m_Vec.magnitude(); - } - - /** - * Returns the minimum euclidean distance of the given point to the line. - * @param point Point of which the distance to the line will be calculated. - * @return Distance of point to line. - */ - inline float distance ( Point2D point ) const - { - Point2D pointOnLine = getRootPoint ( point ); - return ( point - pointOnLine ).magnitude(); - } - - /** - * Rotates the line round the origin. - * @param angle The angle of rotation in radiants. - */ - inline void rotate ( float angle ) - { - CMat2 rotMat = CMat2 ( angle ); - m_Start = rotMat * m_Start; - m_Vec = rotMat * m_Vec; - } - - /** - * Returns the point of the line with the minimal distance to a given point. - * This algorithm may return a point which lies on the extension of the line and not on itself. - * See also: getClosestPoint. - * @param point Point to which the distance is calculated. - * @return Root point of the line. - */ - inline Point2D getRootPoint ( Point2D point ) const - { - float t = ( point-m_Start ) * m_Vec; - t /= m_Vec * m_Vec; - Point2D pointOnLine = m_Start + ( t * m_Vec ); - return pointOnLine; - } - - /** - * Returns the normal of the line. - * @return Normal of the line. - */ - inline CVec2 getNormal() const { - return m_Vec.getNormal()/m_Vec.magnitude(); - } - - /** - * Returns the point of the line with the minimal distance to a given point. - * This algorithm returns always a point which lies on the line. - * Therefor it is not always the root point. - * See also: getRootPoint. - * @param point Point to which the distance is calculated. - * @return Root point of the line. - */ - Point2D getClosestPoint ( Point2D point ) const; - - /** - * Returns the intersection point of this line with a second line. - * The intersection point is element of this line. - * @param line The line with which the intersection is calculated. - * @return Intersection point. - */ - Point2D getIntersectionPoint ( Line2D line ) const; - - /** - * Returns the parameter t which identifies the intersection point of this line with a second line. - * The intersection point is element of this line. - * @param line The line with which the intersection is calculated. - * @return Parameter t which identifies the intersection point on the line. - */ - float getIntersectionPointParameter ( Line2D line ) const; - - /** - * @return Vertices, e.g. for use in a VectorObject - * @param substeps number of linear interpolation steps between start and end - */ - std::vector< Point2D > vertices ( unsigned substeps=0 ); - - /** - * @overwrite - */ - std::string toString() const; - - private: - - /** - * Start point of the line. - */ - Point2D m_Start; - - /** - * Vector from the start to the end of the line. - */ - CVec2 m_Vec; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Math.cpp b/homer_mapping/src/OccupancyMap/Math/Math.cpp deleted file mode 100644 index 3f31c5bf..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Math.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * Math.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include <limits.h> -#include "Math.h" -#include <math.h> - -#include "vec2.h" - -#define THIS Math - -THIS::THIS() -{ -} - -THIS::~THIS() -{ -} - -float THIS::meanAngle( const std::vector<float>& angles ) -{ - //calculate vectors from angles - CVec2 vectorSum(0,0); - for ( unsigned i=0; i<angles.size(); i++ ) - { - vectorSum = vectorSum + CVec2( cos( angles[i] ), sin ( angles[i] ) ); - } - //return vectorSum.getAngle( CVec2(1,0) ); - if ( vectorSum.magnitude() == 0 ) { return 0; } - return atan2( vectorSum.y(), vectorSum.x() ); -} - - -float THIS::meanAngleWeighted( const std::vector< WeightedValue >& weightedAngles ) -{ - //calculate vectors from angles - CVec2 vectorSum(0,0); - for ( unsigned i=0; i<weightedAngles.size(); i++ ) - { - vectorSum = vectorSum + weightedAngles[i].weight * CVec2( cos( weightedAngles[i].value ), sin ( weightedAngles[i].value ) ); - } - //return vectorSum.getAngle( CVec2(1,0) ); - if ( vectorSum.magnitude() == 0 ) { return 0; } - return atan2( vectorSum.y(), vectorSum.x() ); -} - - -float THIS::angleVariance( float meanAngle, const std::vector<float>& angles ) -{ - float quadSum=0; - for( unsigned i=0; i < angles.size(); i++ ) - { - float turnAngle=minTurnAngle( angles[i], meanAngle ); - quadSum += turnAngle*turnAngle; - } - return quadSum / float ( angles.size() ); -} - - -float THIS::minTurnAngle( float angle1, float angle2 ) -{ -/* CVec2 vector1( cos( angle1 ), sin ( angle1 ) ); - CVec2 vector2( cos( angle2 ), sin ( angle2 ) ); - return vector1.getAngle( vector2 ); - */ - angle1 *= 180.0/M_PI; - angle2 *= 180.0/M_PI; - //if(angle1 < 0) angle1 += M_PI * 2; - //if(angle2 < 0) angle2 += M_PI * 2; - int diff= angle2 - angle1; - diff = (diff + 180) % 360 - 180; - - //float sign=1; - //if ( diff < 0 ) { sign=-1; } - //minimal turn angle: - //if the absolute difference is above 180°, calculate the difference in other direction - //if ( fabs(diff) > M_PI ) { - // diff = 2*M_PI - fabs(diff); - // diff *= sign; - //} - - float ret = static_cast<double>(diff) * M_PI/180.0; - return ret; -} - -Point2D THIS::center( std::vector<Point2D>& points ) -{ - double numPoints = double( points.size() ); - double sumX=0, sumY=0; - for( unsigned i=0; i < points.size(); i++ ) - { - sumX += points[i].x(); - sumY += points[i].y(); - } - return Point2D( sumX / numPoints, sumY / numPoints ); -} - - -double THIS::randomGauss(float variance) -{ - if (variance < 0) { - variance = -variance; - } - double x1, x2, w, y1; - do { - x1 = 2.0 * random01() - 1.0; - x2 = 2.0 * random01() - 1.0; - w = x1 * x1 + x2 * x2; - } while ( w >= 1.0 ); - - w = sqrt((-2.0 * log(w)) / w); - y1 = x1 * w; - // now y1 is uniformly distributed - return sqrt(variance) * y1; -} - -double THIS::random01(unsigned long init) -{ - static unsigned long n; - if (init > 0) { - n = init; - } - n = 1664525 * n + 1013904223; - // create double from unsigned long - return (double)(n/2) / (double)LONG_MAX; -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Math.h b/homer_mapping/src/OccupancyMap/Math/Math.h deleted file mode 100644 index bf00135a..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Math.h +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Math.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#ifndef Math_H -#define Math_H - -#include <vector> -#include "Point2D.h" - -/** - * @class Math - * @brief Generic math and statistics functions - * @author David Gossow (RX) - */ -class Math -{ - public: - - struct WeightedValue - { - float value; - float weight; - }; - - static const double Pi = 3.14159265358979323846; - - /** @return mean value */ - template<class ContainerT> - static double mean ( const ContainerT& values ); - - /** @return variance of given values */ - template<class ContainerT> - static double variance ( const ContainerT& values ); - - /** @return mean angle of given values - * @note there are always two possible choices for the mean angle. This function returns the one with the smallest deviation - * @note Works for angles in [-Pi..Pi], negative angles are treated - */ - static float meanAngle ( const std::vector<float>& angles ); - - static float meanAngleWeighted ( const std::vector< WeightedValue >& weightedAngles ); - - /** @return variance for given mean */ - static float angleVariance ( float meanAngle, const std::vector<float>& angles ); - - /** @return minimal angle needed to turn from angle 1 to angle 2 [-Pi..Pi] */ - static float minTurnAngle ( float angle1, float angle2 ); - - static Point2D center ( std::vector<Point2D>& points ); - - static float deg2Rad ( float deg ) { return deg / 180.0*Pi; } - - static float rad2Deg ( float rad ) { return rad / Pi*180.0; } - - static double randomGauss ( float variance = 1.0 ); - - static double random01 ( unsigned long init = 0 ); - - /** @return ratio between one dimension seen under old viewangle and dimension under new viewangle*/ - static double angleToPercent ( double newAngle, double oldAngle ) { return tan ( ( Pi / 180.0 ) * newAngle / 2 ) / tan ( ( Pi / 180.0 ) * oldAngle / 2 ); }; - - /** @return angle under which the ratio between dimension seen under old viewangle and new viewangle equals percent*/ - static double percentToAngle ( double percent, double angle ) { return 2* atan ( tan ( ( Pi / 180.0 ) * angle / 2 ) * percent ) * ( 180 / Pi ); }; - - /** @return horizontal view angle corresponding to diagonal view angle and aspect ratio (e.g. 4.0/3.0)*/ - static double horizontalViewAngle ( double diagonalAngle, double aspectRatio ) { return verticalViewAngle ( diagonalAngle, 1.0 / aspectRatio ); }; - - /** @return vertical view angle corresponding to diagonal view angle and aspect ratio (e.g. 4.0/3.0)*/ - static double verticalViewAngle ( double diagonalAngle, double aspectRatio ) - { - return percentToAngle ( 1.0 / sqrt ( pow ( aspectRatio, 2 ) + 1.0 ), diagonalAngle ); - }; - - template<class ValueT> - static inline ValueT min ( ValueT a, ValueT b ) { return a < b ? a : b; } - - template<class ValueT> - static inline ValueT max ( ValueT a, ValueT b ) { return a > b ? a : b; } - - private: - - /** @brief The constructor */ - Math(); - - /** @brief The destructor */ - ~Math(); - -}; - -template<class ContainerT> -double Math::mean ( const ContainerT& values ) -{ - typename ContainerT::const_iterator it; - it = values.begin(); - double sum = 0; - while ( it != values.end() ) - { - sum += *it; - it++; - } - return sum / double ( values.size() ); -} - - -template<class ContainerT> -double Math::variance ( const ContainerT& values ) -{ - double mean = mean ( values ); - typename ContainerT::const_iterator it; - it = values.begin(); - double sum = 0; - while ( it != values.end() ) - { - double diff = *it - mean; - sum += diff * diff; - it++; - } - return sum / double ( values.size() ); -} - - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Matrix.cpp b/homer_mapping/src/OccupancyMap/Math/Matrix.cpp deleted file mode 100644 index abe38365..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Matrix.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * Matrix.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include "Matrix.h" - -#define THIS Matrix - -THIS THIS::transpose() { - Matrix newMatrix(m_Columns, m_Lines); - for (unsigned i = 0; i < m_Lines*m_Columns; i++) { - newMatrix.setValue(i/m_Columns, i%m_Lines, m_Values[i/m_Lines * i%m_Columns]); - } - return newMatrix; -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Matrix.h b/homer_mapping/src/OccupancyMap/Math/Matrix.h deleted file mode 100644 index 89f5f39a..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Matrix.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * Matrix.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#ifndef MATRIX_H -#define MATRIX_H - -#include "mat2.h" -#include "mat3.h" - -/** - * @class Matrix - * @brief This class describes a Matrix - * @author Michael Dahl - */ -class Matrix -{ - public: - - /** @brief The constructor */ - Matrix(unsigned lines, unsigned columns){ - m_Lines = lines; - m_Columns = columns; - m_Values = new double[lines*columns]; - for (unsigned i = 0; i< lines*columns; i++) { - m_Values[i] = 0; - } - } - - Matrix(const CMat2 matrix2) { - m_Lines = 2; - m_Columns = 2; - m_Values = new double[4]; - for(unsigned i = 0; i < m_Lines * m_Columns; i++) { - m_Values[i] = matrix2.valueAt(i); - } - } - - Matrix(const CMat3 matrix3) { - m_Lines = 3; - m_Columns = 3; - m_Values = new double[9]; - for(unsigned i = 0; i < m_Lines * m_Columns; i++) { - m_Values[i] = matrix3.valueAt(i); - } - } - - /** @brief The destructor */ - ~Matrix() { - delete[] m_Values; - } - - inline double getValue(int line, int column) const{ - return m_Values[line*m_Columns + column]; - } - - inline void setValue(int line, int column, double value) { - m_Values[line*m_Columns + column] = value; - } - - Matrix transpose(); - - Matrix operator *(double scalar){ - Matrix returnMatrix(m_Lines, m_Columns); - for (unsigned i = 0; i < m_Lines * m_Columns; i++) { - returnMatrix.setValue(i/m_Lines, i%m_Lines, this->getValue(i/m_Lines, i%m_Lines) * scalar); - } - return returnMatrix; - } - - Matrix operator /(double scalar){ - Matrix returnMatrix(m_Lines, m_Columns); - for (unsigned i = 0; i < m_Lines * m_Columns; i++) { - returnMatrix.setValue(i/m_Lines, i%m_Lines, this->getValue(i/m_Lines, i%m_Lines) / scalar); - } - return returnMatrix; - } - - Matrix operator *(const Matrix rhs){ - Matrix returnMatrix(m_Lines, m_Columns); - for (unsigned i = 0; i < m_Lines * m_Columns; i++) { - returnMatrix.setValue(i/m_Lines, i%m_Lines, this->getValue(i/m_Lines, i%m_Lines) * rhs.getValue(i%m_Lines, i/m_Lines)); - } - return returnMatrix; - } - - Matrix operator +(const Matrix rhs){ - Matrix returnMatrix(m_Lines, m_Columns); - for (unsigned i = 0; i < m_Lines * m_Columns; i++) { - returnMatrix.setValue(i/m_Lines, i%m_Lines, this->getValue(i/m_Lines, i%m_Lines) + rhs.getValue(i/m_Lines, i%m_Lines)); - } - return returnMatrix; - } - - Matrix operator -(const Matrix rhs){ - Matrix returnMatrix(m_Lines, m_Columns); - for (unsigned i = 0; i < m_Lines * m_Columns; i++) { - returnMatrix.setValue(i/m_Lines, i%m_Lines, this->getValue(i/m_Lines, i%m_Lines) - rhs.getValue(i/m_Lines, i%m_Lines)); - } - return returnMatrix; - } - - private: - - unsigned int m_Lines; - unsigned int m_Columns; - double* m_Values; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Obb2D.cpp b/homer_mapping/src/OccupancyMap/Math/Obb2D.cpp deleted file mode 100755 index 9d4a2ae8..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Obb2D.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include <stdlib.h> - - -#include "Obb2D.h" -#include <iostream> - -//---------------------------------------------------------------------------------------------------------- -OBB2D::OBB2D() -{ -} -//---------------------------------------------------------------------------------------------------------- -OBB2D::~OBB2D() -{ -} -//---------------------------------------------------------------------------------------------------------- -std::pair<CVec2,CVec2> OBB2D::computeAABB() const -{ - CVec2 mins(999999,999999); - CVec2 maxs(-999999,-999999); - for (int i=0;i<4;i++) - { - if (mPoints[i][0]<mins[0]) mins[0]=mPoints[i][0]; - if (mPoints[i][1]<mins[1]) mins[1]=mPoints[i][1]; - if (mPoints[i][0]>maxs[0]) maxs[0]=mPoints[i][0]; - if (mPoints[i][1]>maxs[1]) maxs[1]=mPoints[i][1]; - } - return std::make_pair(mins,maxs); -} -//---------------------------------------------------------------------------------------------------------- -// Polygon an Kante (clipStart, clipEnd) clippen, Originalpunkte werden ueberschrieben -int clipEdge(const CVec2* points, int numPoints, const CVec2& clipStart, const CVec2& clipEnd, CVec2* dest) -{ - int result=0; - - // Normale zeigt nach aussen - CVec2 n(clipEnd[1] - clipStart[1], - clipStart[0] - clipEnd[0]); - - //n=n*(-1); - - float d0=clipStart*n; - - int i=numPoints-1; - for (int iNext=0;iNext<numPoints;iNext++) - { - const CVec2& a=points[i]; - const CVec2& b=points[iNext]; - - float adotn=a*n; - float bdotn=b*n; - float da=adotn-d0; - float db=bdotn-d0; - - if (da<=0) - { - if (db<=0) - { - // beide innerhalb - //outputPoints.push_back(b); - dest[result++]=b; - } - else - { - // a drinnen, b draussen => schnittpunkt - float t=-da/(bdotn-adotn); - //outputPoints.push_back(a+t*(b-a)); - dest[result++]=a+t*(b-a); - } - } - else - { - if (db<=0) - { - // a draussen, b drinnen => schnittpunkt - float t=-da/(bdotn-adotn); - //outputPoints.push_back(a+t*(b-a)); - //outputPoints.push_back(b); - dest[result++]=a+t*(b-a); - dest[result++]=b; - } - else - { - // beide ausserhalb - } - } - - i=iNext; - } - - return result; -} -//---------------------------------------------------------------------------------------------------------- -float OBB2D::computeClippedArea(const OBB2D& clipPoly) -{ - CVec2* tmp1=(CVec2*)alloca(20*sizeof(CVec2)); - CVec2* tmp2=(CVec2*)alloca(20*sizeof(CVec2)); - - int res=0; - - res=clipEdge(mPoints,4,clipPoly[3],clipPoly[0],tmp1); - res=clipEdge(tmp1,res,clipPoly[0],clipPoly[1],tmp2); - res=clipEdge(tmp2,res,clipPoly[1],clipPoly[2],tmp1); - res=clipEdge(tmp1,res,clipPoly[2],clipPoly[3],tmp2); - - /* - static int maxres=0; - if (res>=maxres) - { - std::cout << "res: " << res << std::endl; - maxres=res; - }*/ - - - float area=0; - for (int i=0;i<res;i++) - { - area+=(tmp2[i][1]+tmp2[(i+1)%res][1])*(tmp2[i][0]-tmp2[(i+1)%res][0]); - } - area=0.5f*fabs(area); - return area; -} -//---------------------------------------------------------------------------------------------------------- -/*float Polygon2D::computeArea() const -{ -#if 0 - float area=0; - CVec2 last=mPoints[1]; - for (int i=2;i<mPoints.size();i++) - { - CVec2 a=last-mPoints[0]; - CVec2 b=mPoints[i]-mPoints[0]; - area+=0.5f*fabs(a.x*b.y-a.y*b[0]); - - last=mPoints[i]; - } - return area; -#else - float area2=0; - for (int i=0;i<mPoints.size();i++) - { - area2+=(mPoints[i][1]+mPoints[(i+1)%mPoints.size()][1])*(mPoints[i][0]-mPoints[(i+1)%mPoints.size()][0]);//mPoints[i].x*mPoints[i+1].y-mPoints[i+1].x*mPoints[i][1]; - } - area2=0.5f*fabs(area2); - //std::cout << "area: " << area << " " << area2 << std::endl; - return area2; -#endif -}*/ -//---------------------------------------------------------------------------------------------------------- - diff --git a/homer_mapping/src/OccupancyMap/Math/Obb2D.h b/homer_mapping/src/OccupancyMap/Math/Obb2D.h deleted file mode 100755 index ec7313ab..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Obb2D.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _OBB2D_H -#define _OBB_H - -#include "vec2.h" -#include <vector> - -/** - * Obolete. Used by Robbie 9 for line clipping. - * Bad documentation. For questions ask F. Neuhaus. - */ - -class OBB2D -{ - public: - - OBB2D(); - ~OBB2D(); - - CVec2& operator[](int i) { return mPoints[i]; }; - const CVec2& operator[](int i) const { return mPoints[i]; }; - - float computeClippedArea(const OBB2D& clipPoly); - - std::pair<CVec2,CVec2> computeAABB() const; - - - private: - - CVec2 mPoints[4]; -}; - -#endif - diff --git a/homer_mapping/src/OccupancyMap/Math/Pixel.h b/homer_mapping/src/OccupancyMap/Math/Pixel.h deleted file mode 100644 index 026fd3a6..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Pixel.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Pixel.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pixel.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef PIXEL_H -#define PIXEL_H - -#include "Point2D.h" -#include <vector> - -/** @class Pixel - * @brief Stores discrete pixel coordinates - * @author Stephan Wirth, David Gossow (RX) - */ -class Pixel { - - public: - - inline Pixel( int x = 0, int y = 0) { m_X = x; m_Y = y; }; - inline ~Pixel() {}; - - inline int x() const { return m_X; } - inline int y() const { return m_Y; } - - inline void setX( int x ) { m_X = x; } - inline void setY( int y ) { m_Y = y; } - - inline bool operator ==( Pixel& rhs ) { return ( m_X == rhs.m_X ) && ( m_Y == rhs.m_Y ); } - inline bool operator !=( Pixel& rhs ) { return ( m_X != rhs.m_X ) || ( m_Y != rhs.m_Y ); } - inline Pixel operator *( float rhs ) { return Pixel( m_X * rhs, m_Y * rhs ); } - inline Pixel operator /( float rhs ) { return Pixel( m_X / rhs, m_Y / rhs ); } - - inline Point2D toPoint2D() { return Point2D( m_X, m_Y ); } - - inline std::vector<Point2D> vertices() - { - std::vector<Point2D> result(5); - result[0]=Point2D( m_X-0.5, m_Y-0.5 ); - result[1]=Point2D( m_X+0.5, m_Y-0.5 ); - result[2]=Point2D( m_X+0.5, m_Y+0.5 ); - result[3]=Point2D( m_X-0.5, m_Y+0.5 ); - result[4]=result[0]; - return result; - } - - private: - - int m_X; - int m_Y; - -}; - - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Point2D.cpp b/homer_mapping/src/OccupancyMap/Math/Point2D.cpp deleted file mode 100644 index c8ae09b7..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Point2D.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Point2D.cpp - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include "Point2D.h" - -#define THIS Point2D - -float THIS::getPolarAngle () const -{ - float angle = atan ( m_Y /m_X ); - if ( m_X < 0 ) - { - angle = - ( M_PI - angle ); - } - while ( angle >= M_PI ) - { - angle -= 2*M_PI; - } - while ( angle < -M_PI ) - { - angle += 2*M_PI; - } - return angle; -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Point2D.h b/homer_mapping/src/OccupancyMap/Math/Point2D.h deleted file mode 100644 index 94810ef9..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Point2D.h +++ /dev/null @@ -1,312 +0,0 @@ -/******************************************************************************* - * Point2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Point2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#include "vec2.h" -#include <float.h> - -#ifndef POINT2D_H -#define POINT2D_H - -/** - * @class Point2D - * - * @author Susanne Maur - * - */ -class Point2D -{ - - public: - - /** - * Creates a new point in 2D with x- and y-coordinat set to zero. - */ - inline Point2D() - { - m_X = 0.0; - m_Y = 0.0; - } - - /** - * Creates a new point in 2D. - * @param x x-coordinate of the point. - * @param y y-coordinate of the point. - */ - inline Point2D ( double x, double y ) - { - m_X = x; - m_Y = y; - } - - - - /** - * Copy construcor - */ - inline Point2D (const Point2D& p){ - m_X = p.x(); - m_Y = p.y(); - } - - /** - * Creates a new point in 2D. - * @param v Vector form origin to the point. - */ - inline Point2D ( const CVec2& v ) - { - m_X = v[0]; - m_Y = v[1]; - } - - /** - * Destructor, does nothing. - */ - inline ~Point2D() - { - } - - /** - * Returns the x-coordinate of the point. - * @return the x-coordinate of the point. - */ - inline double x() const - { - return m_X; - } - - /** - * Returns the y-coordinate of the point. - * @return the y-coordinate of the point. - */ - inline double y() const - { - return m_Y; - } - - /** - * Sets the x- and y-coordinate of the point to new values. - * @param x the new value of the x coordinate. - * @param y the new value of the x coordinate. - */ - inline void set ( double x, double y ) - { - m_X = x; - m_Y = y; - } - - /** - * Sets the x-coordinate of the point to a new value. - * @param x the new value of the x coordinate. - */ - inline void setX ( double x ) - { - m_X = x; - } - - /** - * Sets the y-coordinate of the point to a new value. - * @param y the new value of the x coordinate. - */ - inline void setY ( double y ) - { - m_Y = y; - } - - /** - * Overloaded operators. - */ - - inline Point2D& operator= ( const Point2D& p) { - m_X = p.x(); - m_Y = p.y(); - return *this; - } - - inline Point2D operator+ ( const CVec2& v ) const - { - return Point2D ( m_X + v[0], m_Y + v[1] ); - } - - inline Point2D operator+ ( const Point2D& p ) const - { - return Point2D ( m_X + p.x(), m_Y + p.y() ); - } - - inline CVec2 operator- ( const Point2D& p ) const - { - return CVec2 ( m_X - p.x(), m_Y - p.y() ); - } - - inline Point2D operator- ( const CVec2& v ) const - { - return Point2D ( m_X - v[0], m_Y - v[1] ); - } - - inline Point2D operator* ( double scalar ) const - { - return Point2D ( m_X * scalar, m_Y * scalar ); - } - - inline Point2D operator/ ( double scalar ) const - { - return Point2D ( m_X / scalar, m_Y / scalar ); - } - - inline Point2D& operator+= ( const CVec2& v ) - { - m_X += v[0]; - m_Y += v[1]; - return ( *this ); - } - - inline Point2D& operator-= ( const CVec2& v ) - { - m_X -= v[0]; - m_Y -= v[1]; - return ( *this ); - } - - inline Point2D& operator*= ( double scalar ) - { - m_X *= scalar; - m_Y *= scalar; - return ( *this ); - } - - inline Point2D& operator/= ( double scalar ) - { - m_X /= scalar; - m_Y /= scalar; - return ( *this ); - } - - inline double operator [] ( unsigned int i ) const - { - return ( ( double* ) this ) [i]; - } - - inline double& operator [] ( unsigned int i ) - { - return ( ( double* ) this ) [i]; - } - - inline bool operator== ( const Point2D& point ) const - { - return ( fabs(m_X - point.x()) < 0.001 && fabs(m_Y - point.y()) < 0.001 ); - } - - inline bool operator!= ( const Point2D& point ) const - { - return !((*this)== point); - } - - /** - * Returns the distance to a given point. - * @param point The point to calculate the distance to. - * @return the distance between point the two points. - */ - inline double distance ( const Point2D& point ) const - { - return sqrt ( ( m_X-point.x() ) * ( m_X-point.x() ) + ( m_Y-point.y() ) * ( m_Y-point.y() ) ); - } - - /** - * Returns the distance to origin. - * @return the distance between point the two points. - */ - inline double distance ( ) const - { - return sqrt ( m_X * m_X + m_Y * m_Y ); - } - - /** - * Checks whether two points are equal. - * @param p The point to check equality. - * @return true if points are equal, false otherwise. - */ - inline bool equal ( const Point2D& point ) const - { - if ( ( *this - point ).magnitude() < 0.0001 ) - { - return true; - } - else - { - return false; - } - } - - /** - * Returns the vector which represents the point in 2D. - * @return vector which represents the point in 2D. - */ - inline CVec2 toVector() const - { - return CVec2 ( m_X, m_Y ); - } - - /** - * Returns the angle of the corresponding polar coordinates. - * @return polar angle. - */ - float getPolarAngle () const; - - /** - * Rotate by angle (in radiants) around center. - * @param center Center of rotation - * @param angle Angle in radiants - */ - inline void rotate ( const Point2D& center, float angle ) - { - double x0=m_X-center.m_X; - double y0=m_Y-center.m_Y; - double xRot = x0*cos ( angle ) - y0*sin ( angle ); - double yRot = x0*sin ( angle ) + y0*cos ( angle ); - m_X = xRot+center.m_X; - m_Y = yRot+center.m_Y; - } - - /** - * Rotate by angle (in radiants) around (0,0). - * @param angle Angle in radiants - */ - inline void rotate ( float angle ) - { - double xRot = m_X*cos ( angle ) - m_Y*sin ( angle ); - double yRot = m_X*sin ( angle ) + m_Y*cos ( angle ); - m_X = xRot; - m_Y = yRot; - } - - /** - * Returns the string representation of the point. - * @return string representation of the point. - */ - inline std::string toString() const - { - std::ostringstream str; - str << m_X << " " << m_Y; - return str.str(); - } - - /** @return "invalid" Point (used as end marker in vector drawings) **/ - static Point2D invalidPoint() { return Point2D( DBL_MAX, DBL_MAX ); } - - bool isValid() { return ( ( m_X != DBL_MAX ) || ( m_Y != DBL_MAX ) ); } - - protected: - - double m_X; - double m_Y; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Polygon2D.cpp b/homer_mapping/src/OccupancyMap/Math/Polygon2D.cpp deleted file mode 100644 index 0c5d5e52..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Polygon2D.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************* - * Polygon2D.cpp - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: Polygon2D.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <stdlib.h> -#include "Polygon2D.h" -#include "Point2D.h" -#include "Line2D.h" - - -#define THIS Polygon2D - -using namespace std; - -vector<Line2D> THIS::getLines() const -{ - vector<Line2D> lines; - vector<Point2D>::const_iterator pointIt = m_Points.begin() +1; - while ( pointIt != m_Points.end() ) - { - lines.push_back ( Line2D ( * ( pointIt-1 ), *pointIt ) ); - pointIt++; - } - lines.push_back ( Line2D ( * ( m_Points.end()-1 ), *m_Points.begin() ) ); - - return lines; -} - -void THIS::clipLines ( std::vector<Line2D>& linesToClip ) const -{ - // for each line to clip - vector<Line2D>::iterator linesIt = linesToClip.begin(); - while ( linesIt != linesToClip.end() ) - { - if ( !clipLine ( *linesIt ) ) - { - // line lies completely outside of the polygon - linesToClip.erase ( linesIt ); - continue; - } - linesIt++; - } -} - -bool THIS::clipLine ( Line2D& lineToClip ) const -{ - vector<Line2D> polygonLines = getLines(); - CVec2 v = lineToClip.vec(); - - float tIn = 0.0; - float tOut = 1.0; - - // for each line of the polygon - vector<Line2D>::const_iterator polygonIt = polygonLines.begin(); - while ( polygonIt != polygonLines.end() ) - { - CVec2 n = ( *polygonIt ).getNormal(); -// cout << "polLine "<< ( *polygonIt ).toString() << endl; -// cout << "n "<< n.toString() << endl; - - CVec2 w0 = lineToClip.start()- ( *polygonIt ).start(); - CVec2 w1 = lineToClip.end()- ( *polygonIt ).start(); - -// cout << "w0 " <<w0.toString() << endl; -// cout << "w1 " <<w1.toString() << endl; - - float c0 = w0.dot ( n ); - float c1 = w1.dot ( n ); - - // test if line lies completely inside - if ( c0 < 0 && c1 < 0 ) - { - // do nothing; - polygonIt++; - continue; - } - // test if line lies completely outside - else if ( c0 >= 0 && c1 >= 0 ) - { -/* cout << "return 1" << endl;*/ - return false; - } - // clip lines - else - { - float denominator = v.dot ( n ); - - if ( denominator == 0 ) - { - // impossible to happen - polygonIt++; - continue; - } - - float t = -c0/denominator; - - // test for "in" or "out" point - if ( denominator < 0 && t > tIn ) - { - // intersection point is an "in point" - tIn = t; - } - else if ( denominator > 0 && t < tOut ) - { - // intersection point is an "out point" - tOut = t; - } - } - polygonIt++; - } - - if ( tIn > tOut ) { -/* cout << "return 2" << endl;*/ - return false; - } - - lineToClip.setEnd ( lineToClip.start() + tOut * v ); - lineToClip.setStart ( lineToClip.start() + tIn * v ); - -// cout << "return true" << endl; - - return true; -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Polygon2D.h b/homer_mapping/src/OccupancyMap/Math/Polygon2D.h deleted file mode 100644 index 16f5ca6e..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Polygon2D.h +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * Polygon2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Polygon2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef POLYGON2D_H -#define POLYGON2D_H - -#include <vector> - -class Polygon2D; -class Point2D; -class Line2D; - -/** - * @class Polygon2D - * - * @author Susanne Maur - * - */ -class Polygon2D -{ - public: - - inline Polygon2D() {} - - /** - * Creates a new polygon - * The points must be given counterclockwise. - */ - inline Polygon2D ( std::vector<Point2D>& points ) - { - m_Points = points; - } - - inline ~Polygon2D() {} - - inline std::vector<Point2D> getPoints() const{ - return m_Points; - } - - /** - * Returns the line representation of the polygon. - * @return line representation of the polygon. - */ - std::vector<Line2D> getLines() const; - - /** - * Clips lines to this polygon. Not tested!!! - * Implementation of Cyrus-Beck. - * The polygon must be difined counterclockwise. - * @param linesToClip The lines to clip. - */ - void clipLines ( std::vector<Line2D>& linesToClip ) const; - - /** - * Clips a line to this polygon. - * Implementation of Cyrus-Beck. - * The polygon must be difined counterclockwise. - * @param lineToClip The lines to clip. - * @return True if it was possible to clip the line, false if the line lies completely outside. - */ - bool clipLine ( Line2D& lineToClip ) const; - - private: - - std::vector<Point2D> m_Points; - -}; - -#endif - diff --git a/homer_mapping/src/OccupancyMap/Math/Pose.cpp b/homer_mapping/src/OccupancyMap/Math/Pose.cpp deleted file mode 100644 index 6011f280..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Pose.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************* - * Pose.cpp - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pose.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <cmath> - -#include "Pose.h" -#include "Transformation2D.h" - -using namespace std; - - -#define THIS Pose - -THIS::THIS(float x, float y, float theta) : Point2D(x, y) { - m_Theta = theta; -} - -THIS::THIS() { - m_Theta = 0.0; -} - -THIS::~THIS() { -} - -float THIS::theta() const { - return m_Theta; -} - -void THIS::setTheta(float theta) { - m_Theta = theta; -} - -Pose THIS::operator+ ( const Transformation2D& transformation ) const { - float x, y, theta; - x = m_X + transformation.x(); - y = m_Y + transformation.y(); - theta = m_Theta + transformation.theta(); - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Pose(x, y, theta); -} - -Pose THIS::operator- ( const Transformation2D& transformation ) const { - float x, y, theta; - x = m_X - transformation.x(); - y = m_Y - transformation.y(); - theta = m_Theta - transformation.theta(); - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Pose(x, y, theta); -} - -Transformation2D THIS::operator- ( const Pose& pose ) const { - float x, y, theta; - x = m_X - pose.x(); - y = m_Y - pose.y(); - - float s1, s2; - if (m_Theta > pose.theta()) { - s1 = -( 2 * M_PI - m_Theta + pose.theta()); - s2 = m_Theta - pose.theta(); - } else { - s1 = 2 * M_PI - pose.theta() + m_Theta; - s2 = -(pose.theta() - m_Theta); - } - if (fabs(s1) > fabs(s2)) { - theta = s2; - } else { - theta = s1; - } - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Transformation2D(x, y, theta); -} - -Pose THIS::interpolate(const Pose& referencePose, float t) const { - - float newX = m_X + t * (referencePose.x() - m_X); - float newY = m_Y + t * (referencePose.y() - m_Y); - - // Calculate mean angle by adding the vem_Thetaors in unit circle - float x1 = cosf(m_Theta); - float y1 = sinf(m_Theta); - float x2 = cosf(referencePose.theta()); - float y2 = sinf(referencePose.theta()); - float newTheta = atan2 (y1*(1-t)+y2*t, x1*(1-t)+x2*t); - - return Pose(newX, newY, newTheta); -} - -//THIS::THIS( ExtendedInStream& extStrm ) -//{ -// char version; -// extStrm >> version; -// extStrm >> m_X; -// extStrm >> m_Y; -// extStrm >> m_Theta; -//} - -//void THIS::storer( ExtendedOutStream& extStrm ) const -//{ -// char version=10; -// extStrm << version; -// extStrm << m_X; -// extStrm << m_Y; -// extStrm << m_Theta; -//} - diff --git a/homer_mapping/src/OccupancyMap/Math/Pose.h b/homer_mapping/src/OccupancyMap/Math/Pose.h deleted file mode 100644 index d0f6574c..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Pose.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * Pose.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pose.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef POSE_H -#define POSE_H - -#include "Point2D.h" -//#include "Architecture/Serializer/ExtendedOutStream.h" // TODO kann wahrscheinlich weg -//#include "Architecture/Serializer/ExtendedInStream.h" - -class Transformation2D; - -/** - * @class Pose - * - * @author Stephan Wirth, Susanne Maur (RX), David Gossow (RX) - * @brief Class to describe and hold a pose of the robot (x, y)-Position + Orientation - * in world-coordinates - */ -class Pose : public Point2D { - -public: - - /** - * Constructor which initializes the members with the given values. - * @param x x-position - * @param y y-position - * @param theta orientation in radiants - */ - Pose(float x, float y, float theta); - - /** - * Default constructor, initializes members to 0. - */ - Pose(); - - /** - * The destructor is empty. - */ - ~Pose(); - - float theta() const; - - void setTheta(float theta); - - Pose operator+ ( const Transformation2D& transformation ) const; - Pose operator- ( const Transformation2D& transformation ) const; - Transformation2D operator- ( const Pose& pose ) const; - - /** - * Interpolates between two poses and returns a pose which correlates with - * current pose + t * (reference pose - current pose) - * @param referencePose The second pose to interpolate between. - * @param t The factor of interpolation. - * @return Interpolated pose - */ - Pose interpolate(const Pose& referencePose, float t) const; - -// Pose( ExtendedInStream& extStrm ); - -// void storer( ExtendedOutStream& extStrm ) const; - -protected: - - float m_Theta; -}; - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/Transformation2D.cpp b/homer_mapping/src/OccupancyMap/Math/Transformation2D.cpp deleted file mode 100644 index 693c7a39..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Transformation2D.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/******************************************************************************* - * Transformation2D.cpp - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Transformation2D.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include "Transformation2D.h" - -#include <cmath> -#include <vector> -#include <iostream> -#include <sstream> -#include "vec2.h" // TODO das sieht nach baselib aus ggf. durch baselib ersetzen -#include "mat2.h" // TODO das sieht nach baselib aus ggf. durch baselib ersetzen -#include "Point2D.h" -#include "Line2D.h" - -#define THIS Transformation2D -#define BASE CVec2 - -THIS::Transformation2D() : BASE() -{ - m_Theta = 0.0; -} - -THIS::Transformation2D ( double x, double y, double theta ) : BASE ( x,y ) -{ - m_Theta = theta; -} - -THIS::Transformation2D ( const CVec2& vec, double theta ) : BASE ( vec ) -{ - m_Theta = theta; -} - -THIS::~Transformation2D() -{ -} - -void THIS::set ( double x, double y, double theta ) -{ - m_X = x; - m_Y = y; - m_Theta = theta; -} - -double THIS::theta() const -{ - return m_Theta; -} - -Transformation2D THIS::operator+ ( Transformation2D t ) const -{ - double theta = m_Theta + t.theta(); - // TODO comment only for scan matching test -// while ( theta >= M_PI ) theta -= 2*M_PI; -// while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X + t.x(), m_Y + t.y(), theta ); -} - -Transformation2D& THIS::operator+= ( Transformation2D t ) -{ - m_X += t.x(); - m_Y += t.y(); - m_Theta += t.theta(); - // TODO comment only for scan matching test -// while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; -// while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; - return ( *this ); -} - -Transformation2D THIS::operator- ( Transformation2D t ) const -{ - float s1, s2, theta; - if ( m_Theta > t.theta() ) - { - s1 = - ( 2 * M_PI - m_Theta + t.theta() ); - s2 = m_Theta - t.theta(); - } - else - { - s1 = 2 * M_PI - t.theta() + m_Theta; - s2 = - ( t.theta() - m_Theta ); - } - if ( fabs ( s1 ) > fabs ( s2 ) ) - { - theta = s2; - } - else - { - theta = s1; - } - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; -// double theta = m_Theta - t.theta(); -// while ( theta >= M_PI ) theta -= 2*M_PI; -// while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X - t.x(), m_Y - t.y(), theta ); -} - -Transformation2D& THIS::operator-= ( Transformation2D t ) -{ - m_X -= t.x(); - m_Y -= t.y(); - - float s1, s2, theta; - if ( m_Theta > t.theta() ) - { - s1 = - ( 2 * M_PI - m_Theta + t.theta() ); - s2 = m_Theta - t.theta(); - } - else - { - s1 = 2 * M_PI - t.theta() + m_Theta; - s2 = - ( t.theta() - m_Theta ); - } - if ( fabs ( s1 ) > fabs ( s2 ) ) - { - theta = s2; - } - else - { - theta = s1; - } - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; - m_Theta = theta; - - return ( *this ); - -// m_X -= t.x(); -// m_Y -= t.y(); -// m_Theta -= t.theta(); -// while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; -// while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; -// return ( *this ); -} - -Transformation2D THIS::operator* ( float factor ) const -{ - - double theta = m_Theta * factor; - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X * factor, m_Y * factor, theta ); -} - -Transformation2D& THIS::operator*= ( float factor ) -{ - m_X *= factor; - m_Y *= factor; - m_Theta *= factor; - while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; - while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; - return ( *this ); -} - - -Transformation2D THIS::operator/ ( float factor ) const -{ - double theta = m_Theta / factor; - return Transformation2D ( m_X / factor, m_Y / factor, theta ); -} - -Transformation2D& THIS::operator/= ( float factor ) -{ - m_X /= factor; - m_Y /= factor; - m_Theta /= factor; - return ( *this ); -} - -bool THIS::operator== ( Transformation2D t ) const -{ - if ( t.x() == m_X && t.y() == m_Y && t.theta() == m_Theta ) - { - return true; - } - else - { - return false; - } -} - -bool THIS::operator!= ( Transformation2D t ) const -{ - return ! ( ( *this ) ==t ); -} - -bool THIS::operator<= ( Transformation2D t ) const -{ - return ( this->magnitude() <= t.magnitude() ) && ( m_Theta <= t.theta() ); -} - -bool THIS::operator>= ( Transformation2D t ) const -{ - return ( this->magnitude() >= t.magnitude() ) && ( m_Theta >= t.theta() ); -} - -bool THIS::operator< ( Transformation2D t ) const -{ - return ( m_X < t.x() ) || ( m_Y < t.y() ) || ( ( m_Theta < t.theta() ) && ( *this <= t ) ); -} - -bool THIS::operator> ( Transformation2D t ) const -{ - return ( m_X > t.x() ) || ( m_Y > t.y() ) || ( ( m_Theta > t.theta() ) && ( *this >= t ) ); -} - -Transformation2D THIS::abs() const -{ - return Transformation2D ( std::abs ( m_X ), std::abs ( m_Y ), std::abs ( m_Theta ) ); -} - -Transformation2D THIS::inverse() const -{ - return ( *this ) * ( -1.0 ); -} - -Point2D THIS::transform ( const Point2D& point ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - Point2D transformedPoint = rotMat * ( point ); - transformedPoint += transVec; - return transformedPoint; -} - -std::vector<Point2D> THIS::transform ( const std::vector<Point2D>& points ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - std::vector<Point2D> transformedPoints; - std::vector<Point2D>::const_iterator iter = points.begin(); - while ( iter != points.end() ) - { - Point2D currPoint = rotMat * ( *iter ); - currPoint += transVec; - transformedPoints.push_back ( currPoint ); - iter++; - } - return transformedPoints; -} - -// // Reihenfolge rotation/translation vertauscht !!! -// Point2D THIS::transform ( Point2D point ) const -// { -// CMat2 rotMat = CMat2 ( m_Theta ); -// CVec2 transVec = CVec2 ( m_X, m_Y ); -// Point2D transformedPoint = point+transVec; -// transformedPoint = rotMat * point; -// return transformedPoint; -// } -// -// // Reihenfolge rotation/translation vertauscht !!! -// std::vector<Point2D> THIS::transform ( std::vector<Point2D> points ) const -// { -// CMat2 rotMat = CMat2 ( m_Theta ); -// CVec2 transVec = CVec2 ( m_X, m_Y ); -// std::vector<Point2D> transformedPoints; -// std::vector<Point2D>::const_iterator iter = points.begin(); -// while ( iter != points.end() ) -// { -// Point2D currPoint = ( *iter )+ transVec; -// currPoint = rotMat * currPoint; -// transformedPoints.push_back ( currPoint ); -// iter++; -// } -// return transformedPoints; -// } - -Line2D THIS::transform ( const Line2D& line ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - Line2D transformedLine = Line2D ( rotMat * line.start() + transVec, rotMat * line.end() + transVec ); - return transformedLine; -} - -std::vector<Line2D> THIS::transform ( const std::vector<Line2D>& lines ) const -{ - //CMat2 rotMat = CMat2 ( m_Theta ); - //CVec2 transVec = CVec2 ( m_X, m_Y ); - std::vector<Line2D> transformedLines; - std::vector<Line2D>::const_iterator iter = lines.begin(); - while ( iter != lines.end() ) - { - transformedLines.push_back ( transform(*iter) ); - iter++; - } - return transformedLines; -} - -std::string THIS::toString() const -{ - std::ostringstream str; - str << "deltaX: " << m_X << ", deltaY: " << m_Y << ", deltaTheta: " << m_Theta; - return str.str(); -} - - - -#undef THIS -#undef BASE - diff --git a/homer_mapping/src/OccupancyMap/Math/Transformation2D.h b/homer_mapping/src/OccupancyMap/Math/Transformation2D.h deleted file mode 100644 index 59a54d82..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Transformation2D.h +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * Transformation2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Transformation2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef TRANSFORMATION2D_H -#define TRANSFORMATION2D_H - -#include <cmath> -#include <vector> -//#include "Workers/Math/Vec.h" -#include "Point2D.h" -#include "Line2D.h" - - -/** - * @class Transformation2D - * - * @author Susanne Maur - * - * @brief Class to describe a transformation of poses in 2D. - * This inplies a translation in x and y direction each and a rotation. - */ -class Transformation2D : public CVec2 -{ - - public: - - /** - * Constructor that initializes the members. - * @param x translation in x direction in m - * @param y translation in y direction in m - * @param theta rotation in radiants - */ - Transformation2D ( double x, double y, double theta ); - - /** - * Constructor that initializes the members. - * @param vec a vector which represents the translation in x and y direction - * @param theta rotation in radiants - */ - Transformation2D ( const CVec2& vec, double theta ); - - /** - * Default constructor sets all members to 0.0. - */ - Transformation2D(); - - /** - * Default destructor. - */ - ~Transformation2D(); - - /** - * Sets the values of transformation. - * @param x translation in x direction in mm - * @param y translation in y direction in mm - * @param theta rotation in radiants - */ - void set ( double x, double y, double theta ); - - /** - * Returns the rotation in radiants. - * @return rotation in radiants - */ - double theta() const; - - /** - * Adds two transformations. - */ - Transformation2D operator+ ( Transformation2D t ) const; - Transformation2D& operator+= ( Transformation2D t ); - - /** - * Subtracts two transformations. - */ - Transformation2D operator- ( Transformation2D t ) const; - Transformation2D& operator-= ( Transformation2D t ); - - /** - * Scales a transformation by a factor - */ - Transformation2D operator* ( float factor ) const; - Transformation2D& operator*= ( float factor ); - - /** - * Scales a transformation by a factor - */ - Transformation2D operator/ ( float factor ) const; - Transformation2D& operator/= ( float factor ); - - /** - * Test equality of transformations. - */ - bool operator== ( Transformation2D t ) const; - bool operator!= ( Transformation2D t ) const; - - /** - * Compare transformations. - * (attention: algebraic signs are taken into account, if necessary use fabs()) - */ - bool operator<= ( Transformation2D t ) const; - bool operator>= ( Transformation2D t ) const; - bool operator< ( Transformation2D t ) const; - bool operator> ( Transformation2D t ) const; - - /** - * Applies abs() on every attribute. - */ - Transformation2D abs() const; - - /** - * Inverts the transformation, scales every attribute with -1. - */ - Transformation2D inverse() const; - - /** - * Transformes points by first rotation, then translating. - */ - Point2D transform ( const Point2D& point ) const; - std::vector<Point2D> transform ( const std::vector<Point2D>& points ) const; - - /** - * Transformes lines by first rotation, then translating. - */ - Line2D transform ( const Line2D& line ) const; - std::vector<Line2D> transform ( const std::vector<Line2D>& lines ) const; - - /** - * Returns the string representation of the transformation. - * @return string representation of the transformation. - */ - std::string toString() const; - - private: - double m_Theta; -}; - -#endif - diff --git a/homer_mapping/src/OccupancyMap/Math/Vector3D.cpp b/homer_mapping/src/OccupancyMap/Math/Vector3D.cpp deleted file mode 100644 index 495846a7..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Vector3D.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Vector3D.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include "Vector3D.h" - -#define THIS Vector3D - -using namespace std; - -std::string THIS::toString( int precision, std::string name ) -{ - std::ostringstream s; - - s.precision( precision ); - s.setf(ios::fixed,ios::floatfield); - - for ( unsigned row=0; row<3; row++ ) - { - if ( name != "" ) - { - if ( row==1 ) - { - s << name << " = "; - } - else - { - s.width( name.length()+3 ); - s << ""; - } - } - - s << "( "; - s.width( precision+4 ); - switch ( row ) - { - case 0: - s << m_X << " "; - break; - case 1: - s << m_Y << " "; - break; - case 2: - s << m_Z << " "; - break; - } - s << ")" << endl; - } - return s.str(); -} - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/Vector3D.h b/homer_mapping/src/OccupancyMap/Math/Vector3D.h deleted file mode 100644 index ae656232..00000000 --- a/homer_mapping/src/OccupancyMap/Math/Vector3D.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Vector3D.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#ifndef VEC3_H -#define VEC3_H - -#include <math.h> -#include <assert.h> -#include <string> -#include "vec2.h" - -class Vector3D -{ - public: - - Vector3D(); - Vector3D ( float x, float y, float z ); - Vector3D ( const CVec2& v, float z); - - Vector3D ( const Vector3D& v2 ); - - Vector3D operator+ ( const Vector3D& vVector ) const; - Vector3D& operator+= ( const Vector3D& vVector ); - Vector3D operator+() const; - - Vector3D operator- ( const Vector3D& vVector ) const; - Vector3D& operator-= ( const Vector3D& vVector ); - Vector3D operator-() const; - - // Dot - float operator* ( const Vector3D& vVector ) const; - - // Cross - Vector3D operator^ ( const Vector3D& vVector2 ) const; - - // Scalar Mult - Vector3D operator* ( const float num ) const; - Vector3D& operator*= ( const float num ); - Vector3D operator/ ( float num ) const; - Vector3D& operator/= ( const float num ); - - bool operator < ( const Vector3D& vVec ) const; - bool operator > ( const Vector3D& vVec ) const; - bool operator== ( const Vector3D& v1 ) const; - - float operator [] ( const unsigned int i ) const; - float& operator [] ( const unsigned int i ); - - void set ( float fx, float fy, float fz ); - - float x() const { - return m_X; - } - - float y() const { - return m_Y; - } - - float z() const { - return m_Z; - } - - void lerp ( const Vector3D& v1, const Vector3D& v2, float f ); - - float magnitude() const; - - std::string toString( int precision=3, std::string name="" ); - - private: - float m_X, m_Y, m_Z; -}; - -#include "vec3_inl.h" - - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/mat2.h b/homer_mapping/src/OccupancyMap/Math/mat2.h deleted file mode 100644 index 254e8dc6..00000000 --- a/homer_mapping/src/OccupancyMap/Math/mat2.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * mat2.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#ifndef MAT2_H -#define MAT2_H - -#include <math.h> -#include "Point2D.h" -#include "vec2.h" - -class CMat2 -{ - public: - CMat2(); - CMat2(float rot); - ~CMat2(); - - CMat2 operator *(const CMat2 &mat) const; - - CVec2 operator *(const CVec2& v) const; - - Point2D operator *(const Point2D& p) const; - - float& operator [] (unsigned int position) { - return fMatrix[position]; - } - - CMat2 operator +(const CMat2 rhs) const { - CMat2 newMatrix; - for (unsigned int i = 0; i < 4; i++) { - newMatrix[i] = valueAt(i) + rhs.valueAt(i); - } - return newMatrix; - } - - CMat2 operator -(const CMat2 rhs) const { - CMat2 newMatrix; - for (unsigned int i = 0; i < 4; i++) { - newMatrix[i] = valueAt(i) - rhs.valueAt(i); - } - return newMatrix; - } - - float valueAt(unsigned int position) const{ - return fMatrix[position]; - } - - union - { - float fMatrix[4]; - float m[2][2]; - struct - { - float xx, xy; - float yx, yy; - }; - }; - - void transpose(); - void loadIdentity(); - - void makeRotation(float fA); - - bool invert(); -}; - - - -#include "mat2_inl.h" - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/mat2_inl.h b/homer_mapping/src/OccupancyMap/Math/mat2_inl.h deleted file mode 100644 index e3f77e16..00000000 --- a/homer_mapping/src/OccupancyMap/Math/mat2_inl.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * mat2_inl.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#include <assert.h> - -inline CMat2::CMat2(){ - for (unsigned int i = 0; i < 4; i++) { - fMatrix[i] = 0; - } -} - -inline CMat2::~CMat2() -{} - -inline CMat2::CMat2(float rot) -{ - makeRotation(rot); -} - -inline CMat2 CMat2::operator * ( const CMat2 & mat ) const -{ - CMat2 retValue; - for (unsigned int line = 0; line < 2; line++) { - for (unsigned int column = 0; column < 2; column++) { - retValue[line*2 + column] = valueAt(line*2 + column) + mat.valueAt(column*2 + line); - } - } - return retValue; -} - -inline CVec2 CMat2::operator * ( const CVec2& v ) const -{ - return CVec2(xx*v[0] + xy*v[1],yx*v[0] + yy*v[1]); -} - -inline Point2D CMat2::operator * ( const Point2D& p ) const -{ - return Point2D(xx*p.x() + xy*p.y(), yx*p.x() + yy*p.y()); -} - -inline void CMat2::transpose() -{ - float t=xy; - xy=yx; - yx=t; -} - -inline void CMat2::loadIdentity() -{ - xx=1.0f; xy=0.0f; - yx=0.0f; yy=1.0f; -} - -inline void CMat2::makeRotation ( float fA ) -{ - xx=yy=cosf(fA); - yx=sinf(fA); - xy=-yx; -} - -inline bool CMat2::invert() -{ - CMat2 tmp; - float det = fMatrix[0]*fMatrix[3] - fMatrix[1]*fMatrix[2]; - - if(fabs(det) < 0.001f) return false; - - det = 1.0 / det; - tmp.fMatrix[0] = fMatrix[3]*det; - tmp.fMatrix[1] = -fMatrix[1]*det; - tmp.fMatrix[2] = -fMatrix[2]*det; - tmp.fMatrix[3] = fMatrix[0]*det; - - (*this)=tmp; - return true; -} - - - - diff --git a/homer_mapping/src/OccupancyMap/Math/mat3.cpp b/homer_mapping/src/OccupancyMap/Math/mat3.cpp deleted file mode 100755 index 306877e8..00000000 --- a/homer_mapping/src/OccupancyMap/Math/mat3.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * mat3.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus, Susanne Maur - *******************************************************************************/ - -#include "mat3.h" -#include "math.h" - -#define THIS CMat3 - -//---------------------------------------------------------------------------------------------------------- -THIS::~CMat3() -{ -} -//---------------------------------------------------------------------------------------------------------- -void THIS::transpose() -{ - float temp; - - temp=fMatrix[1]; - fMatrix[1]=fMatrix[3]; - fMatrix[3]=temp; - - temp=fMatrix[2]; - fMatrix[2]=fMatrix[6]; - fMatrix[6]=temp; - - temp=fMatrix[5]; - fMatrix[5]=fMatrix[7]; - - fMatrix[7]=temp; -} - -//---------------------------------------------------------------------------------------------------------- - -void THIS::reverse() -{ - CMat3 temp; - - temp[0]=fMatrix[4]*fMatrix[8] - fMatrix[5]*fMatrix[7]; - temp[1]=fMatrix[2]*fMatrix[7] - fMatrix[1]*fMatrix[8]; - temp[2]=fMatrix[1]*fMatrix[5] - fMatrix[2]*fMatrix[4]; - temp[3]=fMatrix[5]*fMatrix[6] - fMatrix[3]*fMatrix[8]; - temp[4]=fMatrix[0]*fMatrix[8] - fMatrix[2]*fMatrix[6]; - temp[5]=fMatrix[2]*fMatrix[3] - fMatrix[0]*fMatrix[5]; - temp[6]=fMatrix[3]*fMatrix[7] - fMatrix[4]*fMatrix[6]; - temp[7]=fMatrix[1]*fMatrix[6] - fMatrix[0]*fMatrix[7]; - temp[8]=fMatrix[0]*fMatrix[4] - fMatrix[1]*fMatrix[3]; - - *this = (temp) * (1.0/determinant()); -} - -//---------------------------------------------------------------------------------------------------------- -void THIS::loadIdentity() -{ - fMatrix[0]=1.0f; fMatrix[1]=0; fMatrix[2]=0; - fMatrix[3]=0; fMatrix[4]=1.0f; fMatrix[5]=0; - fMatrix[6]=0; fMatrix[7]=0; fMatrix[8]=1.0f; -} -//---------------------------------------------------------------------------------------------------------- -void THIS::makeRotationX(float fA) -{ - // 1 0 0 0 - // 0 c -s 0 - // 0 s c 0 - // 0 0 0 1 - float c=cosf(fA); - float s=sinf(fA); - fMatrix[0]=1; fMatrix[1]=0; fMatrix[2]=0; - fMatrix[3]=0; fMatrix[4]=c; fMatrix[5]=s; - fMatrix[6]=0; fMatrix[7]=-s; fMatrix[8]=c; - -} -//---------------------------------------------------------------------------------------------------------- -void THIS::makeRotationY(float fA) -{ - // c 0 s 0 - // 0 1 0 0 - //-s 0 c 0 - // 0 0 0 1 - float c=cosf(fA); - float s=sinf(fA); - fMatrix[0]=c; fMatrix[1]=0; fMatrix[2]=-s; - fMatrix[3]=0; fMatrix[4]=1; fMatrix[5]=0; - fMatrix[6]=s; fMatrix[7]=0; fMatrix[8]=c; -} -//---------------------------------------------------------------------------------------------------------- -void THIS::makeRotationZ(float fA) -{ - // c -s 0 0 - // s c 0 0 - // 0 0 1 0 - // 0 0 0 1 - - float c=cosf(fA); - float s=sinf(fA); - fMatrix[0]=c; fMatrix[1]=s; fMatrix[2]=0; - fMatrix[3]=-s; fMatrix[4]=c; fMatrix[5]=0; - fMatrix[6]=0; fMatrix[7]=0; fMatrix[8]=1; -} -//---------------------------------------------------------------------------------------------------------- -void THIS::makeScale(const Vector3D& vScale) -{ - fMatrix[0]=vScale[0]; fMatrix[1]=0; fMatrix[2]=0; - fMatrix[3]=0; fMatrix[4]=vScale[1]; fMatrix[5]=0; - fMatrix[6]=0; fMatrix[7]=0; fMatrix[8]=vScale[2]; -} -//---------------------------------------------------------------------------------------------------------- -CMat3 THIS::operator*(const CMat3& mat) const -{ - CMat3 r; - float* r0=(float*)&r.fMatrix; - float* m2=(float*)&fMatrix; - float* m1=(float*)&mat.fMatrix; - - r0[0]=m1[0]*m2[0]+ m1[1]*m2[3]+ m1[2]*m2[6]; - r0[1]=m1[0]*m2[1]+ m1[1]*m2[4]+ m1[2]*m2[7]; - r0[2]=m1[0]*m2[2]+ m1[1]*m2[5]+ m1[2]*m2[8]; - - r0[3]=m1[3]*m2[0]+ m1[4]*m2[3]+ m1[5]*m2[6]; - r0[4]=m1[3]*m2[1]+ m1[4]*m2[4]+ m1[5]*m2[7]; - r0[5]=m1[3]*m2[2]+ m1[4]*m2[5]+ m1[5]*m2[8]; - - r0[6]=m1[6]*m2[0]+ m1[7]*m2[3]+ m1[8]*m2[6]; - r0[7]=m1[6]*m2[1]+ m1[7]*m2[4]+ m1[8]*m2[7]; - r0[8]=m1[6]*m2[2]+ m1[7]*m2[5]+ m1[8]*m2[8]; - - - return r; -} -//---------------------------------------------------------------------------------------------------------- -CMat3 THIS::operator *(float f) const { - CMat3 newMatrix; - for (unsigned i = 0; i < 9; i++) { - newMatrix[i] = fMatrix[i] * f; - } - return newMatrix; -} -//------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -CMat3& THIS::operator *=(float f) { - for (unsigned i = 0; i < 9; i++) { - fMatrix[i] *= f; - } - return *this; -} -//---------------------------------------------------------------------------------------------------------- -Vector3D THIS::operator *(const Vector3D& v) const { - Vector3D temp; - temp[0]=fMatrix[0]*v[0]+fMatrix[1]*v[1]+fMatrix[2]*v[2]; - temp[1]=fMatrix[3]*v[0]+fMatrix[4]*v[1]+fMatrix[5]*v[2]; - temp[2]=fMatrix[6]*v[0]+fMatrix[7]*v[1]+fMatrix[8]*v[2]; - return temp; -} -//---------------------------------------------------------------------------------------------------------- -CMat3 THIS::operator +(const CMat3& mat) { - CMat3 newMatrix; - for (unsigned i = 0; i < 9; i++) { - newMatrix[i] = mat.valueAt(i) + valueAt(i); - } - return newMatrix; -} - -//---------------------------------------------------------------------------------------------------------- -std::string THIS::toString() const -{ - std::ostringstream st; - for (int i=0;i<3;i++) - { - for (int j=0;j<3;j++) - { - st<<m[j][i]<<" "; - } - st<<"\n"; - } - return st.str(); -} -//---------------------------------------------------------------------------------------------------------- -float THIS::determinant() const { - return fMatrix[0]*fMatrix[4]*fMatrix[8] + fMatrix[1]*fMatrix[5]*fMatrix[6 ] + fMatrix[2]*fMatrix[3]*fMatrix[7] - - fMatrix[2]*fMatrix[4]*fMatrix[6] - fMatrix[1]*fMatrix[3]*fMatrix[8] - fMatrix[0]*fMatrix[5]*fMatrix[7]; -} -//---------------------------------------------------------------------------------------------------------- - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/mat3.h b/homer_mapping/src/OccupancyMap/Math/mat3.h deleted file mode 100755 index 629b9e7d..00000000 --- a/homer_mapping/src/OccupancyMap/Math/mat3.h +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * mat3.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus, Susanne Maur - *******************************************************************************/ -#ifndef MAT3_H -#define MAT3_H - -#include <iostream> -#include <sstream> -#include <assert.h> -#include "Vector3D.h" - -class CMat3 { - public: - CMat3(); - CMat3( float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz ); - ~CMat3(); - - /** overwritten operator**/ - CMat3 operator *(const CMat3 &mat) const; - CMat3 operator *(float f) const; - CMat3& operator *=(float f); - Vector3D operator *(const Vector3D& v) const; - float& operator [](const unsigned value); - CMat3 operator +(const CMat3& mat1); - - /** @return value at position **/ - float valueAt(unsigned i) const; - - /** set value at position **/ - void setValue(unsigned line, unsigned column, float value); - - /** @return determinant of matrix **/ - float determinant() const; - - /** transpose matrix **/ - void transpose(); - /** reverse matrix **/ - void reverse(); - - /** create identity matrix **/ - void loadIdentity(); - - /** create rotation matrix **/ - void makeRotationX(float fA); - void makeRotationY(float fA); - void makeRotationZ(float fA); - - /** create scale matrix **/ - void makeScale(const Vector3D& vScale); - //void BuildRPY(float fRoll, float fPitch, float fYaw); - - std::string toString() const; - - private: - union - { - float fMatrix[9]; - float m[3][3]; - struct - { - float xx, xy, xz; - float yx, yy, yz; - float zx, zy, zz; - }; - }; -}; - -#include "mat3.inl" - -#endif - diff --git a/homer_mapping/src/OccupancyMap/Math/mat3.inl b/homer_mapping/src/OccupancyMap/Math/mat3.inl deleted file mode 100755 index ae2e6c5f..00000000 --- a/homer_mapping/src/OccupancyMap/Math/mat3.inl +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * mat3.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus, Susanne Maur - *******************************************************************************/ - -#define THIS CMat3 - -//---------------------------------------------------------------------------------------------------------- -inline THIS::CMat3() -{ - for(int i=0;i<9;i++) fMatrix[i]=0.0f; -} -//---------------------------------------------------------------------------------------------------------- -inline THIS::CMat3( float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz ) -{ - fMatrix[0] = xx; - fMatrix[1] = xy; - fMatrix[2] = xz; - fMatrix[3] = yx; - fMatrix[4] = yy; - fMatrix[5] = yz; - fMatrix[6] = zx; - fMatrix[7] = zy; - fMatrix[8] = zz; -} -//---------------------------------------------------------------------------------------------------------- -inline float& THIS::operator [](const unsigned value) { - return fMatrix[value]; -} -//---------------------------------------------------------------------------------------------------------- -inline float THIS::valueAt(unsigned i) const { - return fMatrix[i]; -} -//---------------------------------------------------------------------------------------------------------- -inline void THIS::setValue(unsigned line, unsigned column, float value) { - m[line][column] = value; -} -//---------------------------------------------------------------------------------------------------------- - -#undef THIS diff --git a/homer_mapping/src/OccupancyMap/Math/misc.cpp b/homer_mapping/src/OccupancyMap/Math/misc.cpp deleted file mode 100644 index 1f4facd6..00000000 --- a/homer_mapping/src/OccupancyMap/Math/misc.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/******************************************************************************* - * misc.cpp - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#include "vec2.h" -#include "misc.h" -#include <iostream> -#include "math.h" -#include <assert.h> -#include "Obb2D.h" - -/** -* m - center of the circle -* r - radius of the circle -* x - starting point of the ray -* t - ray -* f - param - return value -*/ -bool intersectRayCircle(const CVec2& m, float r, const CVec2& x, const CVec2& t, float& f) -{ - //|x-m|=r - //|x+r*t-m|=r - //(x+r*t-m)^2=r^2 - //((x-m)+r*t)^2=r^2 - //(x-m)^2+2*(x-m)*r*t+r^2*t^2=r^2 - - //r^2*t^2+r*2*(x-m)*t+(x-m)^2-r^2 - - - float invtSqr=1.0f/t.sqr(); - float p = 2.0f*((x-m)*t)*invtSqr; - float q = ((m-x).sqr() - r*r)*invtSqr; - float diskr = p*p*0.25f - q; - - if (diskr < 0) - { - return false; - } - - diskr=sqrtf(diskr); - f = -0.5f*p - diskr; - - if (f<0) - { - f = -0.5f*p + diskr; - if (f>0) - { - return true; - } - else - { - return false; - } - } -/* - if (f<0) - { - std::cout << "smaller" << f << std::endl; - if (t*(m-x)>0) - { - f=0.001; - return true; - } - else - return false; - } - */ - return true; - -} - - -bool intersectRayLineSegment(const CVec2& a, const CVec2& b, const CVec2& x, const CVec2& t, float&f) -{ - CVec2 n=(b-a).getNormal(); - - float denom=t*n; - - if (fabs(denom)<0.000001f) - return false; - - f=(n*a-n*x)/denom; - - if (f<0) - { - return false; - } - - CVec2 pt=x+t*f; - if ((a-pt)*(b-pt)<0) - return true; - return false; -} - -float shortestDistanceToLineSegment(const CVec2& a, const CVec2& b, const CVec2& x) -{ - CVec2 dir=b-a; - - if ( (dir*dir) < 0.00001 ) - { - float m1=(x-a).magnitude(); - float m2=(x-b).magnitude(); - if (m1<m2) return m1; - else return m2; - } - - float r=(dir*x-dir*a)/(dir*dir); - if (r<=0.0f) - return (x-a).magnitude(); - if (r>=1.0f) - return (x-b).magnitude(); - - return (a+r*dir-x).magnitude(); - -} - -bool intersectRayCapsule(const CVec2& x, const CVec2& t, const CVec2& a, const CVec2& b, float radius, float& f) -{ - f=99999999; - float r; - bool hadInt=false; - if (intersectRayCircle(a,radius,x,t,r)) - { - if (r<f) - f=r; - hadInt=true; - } - if (intersectRayCircle(b,radius,x,t,r)) - { - if (r<f) - f=r; - hadInt=true; - } - CVec2 n=normalize(b-a).getNormal(); - if (intersectRayLineSegment(a+radius*n,b+radius*n,x,t,r)) - { - if (r<f) - f=r; - hadInt=true; - } - if (intersectRayLineSegment(a-radius*n,b-radius*n,x,t,r)) - { - if (r<f) - f=r; - hadInt=true; - } - return hadInt; -} - -// c - punkt wo arc startet -// p - zentrum des arcs -// r0 - arc radius -// hd - heading -// m1 - kreiszentrum -// r1 - kreisradius -// angle - output -bool intersectPathCircle(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& m1, float r1, float& angle) -{ - CVec2 vec=p-m1; - float s=vec.sqr(); - if (s>sqr(fabs(r0)+r1)) - return false; - - if (s<sqr(fabs(r0)-r1)) - return false; - - float d=sqrtf(s); - - float b=(r0*r0-r1*r1+s)/(2*d); - - CVec2 mid=p-vec*(b/d); - - float h=sqrtf(r0*r0-b*b); - //std::cout << " h : " << h << std::endl; - - CVec2 n=(vec*(h/d)).getNormal(); - - - //CVec2 pm=p-m1; - - CVec2 p1=(mid+n-p); - CVec2 p2=(mid-n-p); - - CVec2 pc=normalize(c-p); - - float angle0=acosf(normalize(p1)*pc); - float angle1=acosf(normalize(p2)*pc); - - //std::cout << "angle0: " << angle0 << std::endl; - - if ((p1*hd)<0) angle0=2*M_PI-angle0; - if ((p2*hd)<0) angle1=2*M_PI-angle1; - - if (angle0<angle1) angle=angle0; - else angle=angle1; - - //angle=angle0; - - return true; - - -} - -bool intersectPathLine(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& p1, const CVec2& p2, float& angle) -{ - CVec2 vec=p2-p1; - - - /* - float invtSqr=1.0f/t.sqr(); - float p = 2.0f*((x-m)*t)*invtSqr; - float q = ((m-x).sqr() - r*r)*invtSqr; - float diskr = p*p*0.25f - q; - */ - - if (((p1-p).sqr()<r0*r0)&&((p2-p).sqr()<r0*r0)) - return false; - - - float invtSqr=1.0f/vec.sqr(); - float pa = 2.0f*((p1-p)*vec)*invtSqr; - float qi = ((p-p1).sqr() - r0*r0)*invtSqr; - float diskr = pa*pa*0.25f - qi; - - if (diskr < 0) - { - return false; - } - - float sqrtfdiskr=sqrtf(diskr); - - float f1 = -0.5f*pa - sqrtfdiskr; - float f2 = -0.5f*pa + sqrtfdiskr; - - if (f1>1) return false; - if (f2<0) return false; - - //std::cout << "f1: " << f1 << " f2: " << f2 << std::endl; - - CVec2 int1=p1+f1*vec; - CVec2 int2=p1+f2*vec; - - //assert((int2-int1).magnitude()<(p1-p2).magnitude()); - - CVec2 pc=normalize(c-p); - - float angle0=acosf(normalize(int1-p)*pc); - float angle1=acosf(normalize(int2-p)*pc); - - - if ((int1-p)*hd<0) - { - angle0=2*M_PI-angle0; - } - if ((int2-p)*hd<0) - { - angle1=2*M_PI-angle1; - } - - - if (angle0<angle1) angle=angle0; - else angle=angle1; - - if (f1<0) angle=angle1; - if (f2>1) angle=angle0; - - - - return true; - -} - -// c - punkt wo arc startet -// p - arc zentrum -// r0 - radius des arcs -// hd - heading -// a - linienanfang -// b - linienende -// radius - linienradius -// r [out] - wie weit ging der arc? - -bool intersectPathCapsule(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& a, const CVec2& b, float radius, float& f) -{ - f=99999999; - float r; - bool hadInt=false; - if (intersectPathCircle(c,p,r0,hd,a,radius,r)) - { - if (r<f) - f=r; - hadInt=true; - } - if (intersectPathCircle(c,p,r0,hd,b,radius,r)) - { - if (r<f) - f=r; - hadInt=true; - } - CVec2 n=normalize(b-a).getNormal(); - if (intersectPathLine(c,p,r0,hd,a+radius*n,b+radius*n,r)) - { - if (r<f) - f=r; - hadInt=true; - } - if (intersectPathLine(c,p,r0,hd,a-radius*n,b-radius*n,r)) - { - if (r<f) - f=r; - hadInt=true; - } - return hadInt; -} - - -bool isInAABB(const std::pair<CVec2,CVec2>& aabb, const CVec2& p) -{ - const CVec2& mins=aabb.first; - const CVec2& maxs=aabb.second; - if ((p[0]>mins[0]) &&(p[1]>mins[1])&&(p[0]<maxs[0]) &&(p[1]<maxs[1])) - return true; - return false; -} - -bool testAABBOverlap(const std::pair<CVec2,CVec2>& a, const std::pair<CVec2,CVec2>& b) -{ - const CVec2& vMins=b.first; - const CVec2& vMaxs=b.second; - CVec2 B=(vMins+vMaxs)*0.5f; - CVec2 A=(a.first+a.second)*0.5f; - CVec2 E=a.second-A; - CVec2 bE=vMaxs-B; - - const CVec2 T = B - A;//vector from A to B - return fabs(T[0]) <= (E[0] + bE[0]) - && - fabs(T[1]) <= (E[1] + bE[1]); - -} - -float computeOBBIntersection(const CVec2& a, const CVec2& b, const CVec2& c, const CVec2& d, float size) -{ - OBB2D g; - CVec2 dab=normalize(b-a)*size; - CVec2 nab=dab.getNormal(); - g[0]=a+nab-dab; - g[1]=a-nab-dab; - g[2]=b-nab+dab; - g[3]=b+nab+dab; - - - OBB2D h; - CVec2 dcd=normalize(d-c)*size; - CVec2 ncd=dcd.getNormal(); - h[0]=c+ncd-dcd; - h[1]=c-ncd-dcd; - h[2]=d-ncd+dcd; - h[3]=d+ncd+dcd; - - std::pair<CVec2,CVec2> aabb=g.computeAABB(); - std::pair<CVec2,CVec2> aabb2=h.computeAABB(); - - //static int all=0; - //all++; - - - if (!testAABBOverlap(aabb,aabb2)) - { - return 0; - } - - //h.clip(g); - /* - static int clips=0; - clips++; - if (clips%10000==0) - std::cout<<"clips: " << clips << " rate: " << float(clips)/float(all) << std::endl; - */ - return h.computeClippedArea(g)/(2*size*((a-b).magnitude()+2*size)); - -} - - - - diff --git a/homer_mapping/src/OccupancyMap/Math/misc.h b/homer_mapping/src/OccupancyMap/Math/misc.h deleted file mode 100644 index 5175e3cd..00000000 --- a/homer_mapping/src/OccupancyMap/Math/misc.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * misc.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#ifndef MISC_H -#define MISC_H - -template<class T> -T sqr(T f) -{ - return f*f; -} - -bool intersectRayCircle(const CVec2& m, float r, const CVec2& x, const CVec2& t, float& f); -bool intersectRayLineSegment(const CVec2& a, const CVec2& b, const CVec2& x, const CVec2& t, float&f); -float shortestDistanceToLineSegment(const CVec2& a, const CVec2& b, const CVec2& x); -bool intersectRayCapsule(const CVec2& x, const CVec2& t, const CVec2& a, const CVec2& b, float radius, float& f); - -bool intersectPathCircle(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& m1, float r1, float& angle); -bool intersectPathLine(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& p1, const CVec2& p2, float& angle); - -bool intersectPathCapsule(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& a, const CVec2& b, float radius, float& f); - -float computeOBBIntersection(const CVec2& a, const CVec2& b, const CVec2& c, const CVec2& d, float size); - -#endif - diff --git a/homer_mapping/src/OccupancyMap/Math/vec2.h b/homer_mapping/src/OccupancyMap/Math/vec2.h deleted file mode 100644 index 39a72c8e..00000000 --- a/homer_mapping/src/OccupancyMap/Math/vec2.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * vec2.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus, Susanne Maur - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#ifndef VEC2_H -#define VEC2_H - -#include <math.h> - -class CVec2 -{ - public: - - inline CVec2() - { - m_X = 0; m_Y = 0; - } - - inline CVec2 ( double x, double y ) - { - m_X=x; m_Y=y; - } - - inline CVec2 ( const CVec2& vec ) - { - m_X=vec.x(); m_Y=vec.y(); - } - - inline CVec2 operator+ ( const CVec2& vVector ) const - { - return CVec2 ( vVector[0] + m_X, vVector[1] + m_Y ); - }; - - inline CVec2 operator- ( const CVec2& vVector ) const - { - return CVec2 ( m_X - vVector[0], m_Y - vVector[1] ); - }; - - inline CVec2 operator- ( ) const - { - return CVec2 ( - m_X, - m_Y ); - }; - - inline CVec2 operator* ( double num ) const - { - return CVec2 ( m_X * num, m_Y * num ); - }; - - inline double operator* ( const CVec2& vVector ) const - { - return m_X*vVector[0]+m_Y*vVector[1]; - } - - inline CVec2 operator/ ( double num ) const - { - return CVec2 ( m_X / num, m_Y / num ); - } - - inline void set ( double fx, double fy ) - { - m_X=fx; m_Y=fy; - } - - inline double x() const - { - return m_X; - } - - inline double y() const - { - return m_Y; - } - - inline double magnitude() const - { - double sumOfSquares = m_X*m_X + m_Y*m_Y; - return sqrt ( sumOfSquares ); - } - - inline double operator [] ( unsigned int i ) const - { - return ( ( double* ) this ) [i]; - } - - inline double& operator [] ( unsigned int i ) - { - return ( ( double* ) this ) [i]; - } - - inline CVec2& operator/= ( double num ) - { - double inv=1.0f/num; - m_X*=inv; - m_Y*=inv; - return ( *this ); - } - - inline CVec2& operator*= ( double num ) - { - m_X*=num; - m_Y*=num; - return ( *this ); - } - - inline CVec2& normalize() - { - return ( *this/=magnitude() ); - } - - inline CVec2& makePerp() - { - double xn=m_X; - m_X=-m_Y; - m_Y=xn; - return *this; - } - - inline CVec2 getNormal() const - { - return CVec2 ( m_Y, -m_X ); //? - } - - inline CVec2 getNormalized() const - { - return ( *this ) /magnitude(); - } - - inline double sqr() const - { - return ( *this ) * ( *this ); - } - - inline double dot ( const CVec2& vec ) const - { - return ( m_X*vec[0] ) + ( m_Y*vec[1] ); - } - - inline double getAngle ( const CVec2& vec ) const - { - return acos ( dot ( vec ) / ( magnitude() *vec.magnitude() ) ); - } - - /// @param angle Rotation angle in radiants - inline CVec2 rotate ( float angle ) const - { - double xRot = m_X*cos ( angle ) - m_Y*sin ( angle ); - double yRot = m_X*sin ( angle ) + m_Y*cos ( angle ); - return CVec2 ( xRot, yRot ); - } - - inline bool equal ( CVec2 vec ) const - { - return ( m_X==vec.x() && m_Y==vec.y() ); - } - - /** - * Returns the string representation of the vector. - * @return string representation of the point. - */ - inline std::string toString() const - { - std::ostringstream str; - str << m_X << " " << m_Y; - return str.str(); - } - - protected: - double m_X, m_Y; -}; - -inline CVec2 operator* ( double f, const CVec2& v ) -{ - return v*f; -} - -inline CVec2 normalize ( const CVec2& v ) -{ - return v/v.magnitude(); -} - -#endif diff --git a/homer_mapping/src/OccupancyMap/Math/vec3_inl.h b/homer_mapping/src/OccupancyMap/Math/vec3_inl.h deleted file mode 100644 index 533eabbb..00000000 --- a/homer_mapping/src/OccupancyMap/Math/vec3_inl.h +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * vec3_inl.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#define THIS Vector3D - -#include <sstream> - -//---------------------------------------------------------------------------------------------------------- -inline THIS::THIS() -{} -//---------------------------------------------------------------------------------------------------------- -inline THIS::THIS ( float x, float y, float z ) -{ - m_X = x; m_Y = y; m_Z = z; -}; -//---------------------------------------------------------------------------------------------------------- -inline THIS::THIS ( const Vector3D& v2 ) -{ - m_X=v2[0]; - m_Y=v2[1]; - m_Z=v2[2]; -}; -//---------------------------------------------------------------------------------------------------------- -inline THIS::THIS ( const CVec2& v, float z) -{ - m_X=v[0]; - m_Y=v[1]; - m_Z=z; -} -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator+ ( const Vector3D& vVector ) const -{ - return Vector3D ( vVector[0] + m_X, vVector[1] + m_Y, vVector[2] + m_Z ); -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator-() const -{ - return Vector3D ( -m_X,-m_Y,-m_Z ); -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator+() const -{ - return Vector3D ( m_X,m_Y,m_Z ); -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator- ( const Vector3D& vVector ) const -{ - return Vector3D ( m_X-vVector[0],m_Y-vVector[1],m_Z-vVector[2] ); -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator* ( const float num ) const -{ - return Vector3D ( m_X * num, m_Y * num, m_Z * num ); -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D& THIS::operator*= ( const float num ) -{ - m_X*=num; m_Y*=num; m_Z*=num; - return *this; -} -//---------------------------------------------------------------------------------------------------------- -inline Vector3D& THIS::operator/= ( const float num ) -{ - m_X/=num; m_Y/=num; m_Z/=num; - return *this; -} -//---------------------------------------------------------------------------------------------------------- -inline float THIS::operator* ( const Vector3D& vVector ) const -{ - return vVector[0]*m_X+vVector[1]*m_Y+vVector[2]*m_Z; -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D& THIS::operator+= ( const Vector3D& vVector ) -{ - m_X+=vVector[0]; - m_Y+=vVector[1]; - m_Z+=vVector[2]; - return *this; -} -//---------------------------------------------------------------------------------------------------------- -inline bool THIS::operator < ( const Vector3D& vVec ) const -{ - if ( m_X<vVec[0] ) return true; - if ( m_X>vVec[0] ) return false; - if ( m_Y<vVec[1] ) return true; - if ( m_Y>vVec[1] ) return false; - return ( m_Z<vVec[2] ); -} -//---------------------------------------------------------------------------------------------------------- -inline bool THIS::operator > ( const Vector3D& vVec ) const -{ - if ( m_X<vVec[0] ) return false; - if ( m_X>vVec[0] ) return true; - if ( m_Y<vVec[1] ) return false; - if ( m_Y>vVec[1] ) return true; - return ( m_Z>vVec[2] ); -} -//---------------------------------------------------------------------------------------------------------- -inline Vector3D& THIS::operator-= ( const Vector3D& vVector ) -{ - m_X-=vVector[0]; - m_Y-=vVector[1]; - m_Z-=vVector[2]; - return *this; -} -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator^ ( const Vector3D& vVector2 ) const -{ - Vector3D vNormal; - - // Calculate the cross product with the non communitive equation - vNormal[0] = ( ( m_Y * vVector2[2] ) - ( m_Z * vVector2[1] ) ); - vNormal[1] = ( ( m_Z * vVector2[0] ) - ( m_X * vVector2[2] ) ); - vNormal[2] = ( ( m_X * vVector2[1] ) - ( m_Y * vVector2[0] ) ); - - // Return the cross product - return vNormal; -}; -//---------------------------------------------------------------------------------------------------------- -inline bool THIS::operator== ( const Vector3D& v1 ) const -{ - // this is evil! - assert ( 0 ); - - static const float EPS=1.0f/100.0f; - if ( fabs ( v1[0]-m_X ) >EPS ) return false; - if ( fabs ( v1[1]-m_Y ) >EPS ) return false; - if ( fabs ( v1[2]-m_Z ) >EPS ) return false; - - return true; -}; -//---------------------------------------------------------------------------------------------------------- -inline Vector3D THIS::operator/ ( float num ) const -{ - return Vector3D ( m_X / num, m_Y / num, m_Z / num ); -}; -//---------------------------------------------------------------------------------------------------------- -inline float THIS::operator [] ( const unsigned int i ) const -{ - return ( ( float* ) this ) [i]; -} -//---------------------------------------------------------------------------------------------------------- -inline float& THIS::operator [] ( const unsigned int i ) -{ - return ( ( float* ) this ) [i]; -} -//---------------------------------------------------------------------------------------------------------- -inline void THIS::set ( float fx, float fy, float fz ) -{ - m_X=fx; m_Y=fy; m_Z=fz; -} -//---------------------------------------------------------------------------------------------------------- -inline void THIS::lerp ( const Vector3D& v1, const Vector3D& v2,float f ) -{ - ( *this ) =v1* ( 1-f ) +v2*f; -} -//---------------------------------------------------------------------------------------------------------- -inline float THIS::magnitude() const -{ - return sqrtf ( m_X*m_X+m_Y*m_Y+m_Z*m_Z ); -} -//---------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------- -inline Vector3D operator* ( const float n,const Vector3D& v ) -{ - return Vector3D ( v[0]*n,v[1]*n,v[2]*n ); -}; -//---------------------------------------------------------------------------------------------------------- - - -#undef THIS - diff --git a/homer_mapping/src/OccupancyMap/OccupancyMap.cpp b/homer_mapping/src/OccupancyMap/OccupancyMap.cpp deleted file mode 100644 index 811d4f31..00000000 --- a/homer_mapping/src/OccupancyMap/OccupancyMap.cpp +++ /dev/null @@ -1,931 +0,0 @@ -#include "OccupancyMap.h" - -#include "Math/Math.h" - -#include <cmath> -#include <vector> -#include <fstream> -#include <sstream> -#include <QImage> - -#include <Eigen/Geometry> - -#include <ros/ros.h> -#include <tf/transform_listener.h> - -#include "homer_mapnav_msgs/ModifyMap.h" -#include "tools/loadRosConfig.h" -#include "tools/tools.h" - -//uncomment this to get extended information on the tracer -//#define TRACER_OUTPUT - -using namespace std; - -const float UNKNOWN_LIKELIHOOD = 0.3; - -// Flags of current changes // -const char NO_CHANGE = 0; -const char OCCUPIED = 1; -const char FREE = 2; -//the safety border around occupied pixels which is left unchanged -const char SAFETY_BORDER = 3; -/////////////////////////////// - -//assumed laser measure count for loaded maps -const int LOADED_MEASURECOUNT = 10; - - -OccupancyMap::OccupancyMap() -{ - initMembers(); -} - -OccupancyMap::OccupancyMap(float *&occupancyProbability, geometry_msgs::Pose origin, float resolution, int pixelSize, Box2D<int> exploredRegion) -{ - initMembers(); - - - m_Origin = origin; - m_Resolution = resolution; - m_PixelSize = pixelSize; - m_ByteSize = pixelSize * pixelSize; - m_ExploredRegion = exploredRegion; - m_ChangedRegion = exploredRegion; - - if ( m_OccupancyProbability ) - { - delete[] m_OccupancyProbability; - } - m_OccupancyProbability = occupancyProbability; - for(unsigned i = 0; i < m_ByteSize; i++) - { - if(m_OccupancyProbability[i] != 0.5) - { - m_MeasurementCount[i] = LOADED_MEASURECOUNT; - m_OccupancyCount[i] = m_OccupancyProbability[i] * (float)LOADED_MEASURECOUNT; - } - } -} - - -OccupancyMap::OccupancyMap ( const OccupancyMap& occupancyMap ) -{ - m_OccupancyProbability = 0; - m_MeasurementCount = 0; - m_OccupancyCount = 0; - m_CurrentChanges = 0; - m_InaccessibleCount = 0; - m_HighSensitive = 0; - m_LaserMaxRange = 0; - m_LaserMinRange = 0; - - *this = occupancyMap; -} - -OccupancyMap::~OccupancyMap() -{ - cleanUp(); -} - -void OccupancyMap::initMembers() -{ - float mapSize; - loadConfigValue("/homer_mapping/size", mapSize); - loadConfigValue("/homer_mapping/resolution", m_Resolution); - - //add one safety pixel - m_PixelSize = mapSize / m_Resolution + 1; - m_ByteSize = m_PixelSize * m_PixelSize; - - m_Origin.position.x = -m_PixelSize*m_Resolution/2; - m_Origin.position.y = -m_PixelSize*m_Resolution/2; - m_Origin.orientation.w = 1.0; - m_Origin.orientation.x = 0.0; - m_Origin.orientation.y = 0.0; - m_Origin.orientation.z = 0.0; - - loadConfigValue("/homer_mapping/backside_checking", m_BacksideChecking); - loadConfigValue("/homer_mapping/obstacle_borders", m_ObstacleBorders); - loadConfigValue("/homer_mapping/measure_sampling_step", m_MeasureSamplingStep); - loadConfigValue("/homer_mapping/laser_scanner/free_reading_distance", m_FreeReadingDistance); - - m_OccupancyProbability = new float[m_ByteSize]; - m_MeasurementCount = new unsigned short[m_ByteSize]; - m_OccupancyCount = new unsigned short[m_ByteSize]; - m_CurrentChanges = new unsigned char[m_ByteSize]; - m_InaccessibleCount = new unsigned char[m_ByteSize]; - m_HighSensitive = new unsigned short[m_ByteSize]; - for ( unsigned i=0; i<m_ByteSize; i++ ) - { - m_OccupancyProbability[i]=UNKNOWN_LIKELIHOOD; - m_OccupancyCount[i]=0; - m_MeasurementCount[i]=0; - m_CurrentChanges[i]=NO_CHANGE; - m_InaccessibleCount[i]=0; - m_HighSensitive[i] = 0; - } - - m_ExploredRegion=Box2D<int> ( m_PixelSize/2.1, m_PixelSize/2.1, m_PixelSize/1.9, m_PixelSize/1.9 ); - maximizeChangedRegion(); -} - - -OccupancyMap& OccupancyMap::operator= ( const OccupancyMap & occupancyMap ) -{ - // free allocated memory - cleanUp(); - - m_Resolution = occupancyMap.m_Resolution; - m_ExploredRegion = occupancyMap.m_ExploredRegion; - m_PixelSize = occupancyMap.m_PixelSize; - m_ByteSize = occupancyMap.m_ByteSize; - - loadConfigValue("/homer_mapping/backside_checking", m_BacksideChecking); - - // re-allocate all arrays - m_OccupancyProbability = new float[m_ByteSize]; - m_MeasurementCount = new unsigned short[m_ByteSize]; - m_OccupancyCount = new unsigned short[m_ByteSize]; - m_CurrentChanges = new unsigned char[m_ByteSize]; - m_InaccessibleCount = new unsigned char[m_ByteSize]; - m_HighSensitive = new unsigned short[m_ByteSize]; - - // copy array data - memcpy ( m_OccupancyProbability, occupancyMap.m_OccupancyProbability, m_ByteSize * sizeof ( *m_OccupancyProbability ) ); - memcpy ( m_MeasurementCount, occupancyMap.m_MeasurementCount, m_ByteSize * sizeof ( *m_MeasurementCount ) ); - memcpy ( m_OccupancyCount, occupancyMap.m_OccupancyCount, m_ByteSize * sizeof ( *m_OccupancyCount ) ); - memcpy ( m_CurrentChanges, occupancyMap.m_CurrentChanges, m_ByteSize * sizeof ( *m_CurrentChanges ) ); - memcpy ( m_InaccessibleCount, occupancyMap.m_InaccessibleCount, m_ByteSize * sizeof ( *m_InaccessibleCount ) ); - memcpy ( m_HighSensitive, occupancyMap.m_HighSensitive, m_ByteSize * sizeof ( *m_HighSensitive) ); - - - return *this; -} - -int OccupancyMap::width() const -{ - return m_PixelSize; -} - -int OccupancyMap::height() const -{ - return m_PixelSize; -} - -float OccupancyMap::getOccupancyProbability ( Eigen::Vector2i p ) -{ - unsigned offset = m_PixelSize * p.y() + p.x(); - if ( offset > unsigned ( m_ByteSize ) ) - { - return UNKNOWN_LIKELIHOOD; - } - return m_OccupancyProbability[ offset ]; -} - -void OccupancyMap::resetHighSensitive() -{ - ROS_INFO_STREAM("High sensitive Areas reseted"); - m_reset_high = true; -} - -void OccupancyMap::computeOccupancyProbabilities() -{ - for ( int y = m_ChangedRegion.minY(); y <= m_ChangedRegion.maxY(); y++ ) - { - int yOffset = m_PixelSize * y; - for ( int x = m_ChangedRegion.minX(); x <= m_ChangedRegion.maxX(); x++ ) - { - int i = x + yOffset; - if ( m_MeasurementCount[i] > 0 ) - { - m_OccupancyProbability[i] = m_OccupancyCount[i] / static_cast<float> ( m_MeasurementCount[i] ); - if (m_HighSensitive[i] == 1) - { - if(m_reset_high == true) - { - m_OccupancyCount[i] = 0; - m_OccupancyProbability[i] = 0; - } - if(m_MeasurementCount[i] > 20 ) - { - m_MeasurementCount[i] = 10; - m_OccupancyCount[i] = 10 * m_OccupancyProbability[i]; - } - if(m_OccupancyProbability[i] > 0.3) - { - m_OccupancyProbability[i] = 1 ; - } - } - } - else - { - m_OccupancyProbability[i] = UNKNOWN_LIKELIHOOD; - } - } - } - if(m_reset_high == true) - { - m_reset_high = false; - } -} - -void OccupancyMap::insertLaserData ( sensor_msgs::LaserScanConstPtr laserData ) -{ - markRobotPositionFree(); - - m_LaserMaxRange = laserData->range_max; - m_LaserMinRange = laserData->range_min; - tf::StampedTransform laserTransform; - try - { - m_tfListener.lookupTransform("/base_link", laserData->header.frame_id, ros::Time(0), laserTransform); - } - catch (tf::TransformException ex) { - ROS_ERROR_STREAM(ex.what()); - } - - m_LaserPos.x = laserTransform.getOrigin().getX(); - m_LaserPos.y = laserTransform.getOrigin().getY(); - - std::vector<RangeMeasurement> ranges; - ranges.reserve ( laserData->ranges.size() ); - - bool errorFound=false; - int lastValidIndex=-1; - float lastValidRange=m_FreeReadingDistance; - - RangeMeasurement rangeMeasurement; - rangeMeasurement.sensorPos = m_LaserPos; - for ( unsigned int i = 0; i < laserData->ranges.size(); i++ ) - { - if ( ( laserData->ranges[i] >= m_LaserMinRange ) && ( laserData->ranges[i] <= m_LaserMaxRange ) ) - { - //if we're at the end of an errorneous segment, interpolate - //between last valid point and current point - if ( errorFound ) - { - //smaller of the two ranges belonging to end points - float range = Math::min ( lastValidRange, laserData->ranges[i] ); - range -= m_Resolution * 2; - - if ( range < m_FreeReadingDistance ) - { - range = m_FreeReadingDistance; - } - else - if ( range > m_LaserMaxRange*0.8 ) - { - range = m_LaserMaxRange*0.8; - } - - //choose smaller range - for ( unsigned j=lastValidIndex+1; j<i; j++ ) - { - rangeMeasurement.endPos = map_tools::laser_range_to_point(range, j, laserData->angle_min, laserData->angle_increment, m_tfListener, laserData->header.frame_id, "/base_link");// laserConf->nativeLaserToRobot ( j, range ); //TODO use tf - rangeMeasurement.free = true; - ranges.push_back ( rangeMeasurement ); - } - } - rangeMeasurement.endPos = map_tools::laser_range_to_point(laserData->ranges[i], i, laserData->angle_min, laserData->angle_increment, m_tfListener, laserData->header.frame_id, "/base_link"); - rangeMeasurement.free = false; - ranges.push_back ( rangeMeasurement ); - - errorFound=false; - lastValidIndex=i; - lastValidRange=laserData->ranges[i]; - } - else - { - errorFound=true; - } - } - - if ( errorFound ) - { - for ( unsigned j=lastValidIndex+1; j<laserData->ranges.size(); j++ ) - { - rangeMeasurement.endPos = map_tools::laser_range_to_point(m_FreeReadingDistance, j, laserData->angle_min, laserData->angle_increment, m_tfListener, laserData->header.frame_id, "/base_link"); // - - rangeMeasurement.free = true; - ranges.push_back ( rangeMeasurement ); - } - } - - insertRanges ( ranges ); -} - - -void OccupancyMap::insertRanges ( vector<RangeMeasurement> ranges ) -{ - clearChanges(); - - Eigen::Vector2i lastEndPixel; - - - //paint safety borders - if ( m_ObstacleBorders ) - { - for ( unsigned i=0; i<ranges.size(); i++ ) - { - geometry_msgs::Point endPosWorld = map_tools::transformPoint(ranges[i].endPos, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i endPixel = map_tools::toMapCoords(endPosWorld, m_Origin, m_Resolution); - - for ( int y=endPixel.y()-1; y <= endPixel.y() +1; y++ ) - { - for ( int x=endPixel.x()-1; x <= endPixel.x() +1; x++ ) - { - unsigned offset=x+m_PixelSize*y; - if ( offset < unsigned ( m_ByteSize ) ) - { - m_CurrentChanges[ offset ] = SAFETY_BORDER; - } - } - } - } - } - //paint safety ranges - for ( unsigned i=0; i<ranges.size(); i++ ) - { - geometry_msgs::Point startPosWorld = map_tools::transformPoint(ranges[i].endPos, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i startPixel = map_tools::toMapCoords(startPosWorld, m_Origin, m_Resolution); - geometry_msgs::Point endPos; - endPos.x = ranges[i].endPos.x * 4; - endPos.y = ranges[i].endPos.y * 4; - - geometry_msgs::Point endPosWorld = map_tools::transformPoint(endPos, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i endPixel = map_tools::toMapCoords(endPosWorld, m_Origin, m_Resolution); - - - if(endPixel.x() < 0) endPixel.x() = 0; - if(endPixel.y() < 0) endPixel.y() = 0; - if(endPixel.x() >= m_PixelSize) endPixel.x() = m_PixelSize - 1; - if(endPixel.y() >= m_PixelSize) endPixel.y() = m_PixelSize - 1; - - drawLine ( m_CurrentChanges, startPixel, endPixel, SAFETY_BORDER ); - } - - //paint end pixels - for ( unsigned i=0; i<ranges.size(); i++ ) - { - if ( !ranges[i].free ) - { - geometry_msgs::Point endPosWorld = map_tools::transformPoint(ranges[i].endPos, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i endPixel = map_tools::toMapCoords(endPosWorld, m_Origin, m_Resolution); - - if ( endPixel != lastEndPixel ) - { - unsigned offset = endPixel.x() + m_PixelSize * endPixel.y(); - if ( offset < m_ByteSize ) - { - m_CurrentChanges[ offset ] = ::OCCUPIED; - } - } - lastEndPixel=endPixel; - } - } - - //paint free ranges - for ( unsigned i=0; i<ranges.size(); i++ ) - { - geometry_msgs::Point sensorPosWorld = map_tools::transformPoint(ranges[i].sensorPos, m_tfListener, "/base_link", "/map"); - geometry_msgs::Point endPosWorld = map_tools::transformPoint(ranges[i].endPos, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i sensorPixel = map_tools::toMapCoords(sensorPosWorld, m_Origin, m_Resolution); - Eigen::Vector2i endPixel = map_tools::toMapCoords(endPosWorld, m_Origin, m_Resolution); - - m_ChangedRegion.enclose ( sensorPixel.x(), sensorPixel.y() ); - m_ChangedRegion.enclose ( endPixel.x(), endPixel.y() ); - - if ( endPixel != lastEndPixel ) - { - drawLine ( m_CurrentChanges, sensorPixel, endPixel, ::FREE ); - } - - lastEndPixel=endPixel; - } - - m_ChangedRegion.clip ( Box2D<int> ( 0,0,m_PixelSize-1,m_PixelSize-1 ) ); - m_ExploredRegion.enclose ( m_ChangedRegion ); - applyChanges(); - computeOccupancyProbabilities(); -} - -double OccupancyMap::contrastFromProbability ( int8_t prob ) -{ - // range from 0..126 (=127 values) and 128..255 (=128 values) - double diff = ( ( double ) prob - UNKNOWN ); - double contrast; - if ( prob <= UNKNOWN ) - { - contrast = ( diff / UNKNOWN ); // 0..1 - } - else - { - contrast = ( diff / ( UNKNOWN+1 ) ); // 0..1 - } - return ( contrast * contrast ); -} - -double OccupancyMap::evaluateByContrast() -{ - double contrastSum = 0.0; - unsigned int contrastCnt = 0; - - for ( int y = m_ExploredRegion.minY(); y <= m_ExploredRegion.maxY(); y++ ) - { - for ( int x = m_ExploredRegion.minX(); x <= m_ExploredRegion.maxX(); x++ ) - { - int i = x + y * m_PixelSize; - if ( m_MeasurementCount [i] > 1 ) - { - int prob = m_OccupancyProbability[i] * 100; - if ( prob != NOT_SEEN_YET ) // ignore not yet seen cells - { - contrastSum += contrastFromProbability ( prob ); - contrastCnt++; - } - } - } - } - if ( ( contrastCnt ) > 0 ) - { - return ( ( contrastSum / contrastCnt ) * 100 ); - } - return ( 0 ); -} - - - -vector<MeasurePoint> OccupancyMap::getMeasurePoints (sensor_msgs::LaserScanConstPtr laserData) -{ - vector<MeasurePoint> result; - result.reserve ( laserData->ranges.size() ); - - double minDist = m_MeasureSamplingStep; - - m_LaserMaxRange = laserData->range_max; - m_LaserMinRange = laserData->range_min; - - Point2D lastHitPos; - Point2D lastUsedHitPos; - - //extract points for measuring - for ( unsigned int i=0; i < laserData->ranges.size(); i++ ) - { - if ( laserData->ranges[i] <= m_LaserMaxRange && laserData->ranges[i] >= m_LaserMinRange ) - { - geometry_msgs::Point hitPosMsg = map_tools::laser_range_to_point(laserData->ranges[i], i, laserData->angle_min, laserData->angle_increment, m_tfListener, laserData->header.frame_id, "/base_link"); //laserConf->nativeLaserToRobot ( i, laserData[i] ); //tf - Point2D hitPos(hitPosMsg.x, hitPosMsg.y); - - if ( hitPos.distance ( lastUsedHitPos ) >= minDist ) - { - MeasurePoint p; - //preserve borders of segments - if ( ( i!=0 ) && - ( lastUsedHitPos.distance ( lastHitPos ) > m_Resolution*0.5 ) && - ( hitPos.distance ( lastHitPos ) >= minDist*1.5 ) ) - { - p.hitPos = lastHitPos; - p.borderType = RightBorder; - result.push_back ( p ); - p.hitPos = hitPos; - p.borderType = LeftBorder; - result.push_back ( p ); - lastUsedHitPos = hitPos; - } - else - { - //save current point - p.hitPos = hitPos; - p.borderType = NoBorder; - result.push_back ( p ); - lastUsedHitPos = hitPos; - } - } - lastHitPos = hitPos; - } - } - - //the first and last one are border pixels - if ( result.size() > 0 ) - { - result[0].borderType = LeftBorder; - result[result.size()-1].borderType = RightBorder; - } - - //calculate front check points - for ( unsigned i=0; i < result.size(); i++ ) - { - CVec2 diff; - - switch ( result[i].borderType ) - { - case NoBorder: - diff = result[i-1].hitPos - result[i+1].hitPos; - break; - case LeftBorder: - diff = result[i].hitPos - result[i+1].hitPos; - break; - case RightBorder: - diff = result[i-1].hitPos - result[i].hitPos; - break; - } - - CVec2 normal = diff.rotate ( Math::Pi * 0.5 ); - normal.normalize(); - normal *= m_Resolution * sqrt ( 2.0 ) * 10.0; - - result[i].frontPos = result[i].hitPos + normal; - } - - return result; -} - - -float OccupancyMap::computeScore ( Pose robotPose, std::vector<MeasurePoint> measurePoints ) -{ - // This is a very simple implementation, using only the end point of the beam. - // For every beam the end cell is computed and tested if the cell is occupied. - unsigned lastOffset=0; - unsigned hitOffset=0; - unsigned frontOffset=0; - float fittingFactor = 0.0; - - float sinTheta = sin ( robotPose.theta() ); - float cosTheta = cos ( robotPose.theta() ); - - for ( unsigned int i = 0; i < measurePoints.size(); i++ ) - { - //fast variant: - float x = cosTheta * measurePoints[i].hitPos.x() - sinTheta * measurePoints[i].hitPos.y() + robotPose.x(); - float y = sinTheta * measurePoints[i].hitPos.x() + cosTheta * measurePoints[i].hitPos.y() + robotPose.y(); - geometry_msgs::Point hitPos; - hitPos.x = x; - hitPos.y = y; - - Eigen::Vector2i hitPixel = map_tools::toMapCoords(hitPos, m_Origin, m_Resolution); - hitOffset = hitPixel.x() + m_PixelSize*hitPixel.y(); - - //avoid multiple measuring of same pixel or unknown pixel - if ( ( hitOffset == lastOffset ) || ( hitOffset >= unsigned ( m_ByteSize ) ) || ( m_MeasurementCount[hitOffset] == 0 ) ) - { - continue; - } - - if ( m_BacksideChecking ) - { - //avoid matching of back and front pixels of obstacles - x = cosTheta * measurePoints[i].frontPos.x() - sinTheta * measurePoints[i].frontPos.y() + robotPose.x(); - y = sinTheta * measurePoints[i].frontPos.x() + cosTheta * measurePoints[i].frontPos.y() + robotPose.y(); - geometry_msgs::Point frontPos; - frontPos.x = x; - frontPos.y = y; - - Eigen::Vector2i frontPixel = map_tools::toMapCoords(frontPos, m_Origin, m_Resolution); - frontOffset = frontPixel.x() + m_PixelSize*frontPixel.y(); - - if ( ( frontOffset >= unsigned ( m_ByteSize ) ) || ( m_MeasurementCount[frontOffset] == 0 ) ) - { - continue; - } - } - - lastOffset=hitOffset; - //fittingFactor += m_SmoothOccupancyProbability[ offset ]; - fittingFactor += m_OccupancyProbability[ hitOffset ]; - } - return fittingFactor; -} - - -template<class DataT> -void OccupancyMap::drawLine ( DataT* data, Eigen::Vector2i& startPixel, Eigen::Vector2i& endPixel, char value ) -{ - - //bresenham algorithm - int xstart = startPixel.x(); - int ystart = startPixel.y(); - int xend = endPixel.x(); - int yend = endPixel.y(); - - int x, y, t, dist, xerr, yerr, dx, dy, incx, incy; - // compute distances - dx = xend - xstart; - dy = yend - ystart; - - // compute increment - if ( dx < 0 ) - { - incx = -1; - dx = -dx; - } - else - { - incx = dx ? 1 : 0; - } - - if ( dy < 0 ) - { - incy = -1; - dy = -dy; - } - else - { - incy = dy ? 1 : 0; - } - - // which distance is greater? - dist = ( dx > dy ) ? dx : dy; - // initializing - x = xstart; - y = ystart; - xerr = dx; - yerr = dy; - - // compute cells - for ( t = 0; t < dist; t++ ) - { - int index = x + m_PixelSize * y; - // set flag to free if no flag is set - // (do not overwrite occupied cells) - if(index < 0) continue; - if ( data[index] == NO_CHANGE ) - { - data[index] = value; - } -/* if ( data[index] == OCCUPIED || data[index] == SAFETY_BORDER ) - { - return; - }*/ - xerr += dx; - yerr += dy; - if ( xerr > dist ) - { - xerr -= dist; - x += incx; - } - if ( yerr > dist ) - { - yerr -= dist; - y += incy; - } - } -} - - -void OccupancyMap::applyChanges() -{ - for ( int y = m_ChangedRegion.minY(); y <= m_ChangedRegion.maxY(); y++ ) - { - int yOffset = m_PixelSize * y; - for ( int x = m_ChangedRegion.minX(); x <= m_ChangedRegion.maxX(); x++ ) - { - int i = x + yOffset; - if ( ( m_CurrentChanges[i] == ::FREE || m_CurrentChanges[i] == ::OCCUPIED ) && m_MeasurementCount[i] < SHRT_MAX ) - { - m_MeasurementCount[i]++; - } - if ( m_CurrentChanges[i] == ::OCCUPIED && m_OccupancyCount[i] < USHRT_MAX ) - { - m_OccupancyCount[i]++; - } - } - } -} - -void OccupancyMap::clearChanges() -{ - m_ChangedRegion.expand ( 2 ); - m_ChangedRegion.clip ( Box2D<int> ( 0,0,m_PixelSize-1,m_PixelSize-1 ) ); - for ( int y = m_ChangedRegion.minY(); y <= m_ChangedRegion.maxY(); y++ ) - { - int yOffset = m_PixelSize * y; - for ( int x = m_ChangedRegion.minX(); x <= m_ChangedRegion.maxX(); x++ ) - { - int i = x + yOffset; - m_CurrentChanges[i] = NO_CHANGE; - } - } - m_ChangedRegion=Box2D<int> ( m_PixelSize - 1, m_PixelSize - 1, 0, 0 ); -} - -void OccupancyMap::incrementMeasurementCount ( Eigen::Vector2i p ) -{ - unsigned index = p.x() + m_PixelSize * p.y(); - if ( index < m_ByteSize ) - { - if ( m_CurrentChanges[index] == NO_CHANGE && m_MeasurementCount[index] < USHRT_MAX ) - { - m_CurrentChanges[index] = ::FREE; - m_MeasurementCount[index]++; - } - } - else - { - ROS_ERROR( "Index out of bounds: x = %d, y = %d", p.x(), p.y() ); - } -} - -void OccupancyMap::incrementOccupancyCount ( Eigen::Vector2i p ) -{ - int index = p.x() + m_PixelSize * p.y(); - if ( ( m_CurrentChanges[index] == NO_CHANGE || m_CurrentChanges[index] == ::FREE ) && m_MeasurementCount[index] < USHRT_MAX ) - { - m_CurrentChanges[index] = ::OCCUPIED; - m_OccupancyCount[index]++; - } -} - -void OccupancyMap::scaleDownCounts ( int maxCount ) -{ - clearChanges(); - if ( maxCount <= 0 ) - { - ROS_WARN("WARNING: argument maxCount is choosen to small, resetting map."); - memset ( m_MeasurementCount, 0, m_ByteSize ); - memset ( m_OccupancyCount, 0, m_ByteSize ); - memset ( m_InaccessibleCount, 0, m_ByteSize ); - } - else - { - for ( unsigned i = 0; i < m_ByteSize; i++ ) - { - int scalingFactor = m_MeasurementCount[i] / maxCount; - if ( scalingFactor != 0 ) - { - m_MeasurementCount[i] /= scalingFactor; - m_OccupancyCount[i] /= scalingFactor; - m_InaccessibleCount[i] /= scalingFactor; - } - if ( m_InaccessibleCount[i] > maxCount ) - { - m_InaccessibleCount[i] = maxCount; - } - } - } - maximizeChangedRegion(); - applyChanges(); - computeOccupancyProbabilities(); -} - - -void OccupancyMap::markRobotPositionFree() -{ - geometry_msgs::Point point; - point.x = 0; - point.y = 0; - point.z = 0; - geometry_msgs::Point endPosWorld = map_tools::transformPoint(point, m_tfListener, "/base_link", "/map"); - Eigen::Vector2i robotPixel = map_tools::toMapCoords(endPosWorld, m_Origin, m_Resolution); - - int width = 0.3 / m_Resolution; - for ( int i = robotPixel.y() - width; i <= robotPixel.y() + width; i++ ) - { - for ( int j = robotPixel.x() - width; j <= robotPixel.x() + width; j++ ) - { - incrementMeasurementCount ( Eigen::Vector2i ( i, j ) ); - } - } - Box2D<int> robotBox ( robotPixel.x()-width, robotPixel.y()-width, robotPixel.x() +width, robotPixel.y() +width ); - m_ChangedRegion.enclose ( robotBox ); - m_ExploredRegion.enclose ( robotBox ); -} - - -QImage OccupancyMap::getProbabilityQImage ( int trancparencyThreshold, bool showInaccessible ) const -{ - QImage retImage ( m_PixelSize, m_PixelSize, QImage::Format_RGB32 ); - for ( int y = 0; y < m_PixelSize; y++ ) - { - for ( int x = 0; x < m_PixelSize; x++ ) - { - int index = x + y * m_PixelSize; - int value = UNKNOWN; - if ( m_MeasurementCount[index] > 0 ) - { - value = static_cast<int> ( ( 1.0 - m_OccupancyProbability[index] ) * 255 ); - if ( m_MeasurementCount[index] < trancparencyThreshold ) - { - value = static_cast<int> ( ( 0.75 + 0.025 * m_MeasurementCount[index] ) * ( 1.0 - m_OccupancyProbability[index] ) * 255 ); - } - } - if ( showInaccessible && m_InaccessibleCount[index] >= 2 ) - { - value = 0; - } - retImage.setPixel ( x, y, qRgb ( value, value, value ) ); - } - } - return retImage; -} - -void OccupancyMap::getOccupancyProbabilityImage ( vector<int8_t>& data, int& width, int& height, float& resolution ) -{ - width = m_PixelSize; - height = m_PixelSize; - resolution = m_Resolution; - data.resize(m_PixelSize * m_PixelSize); - std::fill(data.begin(), data.end(), (int8_t)NOT_SEEN_YET); //note: linker error without strange cast from int8_t to int8_t - for ( int y = m_ExploredRegion.minY(); y <= m_ExploredRegion.maxY(); y++ ) - { - int yOffset = m_PixelSize * y; - for ( int x = m_ExploredRegion.minX(); x <= m_ExploredRegion.maxX(); x++ ) - { - int i = x + yOffset; - if ( m_MeasurementCount[i] < 1 ) - { - continue; - } - // set inaccessible points to black - if ( m_InaccessibleCount[i] >= 2 ) - { - data[i] = 99; - continue; - } - if(m_OccupancyProbability[i] == UNKNOWN_LIKELIHOOD) - { - data[i] = NOT_SEEN_YET; - } - else - { - data[i] = (int)(m_OccupancyProbability[i] * 99); //TODO maybe - 2 (or *0.99 or smth) - } - } - } -} - -void OccupancyMap::maximizeChangedRegion() -{ - m_ChangedRegion=m_ExploredRegion; -} - -void OccupancyMap::applyMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg) -{ - if(msg->data.size() != m_ByteSize) - { - ROS_ERROR_STREAM("Size Mismatch between SLAM map (" << m_ByteSize << ") and masking map (" << msg->data.size() << ")"); - return; - } - for(size_t y = 0; y < msg->info.height; y++) - { - int yOffset = msg->info.width * y; - for(size_t x = 0; x < msg->info.width; x++) - { - int i = yOffset + x; - - switch(msg->data[i]) - { - case homer_mapnav_msgs::ModifyMap::BLOCKED: - case homer_mapnav_msgs::ModifyMap::OBSTACLE: - //increase measure count of cells which were not yet visible to be able to modify unknown areas - if(m_MeasurementCount[i] == 0) - m_MeasurementCount[i] = 10; - - m_OccupancyCount[i] = m_MeasurementCount[i]; - m_OccupancyProbability[i] = 1.0; - m_ExploredRegion.enclose(x, y); - break; - case homer_mapnav_msgs::ModifyMap::FREE: - //see comment above - if(m_MeasurementCount[i] == 0) - m_MeasurementCount[i] = 10; - - m_OccupancyCount[i] = 0; - m_OccupancyProbability[i] = 0.0; - m_ExploredRegion.enclose(x, y); - break; - case homer_mapnav_msgs::ModifyMap::HIGH_SENSITIV: - m_HighSensitive[i] = 1; - break; - } - } - } -} - -void OccupancyMap::cleanUp() -{ - if ( m_OccupancyProbability ) - { - delete[] m_OccupancyProbability; - } - if ( m_MeasurementCount ) - { - delete[] m_MeasurementCount; - } - if ( m_OccupancyCount ) - { - delete[] m_OccupancyCount; - } - if ( m_CurrentChanges ) - { - delete[] m_CurrentChanges; - } - if ( m_InaccessibleCount ) - { - delete[] m_InaccessibleCount; - } - if ( m_HighSensitive ) - { - delete[] m_HighSensitive; - } -} diff --git a/homer_mapping/src/OccupancyMap/OccupancyMap.h b/homer_mapping/src/OccupancyMap/OccupancyMap.h deleted file mode 100644 index 718b2dab..00000000 --- a/homer_mapping/src/OccupancyMap/OccupancyMap.h +++ /dev/null @@ -1,379 +0,0 @@ -#ifndef OCCUPANCYMAP_H -#define OCCUPANCYMAP_H - -#include <vector> -#include <list> -#include <string> -#include <iostream> - -#include <Eigen/Geometry> - -#include "Math/Pose.h" -#include "Math/Point2D.h" -#include "Math/Box2D.h" - -#include "nav_msgs/OccupancyGrid.h" -#include <tf/transform_listener.h> - -#include <sensor_msgs/LaserScan.h> - -class QImage; - -using namespace std; - -/** - * Structure to store the start and end point of each laser range in the current scan - * @param sensorPos position of the laser in the current scan (in base_link frame) - * @param endPos position of the end point of the laser frame in the current scan (in base_link frame) - * @param free indicates if the laser range hit an obstacle (false) or not (true) - */ -struct RangeMeasurement -{ - geometry_msgs::Point sensorPos; - geometry_msgs::Point endPos; - bool free; -}; - -/** - * Used in struct MeasurePoint to specify if a measurement point is at the border of a scan segment - */ -enum BorderType -{ - NoBorder, - LeftBorder, - RightBorder -}; - -/** - * Structure to store a measurement point for computeLaserScanProbability() - * @param hitPos Position of measured obstacle (robot coordinates) - * @param frontPos Position to check for NOT_KNOWN terrain - * This is needed to assure that front- and backside of obstacles can be distinguished - * @param border specifies if the measurement point is at the border of a scan segment - */ -struct MeasurePoint -{ - Point2D hitPos; - Point2D frontPos; - BorderType borderType; -}; - -/** - * @class OccupancyMap - * - * @author Malte Knauf, Stephan Wirth, Susanne Maur (RX), David Gossow (RX), Susanne Thierfelder (R16) - * - * @brief This class holds and manages an occupancy map. - * - * An occupancy map is a map where free space and occupied space are marked. This map stores values - * for free and occupied space in an (2D-)unsigned char array. This array can be seen as a graylevel image. - * The darker a cell, the higher the probability that this cell is occupied by an obstacle. - * The size of the map and the size of one cell can be defined in the setup file with the values - * MAP_SIZE and MAP_CELL_SIZE. The origin of the coordinate system of the map is the center of the array. - * The x-axis is heading front, the y-axis points to the left (like the robot's coordinate system). - * The mapping data has to be inserted via the method insertLaserData(). - */ -class OccupancyMap { - - public: - static const int8_t INACCESSIBLE = 100; - static const int8_t OBSTACLE = 99; - static const int8_t OCCUPIED = 98; - static const int8_t UNKNOWN = 50; - static const int8_t NOT_SEEN_YET = -1; - static const int8_t FREE = 0; - - /** - * The default constructor calls initMembers(). - */ - OccupancyMap(); - - /** - * Constructor for a loaded map. - */ - OccupancyMap(float*& occupancyProbability, geometry_msgs::Pose origin, float resolution, int pixelSize, Box2D<int> exploredRegion); - - /** - * Copy constructor, copies all members inclusive the arrays that lie behind the pointers. - * @param occupancyMap Source for copying - */ - OccupancyMap(const OccupancyMap& occupancyMap); - - /** - * Method to init all members with default values from the configuration file. All arrays are initialized. - */ - void initMembers(); - - /** - * Assignment operator, copies all members (deep copy!) - * @param source Source to copy from - * @return Reference to copied OccupancyMap - */ - OccupancyMap& operator=(const OccupancyMap& source); - - /** - * Deletes all dynamically allocated memory. - */ - ~OccupancyMap(); - - /* - /** - * @return The resolution of the map in m. - */ -// int resolution() const; - - geometry_msgs::Pose origin() const; - - /** - * @return Width of the map. - */ - int width() const; - - /** - * @return Height of the map. - */ - int height() const; - - /** - * This method is used to reset all HighSensitive areas - */ - void resetHighSensitive(); - - /** - * @return Probability of pixel p being occupied. - */ - float getOccupancyProbability(Eigen::Vector2i p); - - /** - * @brief This function inserts the data of a laserscan into the map. - * - * With the given data, start and end cells of a laser beam are computed and given to the - * method markLineFree(). - * If the measurement is smaller than VALID_MAX_RANGE, markOccupied() is called for the endpoint. - * @param laserData The laser data msg. - */ - void insertLaserData( sensor_msgs::LaserScanConstPtr laserData ); - - void insertRanges( vector<RangeMeasurement> ranges ); - - /** - * @brief gives a list specially processed coordinates to be used for computeLaserScanProbability - */ - std::vector<MeasurePoint> getMeasurePoints( sensor_msgs::LaserScanConstPtr laserData ); - - /** - * This method computes a score that describes how good the given hypothesis matches with the map - * @param robotPose The pose of the robot - * @return The "fitting factor". The higher the factor, the better the fitting. - * This factor is NOT normalized, it is a positive float between 0 and FLOAT_MAX - */ - float computeScore( Pose robotPose, std::vector<MeasurePoint> measurePoints ); - - /** - * @return QImage of size m_PixelSize, m_PixelSize with values of m_OccupancyProbability scaled to 0-254 - */ - QImage getProbabilityQImage(int trancparencyThreshold, bool showInaccessible) const; - - //puma2::ColorImageRGB8* getUpdateImage( bool withMap=true ); TODO - - /** - * Returns an "image" of the obstacles e.g. seen in the 3D scans - * @returns image with dark red dots in areas where the obstacles were seen - */ - //puma2::ColorImageRGB8* getObstacleImage ( ); TODO - - /** - * Returns an "image" of occupancy probability image. - * @param[out] data vector containing occupancy probabilities. 0 = free, 100 = occupied, -1 = NOT_KNOWN - * @param[out] width Width of data array - * @param[out] height Height of data array - * @param[out] resolution Resolution of the map (m_Resolution) - */ - void getOccupancyProbabilityImage(vector<int8_t> &data, int& width, int& height, float &resolution); - - /** - * This method marks free the position of the robot (according to its dimensions). - */ - void markRobotPositionFree(); - - /** - * @brief Computes the contrast of a single pixel. - * @param prob probability value (100=occupied, 50=NOT_KNOWN, 0=free) of a pixel. - * @return Contrast value from 0 (no contrast) to 1 (max. contrast) of this pixel - */ - double contrastFromProbability (int8_t prob); - - /** - * @brief This method computes the sharpness of the occupancy grid - * @return Contrast value from 0 (no contrast) to 1 (max. contrast) of the map - */ - double evaluateByContrast(); - - /// GETTERS - - Box2D<int> getExploredRegion() { return m_ExploredRegion; } - Box2D<int> getChangedRegion() { return m_ChangedRegion; } - - /** - * Sets cells of this map to free or occupied according to maskMap - */ - void applyMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg); - - - protected: - - /** - * This method increments m_MeasurementCount for pixel p. - * @param p Pixel that has been measured. - */ - void incrementMeasurementCount(Eigen::Vector2i p); - - /** - * This method increments the occupancy count int m_OccupancyCount for pixel p. - * @param p Occupied pixel. - */ - void incrementOccupancyCount(Eigen::Vector2i p); - - /** - * This method increments m_MeasurementCount and if neccessary m_OccupancyCount for all pixels. - */ - void applyChanges(); - - void clearChanges(); - - /** - * This method scales the counts of all pixels down to the given value. - * @param maxCount Maximum value to which all counts are set. - */ - void scaleDownCounts(int maxCount); - - /** - * This function paints a line from a start pixel to an end pixel. - * The computation is made with the Bresenham algorithm. - * @param data array on which the line shall be painted - * @param startPixel starting coordinates of the beam - * @param endPixel ending coordinates of the beam - * @param value The value with which the lines are marked. - */ - template<class DataT> - void drawLine(DataT* data, Eigen::Vector2i& startPixel, Eigen::Vector2i& endPixel, char value); - - /** - * This method computes the values for m_OccupancyProbabilities from m_MeasurementCount and m_OccupancyCount. - */ - void computeOccupancyProbabilities(); - - /** - * This method sets all values of m_CurrentChanges to NO_CHANGE. - */ - void clearCurrentChanges(); - - /** - * This method resets all values of m_MinChangeX, m_MaxChangeX, m_MinChangeY and m_MaxChangeY. - * This means that no current changes are assumed. - */ - void resetChangedRegion(); - - /** - * This method updates the values of m_MinChangeX, m_MaxChangeX, m_MinChangeY and m_MaxChangeY to current changes. - * The area around the current robot pose will be included to the changed region. - * @param robotPose The current pose of the robot. - */ - void updateChangedRegion(Pose robotPose); - - /** - * This method sets all values of m_MinChangeX, m_MaxChangeX, m_MinChangeY and m_MaxChangeY - * to initial values so that the complete map will be processed. - */ - void maximizeChangedRegion(); - - /** - * This method resets all values of m_ExploredX, m_MaxExploredX, m_MinExploredY and m_MaxExploredY. - */ - void resetExploredRegion(); - - /** - * Deletes all allocated members. - */ - void cleanUp(); - - /** - * Stores the size of one map pixel in m. - */ - float m_Resolution; - - /** - * Stores the origin of the map - */ - geometry_msgs::Pose m_Origin; - /** - * Stores the width of the map in cell numbers. - */ - int m_PixelSize; - - /** - * Stores the size of the map arrays, i.e. m_PixelSize * m_PixelSize - * for faster computation. - */ - unsigned m_ByteSize; - - /** - * Array to store occupancy probability values. - * Values between 0 and 1. - */ - float* m_OccupancyProbability; - - // Counts how often a pixel is hit by a measurement. - unsigned short* m_MeasurementCount; - - // Counts how often a pixel is hit by a measurement that says the pixel is occupied. - unsigned short* m_OccupancyCount; - - // Counts how often a cell is marked as inaccessible via markInaccessible() - unsigned char* m_InaccessibleCount; - - // Used for setting flags for cells, that have been modified during the current update. - unsigned char* m_CurrentChanges; - - // Used for high Sensitive areas - unsigned short* m_HighSensitive; - - /** - * Store values from config files. - */ - // maximum valid range of one laser measurement - float m_LaserMaxRange; - //minimum valid range of one laser measurement - float m_LaserMinRange; - //minimum range classified as free in case of errorneous laser measurement - float m_FreeReadingDistance; - //enables checking to avoid matching front- and backside of an obstacle, e.g. wall - bool m_BacksideChecking; - //leaves a small border around obstacles unchanged when inserting a laser scan - bool m_ObstacleBorders; - //minimum distance in m between two samples for probability calculation - float m_MeasureSamplingStep; - - //bool to reset high_sensitive Areas on the next iteration - bool m_reset_high; - - //position of the laser scaner in base_link frame - geometry_msgs::Point m_LaserPos; - - /** - * Defines a bounding box around the changes in the current map. - */ - Box2D<int> m_ChangedRegion; - - /** - * Defines a bounding box around the area in the map, which is already explored. - */ - Box2D<int> m_ExploredRegion; - - /** - * ros transform listener - */ - tf::TransformListener m_tfListener; - -}; -#endif diff --git a/homer_mapping/src/ParticleFilter/CMakeLists.txt b/homer_mapping/src/ParticleFilter/CMakeLists.txt deleted file mode 100644 index d96f7175..00000000 --- a/homer_mapping/src/ParticleFilter/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -set( - ParticleFilter_SRC - HyperSlamFilter.cpp - SlamParticle.cpp - SlamFilter.cpp - Particle.cpp -) - -add_library( - ParticleFilter - ${ParticleFilter_SRC} -) - -target_link_libraries( - ParticleFilter - OccupancyMap - MappingMath -) diff --git a/homer_mapping/src/ParticleFilter/HyperSlamFilter.cpp b/homer_mapping/src/ParticleFilter/HyperSlamFilter.cpp deleted file mode 100755 index cd005dbd..00000000 --- a/homer_mapping/src/ParticleFilter/HyperSlamFilter.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "HyperSlamFilter.h" - -#include <vector> -#include <cmath> -#include <fstream> -#include <sstream> -#include <stdlib.h> - -#include "ros/ros.h" - -using namespace std; - -HyperSlamFilter::HyperSlamFilter (int particleFilterNum, int particleNum ) -{ - m_ParticleFilterNum = particleFilterNum; - if ( m_ParticleFilterNum < 1 ) - { - m_ParticleFilterNum = 1; - } - ROS_DEBUG( "Using %d Hyper Particles.", particleFilterNum); - - m_ParticleNum = particleNum; - - m_DoMapping = true; - - m_DeletionThreshold = 0.98; - - for ( unsigned i=0; i < m_ParticleFilterNum; i++ ) - { - ostringstream stream; - stream << "SlamFilter " << i; - SlamFilter *slamFilter = new SlamFilter ( particleNum ); - m_SlamFilters.push_back ( slamFilter ); - } - - m_BestSlamFilter = m_SlamFilters[0]; -} - -HyperSlamFilter::~HyperSlamFilter() -{ - for (unsigned i = 0; i < m_ParticleFilterNum; i++) - { - if( m_SlamFilters[i] ) - { - delete m_SlamFilters[i]; - m_SlamFilters[i] = 0; - } - } - -} - -void HyperSlamFilter::setRotationErrorRotating ( float percent ) -{ - for ( unsigned i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setRotationErrorRotating(percent / 100.0); - } -} - -void HyperSlamFilter::setRotationErrorTranslating ( float degreePerMeter ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setRotationErrorTranslating(degreePerMeter / 180.0 * M_PI); - } -} - -void HyperSlamFilter::setTranslationErrorTranslating ( float percent ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setTranslationErrorTranslating(percent / 100.0); - } -} - -void HyperSlamFilter::setTranslationErrorRotating ( float mPerDegree ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setTranslationErrorRotating( mPerDegree / 180.0 * M_PI ); - } -} - -void HyperSlamFilter::setMoveJitterWhileTurning ( float mPerDegree ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setMoveJitterWhileTurning( mPerDegree / 180.0 * M_PI ); - } -} - -void HyperSlamFilter::setScanMatchingClusterSize ( float minClusterSize ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setScanMatchingClusterSize( minClusterSize ); - } -} - -void HyperSlamFilter::resetHigh() -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->resetHigh(); - } -} - -void HyperSlamFilter::setMapping ( bool doMapping ) -{ - m_DoMapping = doMapping; -} - -void HyperSlamFilter:: setOccupancyMap ( OccupancyMap* occupancyMap ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setOccupancyMap( occupancyMap ); - } -} - -void HyperSlamFilter::setRobotPose ( Pose pose, double scatterVarXY, double scatterVarTheta ) -{ - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - m_SlamFilters[i]->setRobotPose(pose, scatterVarXY, scatterVarTheta); - } -} - -void HyperSlamFilter::filter ( Pose currentPose, sensor_msgs::LaserScanConstPtr laserData, ros::Time measurementTime, ros::Duration &filterDuration) -{ - //call filter methods of all particle filters - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - bool randOnOff = (rand() % 100) < 80; - //if mapping is on, switch on with 80% probability to introduce some randomness in different particle filters - m_SlamFilters[i]->setMapping( m_DoMapping && randOnOff ); - m_SlamFilters[i]->filter(currentPose, laserData, measurementTime, filterDuration); - } - - //determine which map has the best/worst contrast - double bestContrast = 0.0; - static unsigned int bestFilter = 0; - double worstContrast = 100.0; - static unsigned int worstFilter = 0; - - for ( unsigned int i=0; i < m_SlamFilters.size(); i++ ) - { - double contrast = m_SlamFilters[i]->evaluateByContrast(); - { - if( contrast > bestContrast ) - { - bestContrast = contrast; - bestFilter = i; - } - if ( contrast < worstContrast ) - { - worstContrast = contrast; - worstFilter = i; - } - } - } - - // set best filter - SlamFilter* lastBestFilter = m_BestSlamFilter; - m_BestSlamFilter = m_SlamFilters[bestFilter]; - - if ( m_BestSlamFilter != lastBestFilter ) - { - ROS_INFO( "Switched to best filter %d (bestContrast: %f) -- the worst filter is %d (worstContrast: %f)", bestFilter, bestContrast, worstFilter, worstContrast); //TODO - } - - if ( bestFilter != worstFilter ) - { - if ( worstContrast < ( bestContrast * m_DeletionThreshold ) ) - { - // replace the worst filter by the one with the best contrast - delete m_SlamFilters[worstFilter]; - m_SlamFilters[worstFilter] = new SlamFilter ( * m_SlamFilters [bestFilter] ); - } - } -} - -SlamFilter* HyperSlamFilter::getBestSlamFilter() -{ - return m_BestSlamFilter; -} - -void HyperSlamFilter::setDeletionThreshold(double deletionThreshold) -{ - m_DeletionThreshold = deletionThreshold; -} diff --git a/homer_mapping/src/ParticleFilter/HyperSlamFilter.h b/homer_mapping/src/ParticleFilter/HyperSlamFilter.h deleted file mode 100755 index d02c2b6d..00000000 --- a/homer_mapping/src/ParticleFilter/HyperSlamFilter.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef HYPERSLAMFILTER_H -#define HYPERSLAMFILTER_H - -#include <vector> -#include "ParticleFilter.h" -#include "SlamParticle.h" -#include "SlamFilter.h" -#include "Math/Pose.h" -#include "../OccupancyMap/OccupancyMap.h" - -#include "sensor_msgs/LaserScan.h" - -class OccupancyMap; - -/** - * @class HyperSlamFilter - * - * @author Malte Knauf, Stephan Wirth, Susanne Maur - * - * @brief This class is used to determine the robot's most likely pose with given map and given laser data. - * - * A particle filter is a descrete method to describe and compute with a probability distribution. - * This particle filter uses an occupancy map to determine the probability of robot states. - * The robot states are stored in a particle together with their weight @see SlamParticle. - * - * @see SlamParticle - * @see ParticleFilter - * @see OccupancyMap - */ -class HyperSlamFilter { - - public: - - /** - * This constructor initializes the random number generator and sets the member variables to the given values. - * @param particleNum Number of particleFilters to use. - */ - HyperSlamFilter(int particleFilterNum, int particleNum); - - /** - * The destructor releases the OccupancyMap and the particles. - */ - ~HyperSlamFilter(); - - /** - * This method runs the filter routine. - * The given odometry measurement is used as movement hypothesis, the laserData-vector is used - * as measurement and is used to weight the particles. - * @param currentPoseOdometry Odometry data of time t. - * @param laserData msg containing the laser measurement. - * @param measurementTime Time stamp of the measurement. - * @param filterDurationTime Returns the time in ms that the filtering needed - */ - void filter(Pose currentPoseOdometry, sensor_msgs::LaserScanConstPtr laserData, ros::Time measurementTime, - ros::Duration &filterDuration); - - /** - * Computes and sets the new value for m_Alpha1. - * @param percent Rotation error while rotating (see class constructor for details) - */ - void setRotationErrorRotating(float percent); - - /** - * Computes and sets the new value for m_Alpha2. - * @param degreesPerMeter Rotation error while translating (see class constructor for details) - */ - void setRotationErrorTranslating(float degreesPerMeter); - - /** - * Computes and sets the new value for m_Alpha3. - * @param percent Translation error while translating (see class constructor for details) - */ - void setTranslationErrorTranslating(float percent); - - /** - * Computes and sets the new value for m_Alpha4. - * @param mPerDegree Translation error while rotating (see class constructor for details) - */ - void setTranslationErrorRotating(float mPerDegree); - - /** - * Computes and sets the new value for m_Alpha5. - * @param mPerDegree Move jitter while turning (see class constructor for details) - */ - void setMoveJitterWhileTurning(float mPerDegree); - - /** - * Sets a new minimal size of a cluster of scan points which is considered in scan matching. - * @param clusterSize Minimal size of a cluster in mm of scan points which is considered in scan matching. - */ - void setScanMatchingClusterSize(float clusterSize); - - /** - * Sets whether the map is updated or just used for self-localization. - * @param doMapping True if robot shall do mapping, false otherwise. - */ - void setMapping(bool doMapping); - - /** - * Deletes the current occupancy map and copies a new one into the system. - * @param occupancyMap The occupancy map to load into the system (copies are being made) - */ - void setOccupancyMap(OccupancyMap* occupancyMap); - - /** - * Sets the robot pose in the current occupancy map. - * @param Robot pose. - * @param scatterVariance if not equal to 0 the poses are equally scattered around the pose - */ - void setRobotPose(Pose pose, double scatterVarXY=0.0, double scatterVarTheta=0.0); - - /** - *Returns the best SlamFilter - */ - SlamFilter* getBestSlamFilter(); - - void resetHigh(); - - /** - * Factor (default 0.98) of the contrast of the best particle. - * If the contrast of the worst particle is below this threshold - * it will be replaced by the best particle - * @param deletionThreshold see above - */ - void setDeletionThreshold(double deletionThreshold); - - /** - * applies masking to map of slam filter set in GUI - * @param msg masking message received from GUI - */ - void applyMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg) - { - for(unsigned i = 0; i < m_ParticleFilterNum; ++i) - { - m_SlamFilters[i]->applyMasking(msg); - } - } - - private: - - /** Used SlamFilters */ - std::vector <SlamFilter*> m_SlamFilters; - - /** Number of SlamFilters */ - unsigned m_ParticleFilterNum; - - /** Number of Particles of SlamFilter */ - unsigned m_ParticleNum; - - /** */ - double m_DeletionThreshold; - - /** Best SLAM Filter */ - SlamFilter* m_BestSlamFilter; - - /** Worst SlamFilter */ - SlamFilter* m_WorstSlamFilter; - - bool m_DoMapping; - -}; -#endif - diff --git a/homer_mapping/src/ParticleFilter/Particle.cpp b/homer_mapping/src/ParticleFilter/Particle.cpp deleted file mode 100644 index bce3b5b1..00000000 --- a/homer_mapping/src/ParticleFilter/Particle.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "Particle.h" - -Particle::Particle(float weight, int id) { - m_Weight = weight; - m_Id = id; -} - -Particle::~Particle() { -} - diff --git a/homer_mapping/src/ParticleFilter/Particle.h b/homer_mapping/src/ParticleFilter/Particle.h deleted file mode 100644 index bd96aa85..00000000 --- a/homer_mapping/src/ParticleFilter/Particle.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PARTICLE_H -#define PARTICLE_H - -#include <iostream> -#include <fstream> - -/** - * @class Particle - * - * @author Malte Knauf, Stephan Wirth - * - * @brief This class is an implementation of a "particle". - * - * A particle as it is used in particle filters is a set of one state and one importance factor (=weight). - * A set of Particles is a discrete representation of a probability distribution. - * - * @see ParticleFilter - */ -class Particle { - - public: - /** - * This constructor assigns the given weight to the member m_Weight. - * @param weight The weight of the particle. - */ - Particle(float weight = 0.0, int id = 0); - - /** - * The destructor does nothing so far. - */ - virtual ~Particle(); - - /** - * This method returns the importance factor of the particle. - * @return The importance factor (=weight) of the particle. - */ - inline float getWeight() const { return m_Weight; } - - /** - * Method to set the weight of the particle. - * @param newWeight New weight for the particle. - */ - inline void setWeight(float newWeight) { m_Weight=newWeight; } - - /** - * @return id of the particle that is stored in m_Id - */ - inline int getId() { return m_Id; } - - private: - /** - * Stores the importance factor (=weight) of the particle. This should be a value between 0 and 1. - */ - float m_Weight; - - /** - * Stores the id of the particle (for testing purpose) - */ - int m_Id; - -}; - -#endif - diff --git a/homer_mapping/src/ParticleFilter/ParticleFilter.h b/homer_mapping/src/ParticleFilter/ParticleFilter.h deleted file mode 100644 index fa6a7f99..00000000 --- a/homer_mapping/src/ParticleFilter/ParticleFilter.h +++ /dev/null @@ -1,310 +0,0 @@ -#ifndef PARTICLEFILTER_H -#define PARTICLEFILTER_H - -#include <iostream> -#include <cmath> -#include <limits.h> - -#include <ros/ros.h> - -class Particle; - -const float MIN_EFFECTIVE_PARTICLE_WEIGHT = 0.2; - -/** - * @class ParticleFilter - * - * @author Malte Knauf, Stephan Wirth - * - * @brief This class is a template class for a particle filter. - * - * A particle filter is a descrete method to describe and compute with a probability distribution. - * This template class implements the basic methods for a particle filter: sort() and resample(). - * Use this class do derivate your custom particle filter from it. Use a self-defined subclass of - * Particle as ParticleType. - * - * @see Particle - */ -template <class ParticleType> -class ParticleFilter { - - public: - /** - * The constructor initializes the random number generator and allocates the memory for the particle lists. - * The lists will have particleNum elements. - * @param particleNum Number of particles for the filter. - */ - ParticleFilter<ParticleType>(int particleNum); - - /** - * The destructor releases the particle lists. - */ - virtual ~ParticleFilter(); - - /** - * @return Number of particles used in this filter - */ - int getParticleNum(); - - /** - * @return The number of effective particles (according to "Improving Grid-based SLAM with Rao-Blackwellized Particle - * Filters by Adaptive Proposals and Selective Resampling (2005)" by Giorgio Grisetti, Cyrill Stachniss, Wolfram Burgard - */ - int getEffectiveParticleNum() const; - int getEffectiveParticleNum2() const; - - /** - * @return Pointer to the particle that has the highest weight. - */ - ParticleType* getBestParticle() const; - - - protected: - - /** - * This method generates a random variable in the interval [0,1]. - * @param init The initial value for the static random base number. When running the constructor of this - * class, this method is run once with the C-function time() as parameter to initialize it. - * Then you should use it without parameter. - * @return Random value between 0 and 1 - */ - double random01(unsigned long init = 0) const; - - /** - * This method sorts the particles in m_CurrentList from leftIndex to rightIndex according to their weight. - * The particle with the highest weight is at position 0 after calling this function. The algorithm used here is - * known as quicksort and works recursively. - * @param leftIndex Left index of area to sort - * @param rightIndex Right index of area to sort - */ - void sort(int leftIndex, int rightIndex); - - /** - * This method normalizes the weights of the particles. After calling this function, the sum of the weights of - * all particles in m_CurrentList equals 1.0. - * In this function the sum of all weights of the particles of m_CurrentList is computed and each weight of each - * particle is devided through this sum. - */ - void normalize(); - - /** - * This method selects a new set of particles out of an old set according to their weight - * (importance resampling). The particles from the list m_CurrentList points to are used as source, - * m_LastList points to the destination list. The pointers m_CurrentList and m_LastList are switched. - * The higher the weight of a particle, the more particles are drawn (copied) from this particle. - * The weight remains untouched, because measure() will be called afterwards. - * This method only works on a sorted m_CurrentList, therefore sort() is called first. - */ - void resample(); - - /** - * This method drifts the particles (second step of a filter process). - * Has to be implemented in sub-classes (pure virtual function). - */ - virtual void drift() = 0; - - /** - * This method has to be implemented in sub-classes. It is used to determine the weight of each particle. - */ - virtual void measure() = 0; - - /** - * These two pointers point to m_ParticleListOne and to m_ParticleListTwo. - * The particles are drawn from m_LastList to m_CurrentList to avoid new and delete commands. - * In each run, the pointers are switched in resample(). - */ - ParticleType** m_CurrentList; - ParticleType** m_LastList; - - /** - * Stores the number of particles. - */ - int m_ParticleNum; - - /** - * Stores the number of effective particles. - */ - int m_EffectiveParticleNum; -}; - -template <class ParticleType> -ParticleFilter<ParticleType>::ParticleFilter(int particleNum) { - // initialize particle lists - m_CurrentList = new ParticleType*[particleNum]; - m_LastList = new ParticleType*[particleNum]; - - // initialize random number generator - random01(time(0)); - - m_ParticleNum = particleNum; -} - - -template <class ParticleType> -ParticleFilter<ParticleType>::~ParticleFilter() { - if (m_CurrentList) { - delete[] m_CurrentList; - m_CurrentList = 0; - } - if (m_LastList) { - delete[] m_LastList; - m_LastList = 0; - } -} - -template <class ParticleType> -int ParticleFilter<ParticleType>::getParticleNum() { - return m_ParticleNum; -} - -template <class ParticleType> -double ParticleFilter<ParticleType>::random01(unsigned long init) const { - static unsigned long n; - if (init > 0) { - n = init; - } - n = 1664525 * n + 1013904223; - // create double from unsigned long - return (double)(n/2) / (double)LONG_MAX; -} - - -template <class ParticleType> -void ParticleFilter<ParticleType>::sort(int indexLeft, int indexRight) { - - // SOMETHING LEFT TO SORT? - if (indexLeft >= indexRight) { - // ready! - return; - } - - // CREATE PARTITION - int le = indexLeft; - int ri = indexRight; - int first = le; - int pivot = ri--; - while(le <= ri) { - // skip from left - while(m_CurrentList[le]->getWeight() > m_CurrentList[pivot]->getWeight()) { - le++; - } - // skip from right - while((ri >= first) && (m_CurrentList[ri]->getWeight() <= m_CurrentList[pivot]->getWeight())) { - ri--; - } - // now we have two elements to swap - if(le < ri) { - // swap - ParticleType* temp = m_CurrentList[le]; - m_CurrentList[le] = m_CurrentList[ri]; - m_CurrentList[ri] = temp; - le++; - } - } - - if(le != pivot) { - // swap - ParticleType* temp = m_CurrentList[le]; - m_CurrentList[le] = m_CurrentList[pivot]; - m_CurrentList[pivot] = temp; - } - - // sort left side - sort(indexLeft, le - 1); - // sort right side - sort(le + 1, indexRight); - -} - -template <class ParticleType> -void ParticleFilter<ParticleType>::normalize() { - - float weightSum = 0.0; - for (int i = 0; i < m_ParticleNum; i++) { - weightSum += m_CurrentList[i]->getWeight(); - } - // only normalize if weightSum is big enough to divide - if (weightSum > 0.000001) { - for (int i = 0; i < m_ParticleNum; i++) { - float newWeight = m_CurrentList[i]->getWeight() / weightSum; - m_CurrentList[i]->setWeight(newWeight); - } - } else { - ROS_WARN_STREAM( "Particle weights VERY small: " << weightSum << ". Got "<< m_ParticleNum << " particles."); - } -} - -template <class ParticleType> -void ParticleFilter<ParticleType>::resample() -{ - // swap pointers - ParticleType** help = m_LastList; - m_LastList = m_CurrentList; - m_CurrentList = help; - // now we copy from m_LastList to m_CurrentList - - int drawIndex = 0; - // index of the particle where we are drawing to - int targetIndex = 0; - - int numToDraw = 0; - do { - numToDraw = static_cast<int>(round((m_ParticleNum * m_LastList[drawIndex]->getWeight()) + 0.5)); - for (int i = 0; i < numToDraw; i++) { - *m_CurrentList[targetIndex++] = *m_LastList[drawIndex]; - // don't draw too much - if (targetIndex >= m_ParticleNum) { - break; - } - } - drawIndex++; - } while (numToDraw > 0 && targetIndex < m_ParticleNum); - - // fill the rest of the particle list - for (int i = targetIndex; i < m_ParticleNum; i++) { - float particlePos = random01(); - float weightSum = 0.0; - drawIndex = 0; - weightSum += m_LastList[drawIndex]->getWeight(); - while (weightSum < particlePos) { - weightSum += m_LastList[++drawIndex]->getWeight(); - } - *m_CurrentList[i] = *m_LastList[drawIndex]; - } -} - - -template <class ParticleType> -int ParticleFilter<ParticleType>::getEffectiveParticleNum() const { - // does not work with normalized particle weights - // does not work with our weights at all (algorithm of Grisetti) - float squareSum = 0; - for (int i = 0; i < m_ParticleNum; i++) { - float weight = m_CurrentList[i]->getWeight(); - squareSum += weight * weight; - } - return static_cast<int>(1.0f / squareSum); -} - - -template <class ParticleType> -int ParticleFilter<ParticleType>::getEffectiveParticleNum2() const { - // does not work with normalized particle weights - int effectiveParticleNum = 0; - for (int i = 0; i < m_ParticleNum; i++) { - if (m_CurrentList[i]->getWeight() > MIN_EFFECTIVE_PARTICLE_WEIGHT) { - effectiveParticleNum ++; - } - } - return effectiveParticleNum; -} - - -template <class ParticleType> -ParticleType* ParticleFilter<ParticleType>::getBestParticle() const { - return m_CurrentList[0]; -} - - -#endif - diff --git a/homer_mapping/src/ParticleFilter/SlamFilter.cpp b/homer_mapping/src/ParticleFilter/SlamFilter.cpp deleted file mode 100644 index 2ebdbd16..00000000 --- a/homer_mapping/src/ParticleFilter/SlamFilter.cpp +++ /dev/null @@ -1,653 +0,0 @@ -#include "SlamFilter.h" - -#include "Math/Transformation2D.h" -#include "Math/Math.h" - -#include "tools/loadRosConfig.h" - -#include "tf/transform_broadcaster.h" - -#include <vector> -#include <cmath> -#include <fstream> -#include <sstream> - -#include "ros/ros.h" - -// minimum move for translation in m -const float MIN_MOVE_DISTANCE2 = 0.02 * 0.02; -// minimum turn in radiants -const float MIN_TURN_DISTANCE2 = 0.1 * 0.1; - -const float M_2PI = 2 * M_PI; - -SlamFilter::SlamFilter ( int particleNum ) : ParticleFilter<SlamParticle> ( particleNum ) -{ - - m_OccupancyMap = new OccupancyMap(); - // generate initial particles - for ( int i = 0; i < m_ParticleNum; i++ ) - { - m_CurrentList[i] = new SlamParticle(); - m_LastList[i] = new SlamParticle(); - } - - float rotationErrorRotating = 0.0; - loadConfigValue("/particlefilter/error_values/rotation_error_rotating", rotationErrorRotating); - float rotationErrorTranslating = 0.0; - loadConfigValue("/particlefilter/error_values/rotation_error_translating", rotationErrorTranslating); - float translationErrorTranslating = 0.0; - loadConfigValue("/particlefilter/error_values/translation_error_translating", translationErrorTranslating); - float translationErrorRotating = 0.0; - loadConfigValue("/particlefilter/error_values/translation_error_translating", translationErrorRotating); - float moveJitterWhileTurning = 0.0; - loadConfigValue("/particlefilter/error_values/move_jitter_while_turning", moveJitterWhileTurning); - loadConfigValue("/particlefilter/max_rotation_per_second", m_MaxRotationPerSecond); - - int updateMinMoveAngleDegrees; - loadConfigValue("/particlefilter/update_min_move_angle", updateMinMoveAngleDegrees); - m_UpdateMinMoveAngle = Math::deg2Rad(updateMinMoveAngleDegrees); - loadConfigValue("/particlefilter/update_min_move_dist", m_UpdateMinMoveDistance); - double maxUpdateInterval; - loadConfigValue("/particlefilter/max_update_interval", maxUpdateInterval); - m_MaxUpdateInterval = ros::Duration(maxUpdateInterval); - - setRotationErrorRotating ( rotationErrorRotating ); - setRotationErrorTranslating ( rotationErrorTranslating ); - setTranslationErrorTranslating ( translationErrorTranslating ); - setTranslationErrorRotating ( translationErrorRotating ); - setMoveJitterWhileTurning ( moveJitterWhileTurning ); - - m_FirstRun = true; - m_DoMapping = true; - - m_EffectiveParticleNum = m_ParticleNum; - - m_LastUpdateTime = ros::Time(0); -} - -SlamFilter::SlamFilter ( SlamFilter& slamFilter ) : ParticleFilter<SlamParticle> ( slamFilter.m_ParticleNum ) -{ - m_OccupancyMap = new OccupancyMap ( * ( slamFilter.m_OccupancyMap ) ); - // generate initial particles - for ( int i = 0; i < m_ParticleNum; i++ ) - { - if ( slamFilter.m_CurrentList[i] == 0 ) - { - m_CurrentList[i]=0; - } - else - { - m_CurrentList[i] = new SlamParticle ( * ( slamFilter.m_CurrentList[i] ) ); - } - if ( slamFilter.m_LastList[i] == 0 ) - { - m_LastList[i]=0; - } - else - { - m_LastList[i] = new SlamParticle ( * ( slamFilter.m_LastList[i] ) ); - } - } - - float rotationErrorRotating = 0.0; - loadConfigValue("/particlefilter/error_values/rotation_error_rotating", rotationErrorRotating); - float rotationErrorTranslating = 0.0; - loadConfigValue("/particlefilter/error_values/rotation_error_translating", rotationErrorTranslating); - float translationErrorTranslating = 0.0; - loadConfigValue("/particlefilter/error_values/translation_error_translating", translationErrorTranslating); - float translationErrorRotating = 0.0; - loadConfigValue("/particlefilter/error_values/translation_error_translating", translationErrorRotating); - float moveJitterWhileTurning = 0.0; - loadConfigValue("/particlefilter/error_values/move_jitter_while_turning", moveJitterWhileTurning); - loadConfigValue("/particlefilter/max_rotation_per_second", m_MaxRotationPerSecond); - - int updateMinMoveAngleDegrees; - loadConfigValue("/particlefilter/update_min_move_angle", updateMinMoveAngleDegrees); - m_UpdateMinMoveAngle = Math::deg2Rad(updateMinMoveAngleDegrees); - loadConfigValue("/particlefilter/update_min_move_dist", m_UpdateMinMoveDistance); - double maxUpdateInterval; - loadConfigValue("/particlefilter/max_update_interval", maxUpdateInterval); - m_MaxUpdateInterval = ros::Duration(maxUpdateInterval); - - setRotationErrorRotating ( rotationErrorRotating ); - setRotationErrorTranslating ( rotationErrorTranslating ); - setTranslationErrorTranslating ( translationErrorTranslating ); - setTranslationErrorRotating ( translationErrorRotating ); - setMoveJitterWhileTurning ( moveJitterWhileTurning ); - - m_FirstRun = slamFilter.m_FirstRun; - m_DoMapping = slamFilter.m_DoMapping; - - m_EffectiveParticleNum = slamFilter.m_EffectiveParticleNum; - - m_LastUpdateTime = slamFilter.m_LastUpdateTime; - - m_ReferencePoseOdometry = slamFilter.m_ReferencePoseOdometry; - m_ReferenceMeasurementTime = slamFilter.m_ReferenceMeasurementTime; -} - - -SlamFilter::~SlamFilter() -{ - if ( m_OccupancyMap ) - { - delete m_OccupancyMap; - } - for ( int i = 0; i < m_ParticleNum; i++ ) - { - if ( m_CurrentList[i] ) - { - delete m_CurrentList[i]; - m_CurrentList[i] = 0; - } - if ( m_LastList[i] ) - { - delete m_LastList[i]; - m_LastList[i] = 0; - } - } -} - - -void SlamFilter::setRotationErrorRotating ( float percent ) -{ - m_Alpha1 = percent / 100.0; -} - -void SlamFilter::resetHigh() -{ - m_OccupancyMap->resetHighSensitive(); -} - -void SlamFilter::setRotationErrorTranslating ( float degreePerMeter ) -{ - m_Alpha2 = degreePerMeter / 180.0 * M_PI; -} - -void SlamFilter::setTranslationErrorTranslating ( float percent ) -{ - m_Alpha3 = percent / 100.0; -} - -void SlamFilter::setTranslationErrorRotating ( float mPerDegree ) -{ - m_Alpha4 = mPerDegree / 180.0 * M_PI; -} - -void SlamFilter::setMoveJitterWhileTurning ( float mPerDegree ) -{ - m_Alpha5 = mPerDegree / 180.0 * M_PI; -} - -void SlamFilter::setScanMatchingClusterSize ( float minClusterSize ) -{ - minClusterSize = minClusterSize; -} - -void SlamFilter::setMapping ( bool doMapping ) -{ - m_DoMapping = doMapping; -} - -void SlamFilter:: setOccupancyMap ( OccupancyMap* occupancyMap ) -{ - //delete old - if ( m_OccupancyMap ) - { - delete m_OccupancyMap; - } - //copy - m_OccupancyMap = occupancyMap; -} - - -vector<Pose>* SlamFilter::getParticlePoses() const -{ - vector<Pose>* particlePoses = new vector<Pose>(); - for ( int i = 0; i < m_ParticleNum; i++ ) - { - float robotX, robotY, robotTheta; - SlamParticle* particle = m_CurrentList[i]; - particle->getRobotPose ( robotX, robotY, robotTheta ); - particlePoses->push_back ( Pose ( robotX, robotY, robotTheta ) ); - } - return particlePoses; -} - -vector<SlamParticle*>* SlamFilter::getParticles() const -{ - vector<SlamParticle*>* particles = new vector<SlamParticle*>(); - for ( int i = 0; i < m_ParticleNum; i++ ) - { - - SlamParticle* particle = m_CurrentList[i]; - particles->push_back ( particle ); - } - return particles; -} - -void SlamFilter::setRobotPose ( Pose pose, double scatterVarXY, double scatterVarTheta ) -{ - // set first particle to exact position - m_CurrentList[0]->setRobotPose ( pose.x(), pose.y(), pose.theta() ); - m_LastList[0]->setRobotPose ( pose.x(), pose.y(), pose.theta() ); - // scatter remaining particles - for ( int i = 1; i < m_ParticleNum; ++i ) - { - const double scatterX = randomGauss() * scatterVarXY; - const double scatterY = randomGauss() * scatterVarXY; - const double scatterTheta = randomGauss() * scatterVarTheta; - - m_CurrentList[i]->setRobotPose ( pose.x()+scatterX, pose.y()+scatterY, pose.theta()+scatterTheta ); - m_LastList[i]->setRobotPose ( pose.x()+scatterX, pose.y()+scatterY, pose.theta()+scatterTheta ); - } -} - -vector<float> SlamFilter::getParticleWeights() const -{ - vector<float> particleWeights ( m_ParticleNum ); - for ( int i = 0; i < m_ParticleNum; i++ ) - { - particleWeights[i] = m_CurrentList[i]->getWeight(); - } - return particleWeights; -} - -double SlamFilter::randomGauss ( float variance ) const -{ - if ( variance < 0 ) - { - variance = -variance; - } - double x1, x2, w, y1; - do - { - x1 = 2.0 * random01() - 1.0; - x2 = 2.0 * random01() - 1.0; - w = x1 * x1 + x2 * x2; - } - while ( w >= 1.0 ); - - w = sqrt ( ( -2.0 * log ( w ) ) / w ); - y1 = x1 * w; - // now y1 is uniformly distributed - return sqrt ( variance ) * y1; -} - -vector<float> SlamFilter::filterOutliers (sensor_msgs::LaserScanConstPtr rawData, float maxDiff ) -{ - if ( rawData->ranges.size() < 2 ) - { - return rawData->ranges; - } - vector<float> filteredData = rawData->ranges; - for ( unsigned int i = 1; i < filteredData.size() - 1; i++ ) - { - if ( abs ( ( float ) ( rawData->ranges[i-1] - rawData->ranges[i]*2 + rawData->ranges[i+1] ) ) > maxDiff*2 ) - { - filteredData[i] = 0; - } - } - if ( fabs ( rawData->ranges[0] - rawData->ranges[1] ) > maxDiff ) - { - filteredData[0] = 0; - } - if ( fabs ( rawData->ranges[ rawData->ranges.size()-1 ] - rawData->ranges[ rawData->ranges.size()-2 ] ) > maxDiff ) - { - filteredData[ rawData->ranges.size()-1 ] = 0; - } - - return filteredData; -} - -void SlamFilter::filter (Pose currentPose, sensor_msgs::LaserScanConstPtr laserData, ros::Time measurementTime, ros::Duration &FilterDuration) -{ - // if first run, initialize data - if ( m_FirstRun ) - { - m_FirstRun = false; - // only do mapping, save first pose as reference - if ( m_DoMapping ) - { - m_OccupancyMap->insertLaserData ( laserData ); - } - m_CurrentLaserData = m_CurrentLaserData = boost::make_shared<sensor_msgs::LaserScan>(*laserData); //copy const ptr to be able to change values; //test - m_ReferencePoseOdometry = currentPose; - m_ReferenceMeasurementTime = measurementTime; - - measure(); - ROS_INFO_STREAM("first run!"); - normalize(); - sort ( 0, m_ParticleNum - 1 ); - - return; - } - - //m_CurrentLaserConfig = laserConf; - m_CurrentPoseOdometry = currentPose; - m_CurrentLaserData = boost::make_shared<sensor_msgs::LaserScan>(*laserData); //copy const ptr to be able to change values - m_CurrentLaserData->ranges = filterOutliers ( laserData, 0.3 ); - - Transformation2D trans = m_CurrentPoseOdometry - m_ReferencePoseOdometry; - - // do not resample if move to small - if ( sqr ( trans.x() ) + sqr ( trans.y() ) < MIN_MOVE_DISTANCE2 && sqr ( trans.theta() ) < MIN_TURN_DISTANCE2 ) - { - ROS_DEBUG_STREAM( "Move too small, will not resample." ); - if ( m_EffectiveParticleNum < m_ParticleNum / 5 ) - { - resample(); - ROS_INFO_STREAM( "Particles too scattered, resampling." ); - } - } - else - { - resample(); - } - - // filter steps - drift(); - measure(); - normalize(); - - sort ( 0, m_ParticleNum - 1 ); - - // mapping step - trans = m_CurrentPoseOdometry - m_ReferencePoseOdometry; - double elapsedSeconds = ( measurementTime - m_ReferenceMeasurementTime ).toSec(); - double thetaPerSecond; - if(elapsedSeconds == 0.0) - thetaPerSecond = trans.theta(); - else - thetaPerSecond = trans.theta() / elapsedSeconds; - - Pose likeliestPose = getLikeliestPose(); - Transformation2D transSinceLastUpdate = likeliestPose - m_LastUpdatePose; - - ostringstream stream; - stream.precision ( 2 ); - stream << "Transformation since last update: angle=" << Math::rad2Deg ( transSinceLastUpdate.theta() ) << " dist=" << transSinceLastUpdate.magnitude() << "m" << endl; - - bool update = ( fabs ( transSinceLastUpdate.theta() ) > m_UpdateMinMoveAngle ) || - ( transSinceLastUpdate.magnitude() > m_UpdateMinMoveDistance ) || - ( ( measurementTime - m_LastUpdateTime ) > m_MaxUpdateInterval ); - - if ( m_DoMapping && update ) - { - stream << "Updating map."; - m_LastUpdatePose = likeliestPose; - m_LastUpdateTime = measurementTime; - if ( thetaPerSecond < m_MaxRotationPerSecond ) - { - updateMap(); - } - else - { - ROS_INFO_STREAM( "No mapping performed, rotation angle too big." ); - } - } - else - { - stream << "No map update performed."; - } - ROS_DEBUG_STREAM( stream.str() ); - // safe last used pose and laserdata as reference - m_ReferencePoseOdometry = m_CurrentPoseOdometry; - m_ReferenceMeasurementTime = measurementTime; -} - -/** - * For the probabilistic motion model of the robot we use the following three parameters: - * - When the robot starts, the initial orientation may have errors (a few degrees). (m_InitialOrientationError) - * - The distance of the robot movement may be wrong (a percentage of the moved distance). (m_TranslationError) - * - The orientation of the robot when the motion was finished may be wrong (a percentage of the rotation) (m_RotationError). - * [cf. "An Efficient FastSLAM Algorithm for Generating Maps of Large-Scale Cyclic Environments - * from Raw Laser Range Measurements", Dirk Haenelt et. al.] - * We use Gaussian-Distributions to estimate the error. - * The expected value of the errors are zero. - */ - -void SlamFilter::drift() -{ - - float rx = m_ReferencePoseOdometry.x(); - float ry = m_ReferencePoseOdometry.y(); - float rt = m_ReferencePoseOdometry.theta(); - float cx = m_CurrentPoseOdometry.x(); - float cy = m_CurrentPoseOdometry.y(); - float ct = m_CurrentPoseOdometry.theta(); - - Transformation2D odoTrans = m_CurrentPoseOdometry - m_ReferencePoseOdometry; - - // find out if driving forward or backward - bool backwardMove = false; - float scalar = odoTrans.x() * cosf ( rt ) + odoTrans.y() * sinf ( rt ); - if ( scalar <= 0 ) - { - backwardMove = true; - } - float distance = sqrt ( sqr ( odoTrans.x() ) + sqr ( odoTrans.y() ) ); - float deltaRot1, deltaTrans, deltaRot2; - if ( distance < sqrt ( MIN_MOVE_DISTANCE2 ) ) - { - deltaRot1 = odoTrans.theta(); - deltaTrans = 0.0; - deltaRot2 = 0.0; - } - else if ( backwardMove ) - { - deltaRot1 = atan2 ( ry - cy, rx - cx ) - rt; - deltaTrans = - distance; - deltaRot2 = ct - rt - deltaRot1; - } - else - { - deltaRot1 = atan2 ( odoTrans.y(), odoTrans.x() ) - rt; - deltaTrans = distance; - deltaRot2 = ct - rt - deltaRot1; - } - - while ( deltaRot1 >= M_PI ) deltaRot1 -= M_2PI; - while ( deltaRot1 < -M_PI ) deltaRot1 += M_2PI; - while ( deltaRot2 >= M_PI ) deltaRot2 -= M_2PI; - while ( deltaRot2 < -M_PI ) deltaRot2 += M_2PI; - - // always leave one particle with pure displacement - SlamParticle* particle = m_CurrentList[0]; - // get stored pose - float robotX, robotY, robotTheta; - particle->getRobotPose ( robotX, robotY, robotTheta ); - Pose pose ( robotX, robotY, robotTheta ); - // move pose - float posX = pose.x() + deltaTrans * cos ( pose.theta() + deltaRot1 ); - float posY = pose.y() + deltaTrans * sin ( pose.theta() + deltaRot1 ); - float theta = pose.theta() + deltaRot1 + deltaRot2; - while ( theta > M_PI ) theta -= M_2PI; - while ( theta <= -M_PI ) theta += M_2PI; - // save new pose - particle->setRobotPose ( posX, posY, theta ); - for ( int i = 1; i < m_ParticleNum; i++ ) - { - SlamParticle* particle = m_CurrentList[i]; - // get stored pose - float robotX, robotY, robotTheta; - particle->getRobotPose ( robotX, robotY, robotTheta ); - Pose pose ( robotX, robotY, robotTheta ); - // move pose - float estDeltaRot1 = deltaRot1 - randomGauss ( m_Alpha1 * fabs ( deltaRot1 ) + m_Alpha2 * deltaTrans ); - float estDeltaTrans = deltaTrans - randomGauss ( m_Alpha3 * deltaTrans + m_Alpha4 * ( fabs ( deltaRot1 ) + fabs ( deltaRot2 ) ) ); - float estDeltaRot2 = deltaRot2 - randomGauss ( m_Alpha1 * fabs ( deltaRot2 ) + m_Alpha2 * deltaTrans ); - - float posX = pose.x() + estDeltaTrans * cos ( pose.theta() + estDeltaRot1 ) + randomGauss ( m_Alpha5 * fabs ( estDeltaRot1 + estDeltaRot2 ) ); - float posY = pose.y() + estDeltaTrans * sin ( pose.theta() + estDeltaRot1 ) + randomGauss ( m_Alpha5 * fabs ( estDeltaRot1 + estDeltaRot2 ) ); - float theta = pose.theta() + estDeltaRot1 + estDeltaRot2; - - // save new pose - while ( theta > M_PI ) theta -= M_2PI; - while ( theta <= -M_PI ) theta += M_2PI; - - particle->setRobotPose ( posX, posY, theta ); - } -} - - -void SlamFilter::measure() -{ - if ( m_OccupancyMap ) - { - m_MeasurePoints = m_OccupancyMap->getMeasurePoints ( m_CurrentLaserData ); - - for ( int i = 0; i < m_ParticleNum; i++ ) - { - SlamParticle* particle = m_CurrentList[i]; - if ( !particle ) - { - ROS_ERROR_STREAM("ERROR: Particle is NULL-pointer!"); - } - else - { - // calculate weights - float robotX, robotY, robotTheta; - particle->getRobotPose ( robotX, robotY, robotTheta ); - Pose pose ( robotX, robotY, robotTheta ); - float weight = m_OccupancyMap->computeScore ( pose, m_MeasurePoints ); - particle->setWeight ( weight ); - } - } - } - m_EffectiveParticleNum = getEffectiveParticleNum2(); - -} - -void SlamFilter::updateMap() -{ - getLikeliestPose(); //call to trigger tf broadcast - m_OccupancyMap->insertLaserData ( m_CurrentLaserData ); -} - -void SlamFilter::printParticles() const -{ - cout << endl << "### PARTICLE LIST ###" << endl; - cout << right << fixed; - cout.width ( 5 ); - for ( int i = 0; i < m_ParticleNum; i++ ) - { - SlamParticle* p_particle = m_CurrentList[i]; - if ( p_particle ) - { - float robotX, robotY, robotTheta; - p_particle->getRobotPose ( robotX, robotY, robotTheta ); - cout << "Particle " << i << ": (" << robotX << "," << robotY << "," << robotTheta * 180.0 / M_PI << "), weight:\t" << p_particle->getWeight() << endl; - } - } - cout << "### END OF LIST ###" << endl; -} - - -void SlamFilter::reduceParticleNumber ( int newParticleNum ) -{ - if ( newParticleNum < m_ParticleNum ) - { - - SlamParticle** newCurrentList = new SlamParticle*[newParticleNum]; - SlamParticle** newLastList = new SlamParticle*[newParticleNum]; - - for ( int i = 0; i < newParticleNum; i++ ) - { - newCurrentList[i] = m_CurrentList[i]; - newLastList[i] = m_LastList[i]; - } - - for ( int i = newParticleNum + 1; i < m_ParticleNum; i++ ) - { - delete m_CurrentList[i]; - delete m_LastList[i]; - } - delete[] m_CurrentList; - delete[] m_LastList; - - m_CurrentList = newCurrentList; - m_LastList = newLastList; - - m_ParticleNum = newParticleNum; - normalize(); - } -} - -Pose SlamFilter::getLikeliestPose() const -{ - float percentage = 3; - int numParticles = static_cast<int> ( percentage / 100 * m_ParticleNum ); - if ( 0 == numParticles ) numParticles = 1; - float sumX = 0, sumY = 0, sumDirX = 0, sumDirY = 0; - for ( int i = 0; i < numParticles; i++ ) - { - float robotX, robotY, robotTheta; - SlamParticle* particle = m_CurrentList[i]; - particle->getRobotPose ( robotX, robotY, robotTheta ); - sumX += robotX; - sumY += robotY; - // calculate sum of vectors in unit circle - sumDirX += cos ( robotTheta ); - sumDirY += sin ( robotTheta ); - } - float meanTheta = atan2 ( sumDirY, sumDirX ); - //broadcast transform map -> base_link - tf::Transform transform(tf::createQuaternionFromYaw(meanTheta), - tf::Vector3(sumX / numParticles, sumY / numParticles, 0.0)); - tf::TransformBroadcaster tfBroadcaster; - tfBroadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "map", "base_link")); - return Pose ( sumX / numParticles, sumY / numParticles, meanTheta ); -} - -OccupancyMap* SlamFilter::getLikeliestMap() const -{ - return m_OccupancyMap; -} - -void SlamFilter::getPoseVariances ( int particleNum, float& poseVarianceX, float& poseVarianceY ) -{ - - // the particles of m_CurrentList are sorted by their weights - if ( particleNum > m_ParticleNum || particleNum <= 0 ) - { - particleNum = m_ParticleNum; - } - // calculate average pose - float averagePoseX = 0; - float averagePoseY = 0; - float robotX = 0.0; - float robotY = 0.0; - float robotTheta = 0.0; - for ( int i = 0; i < particleNum; i++ ) - { - m_CurrentList[i]->getRobotPose ( robotX, robotY, robotTheta ); - averagePoseX += robotX; - averagePoseY += robotY; - } - averagePoseX /= particleNum; - averagePoseY /= particleNum; - - // calculate standard deviation of pose - poseVarianceX = 0.0; - poseVarianceY = 0.0; - for ( int i = 0; i < particleNum; i++ ) - { - m_CurrentList[i]->getRobotPose ( robotX, robotY, robotTheta ); - poseVarianceX += ( averagePoseX - robotX ) * ( averagePoseX - robotX ); - poseVarianceY += ( averagePoseY - robotY ) * ( averagePoseY - robotY ); - } - poseVarianceX /= particleNum; - poseVarianceY /= particleNum; -} - -double SlamFilter::evaluateByContrast() -{ - return m_OccupancyMap->evaluateByContrast(); -} - -void SlamFilter::applyMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg) -{ - m_OccupancyMap->applyMasking(msg); -} diff --git a/homer_mapping/src/ParticleFilter/SlamFilter.h b/homer_mapping/src/ParticleFilter/SlamFilter.h deleted file mode 100644 index f8d96901..00000000 --- a/homer_mapping/src/ParticleFilter/SlamFilter.h +++ /dev/null @@ -1,314 +0,0 @@ -#ifndef SLAMFILTER_H -#define SLAMFILTER_H - -#include <vector> -#include "ParticleFilter.h" -#include "SlamParticle.h" -#include "Math/Pose.h" -#include "../OccupancyMap/OccupancyMap.h" - -#include "sensor_msgs/LaserScan.h" - -class OccupancyMap; - -/** - * @class SlamFilter - * - * @author Malte Knauf, Stephan Wirth, Susanne Maur - * - * @brief This class is used to determine the robot's most likely pose with given map and given laser data. - * - * A particle filter is a descrete method to describe and compute with a probability distribution. - * This particle filter uses an occupancy map to determine the probability of robot states. - * The robot states are stored in a particle together with their weight @see SlamParticle. - * - * @see SlamParticle - * @see ParticleFilter - * @see OccupancyMap - */ -class SlamFilter : public ParticleFilter<SlamParticle> { - - public: - - /** - * This constructor initializes the random number generator and sets the member variables to the given values. - * @param particleNum Number of particles to use. - */ - SlamFilter(int particleNum); - - /// @brief copy constructor - SlamFilter( SlamFilter& slamFilter ); - - /** - * The destructor releases the OccupancyMap and the particles. - */ - ~SlamFilter(); - - /** - * This method runs the filter routine. - * The given odometry measurement is used as movement hypothesis, the laserData-vector is used - * as measurement and is used to weight the particles. - * @param currentPoseOdometry Odometry data of time t. - * @param laserData msg containing the laser measurement. - * @param measurementTime Time stamp of the measurement. - * @param filterDurationTime Returns the time that the filtering needed - */ - void filter(Pose currentPoseOdometry, sensor_msgs::LaserScanConstPtr laserData, ros::Time measurementTime, - ros::Duration &filterDuration); - - /** - * @return The Pose of the most important particle (particle with highest weight). - */ - Pose getLikeliestPose() const; - - /** - * This method can be used to retrieve the most likely map that is stored by the particle filter. - * @return Pointer to the most likely occupancy map. - */ - OccupancyMap* getLikeliestMap() const; - - /** - * This function prints out the list of particles to stdout via cout. - */ - void printParticles() const; - - void resetHigh(); - - /** - * Computes and sets the new value for m_Alpha1. - * @param percent Rotation error while rotating (see class constructor for details) - */ - void setRotationErrorRotating(float percent); - - /** - * Computes and sets the new value for m_Alpha2. - * @param degreesPerMeter Rotation error while translating (see class constructor for details) - */ - void setRotationErrorTranslating(float degreesPerMeter); - - /** - * Computes and sets the new value for m_Alpha3. - * @param percent Translation error while translating (see class constructor for details) - */ - void setTranslationErrorTranslating(float percent); - - /** - * Computes and sets the new value for m_Alpha4. - * @param mPerDegree Translation error while rotating (see class constructor for details) - */ - void setTranslationErrorRotating(float mPerDegree); - - /** - * Computes and sets the new value for m_Alpha5. - * @param mPerDegree Move jitter while turning (see class constructor for details) - */ - void setMoveJitterWhileTurning(float mPerDegree); - - /** - * Sets a new minimal size of a cluster of scan points which is considered in scan matching. - * @param clusterSize Minimal size of a cluster in mm of scan points which is considered in scan matching. - */ - void setScanMatchingClusterSize(float clusterSize); - - /** - * Sets whether the map is updated or just used for self-localization. - * @param doMapping True if robot shall do mapping, false otherwise. - */ - void setMapping(bool doMapping); - - /** - * Deletes the current occupancy map and copies a new one into the system. - * @param occupancyMap The occupancy map to load into the system (is being copied) - */ - void setOccupancyMap(OccupancyMap* occupancyMap); - - /** - * Sets the robot pose in the current occupancy map. - * @param Robot pose. - * @param scatterVariance if not equal to 0 the poses are equally scattered around the pose - */ - void setRobotPose(Pose pose, double scatterVarXY=0.0, double scatterVarTheta=0.0); - - /** - * @return Vector of current particle poses. The vector is sorted according to the weights of the - * particles. The pose of the particle with the highest value is the first element of the vector. - */ - std::vector<Pose>* getParticlePoses() const; - - /** - * @return vector of all particles - */ - std::vector<SlamParticle*>* getParticles() const; - - /** - * @return Vector of current particle weights. The vector is sorted by weight, highest weight first. - */ - std::vector<float> getParticleWeights() const; - - /** - * Calculates and returns the variance of the current likeliest particle poses. - * The orientation of the particle is neglected. - * @param The number of treated particles. - * @param[out] poseVarianceX The variance of particle poses in x direction. - * @param[out] poseVarianceY The variance of particle poses in y direction. - */ - void getPoseVariances(int particleNum, float& poseVarianceX, float& poseVarianceY); - - /** - * This method reduces the number of particles used in this SlamFilter to the given value. - * @param newParticleNumber The new number of particles - */ - void reduceParticleNumber(int newParticleNumber); - - /** - * This method returns the contrast of the occupancy grid - * @return Contrast value from 0 (no contrast) to 1 (max. contrast) of the map - */ - double evaluateByContrast(); - - /** - * This method passes a masking map to to the underlying occupancy map - */ - void applyMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg); - - - private: - - /** - * This method filter outliers in the given laser scan - * @param rawData the laser scan to check - * @param maxDiff maximal difference between two adjacent ranges - * @return filtered scan without outliers - */ - vector<float> filterOutliers(sensor_msgs::LaserScanConstPtr rawData, float maxDiff ); - - /** - * This method generates Gauss-distributed random variables with the given variance. The computation - * method is the Polar Method that is described in the book "A First Course on Probability" by Sheldon Ross. - * @param variance The variance for the Gauss-distribution that is used to generate the random variable. - * @return A random variable that is N(0, variance) distributed. - */ - double randomGauss(float variance = 1.0) const; - - /** - * This method drifts the particles according to the last two odometry readings (time t-1 and time t). - */ - void drift(); - - /** - * This method weightens each particle according to the given laser measurement in m_LaserData. - */ - void measure(); - - /** - * This method updates the map by inserting the current laser measurement at the pose of the likeliest particle. - */ - void updateMap(); - - /** - * For weightening the particles, the filter needs a map. - * This variable holds a pointer to a map. - * @see OccupancyMap - */ - OccupancyMap* m_OccupancyMap; - - /** - * threshold values for when the map will be updated. - * The map is only updated when the robot has turned a minimal angle (m_UpdateMinMoveAngle in radiants), - * has moved a minimal distance (m_UpdateMinMoveDistance in m) or a maximal time has passed (m_MaxUpdateInterval) - */ - float m_UpdateMinMoveAngle; - float m_UpdateMinMoveDistance; - ros::Duration m_MaxUpdateInterval; - - /** - * This variable holds the rotation error that the robot makes while it is rotating. - * Has to be given in percent. Example: robot makes errors of 3 degrees while making a 60 degrees - * move -> error is 5% -> rotationErrorRotating = 5) - */ - float m_Alpha1; - - /** - * This variable holds the rotation error that the robot makes while it is translating - * (moving forward or backwards). Has to be given in degrees per meter. - */ - float m_Alpha2; - - /** - * This variable holds the translation error that the robot makes while it is translating. - * Has to be given in percent. - */ - float m_Alpha3; - - /** - * This variable holds the translation error that the robot makes while it is rotating. - * This error only carries weight, if a translation es performed at the same time. - * See also m_Alpha5. - * Has to be given in milimeters per degree. Example: Robot makes a turn of 10 degrees and moves its - * center unintentional 15 mm. -> translationErrorRotating = 15.0 / 10.0 = 1.5 - */ - float m_Alpha4; - - /** - * This variable holds a move jitter that is considered if the robot is turning. - * Has to be given in milimeters per degree. - */ - float m_Alpha5; - - /** - * The maximal rotation if mapping is performed. If the rotation is bigger, mapping is interrupted. - * This value may depend on the computing power, because it is influenced by the size of time intervals of mapping. - */ - float m_MaxRotationPerSecond; - - /** - * Last laser data. - */ - sensor_msgs::LaserScanPtr m_CurrentLaserData; - - /** - * Last two odometry measurements. - */ - Pose m_ReferencePoseOdometry; - Pose m_CurrentPoseOdometry; - - /** - * Time stamp of the last sensor measurement. - */ - ros::Time m_ReferenceMeasurementTime; - - /** - * True if it is the first run of SlamFilter, false otherwise. - */ - bool m_FirstRun; - - /** - * This variabe is true, if the SlamFilter is used for mapping and updates the map, - * false if it is just used for self-localization. - */ - bool m_DoMapping; - - /** Points used in last measure() step */ - vector<MeasurePoint> m_MeasurePoints; - - /// Pose of robot during last map update - Pose m_LastUpdatePose; - - /** - * Time stamp of the last particle filter step - */ - ros::Time m_LastUpdateTime; - - /** - * Calculates the square of given input f - * @param f input - * @return square of input - */ - template<class T> - T sqr(T f) - { - return f * f; - } -}; -#endif - diff --git a/homer_mapping/src/ParticleFilter/SlamParticle.cpp b/homer_mapping/src/ParticleFilter/SlamParticle.cpp deleted file mode 100644 index 7b501f0c..00000000 --- a/homer_mapping/src/ParticleFilter/SlamParticle.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "SlamParticle.h" - -SlamParticle::SlamParticle(float weight, float robotX, float robotY, float robotTheta) : Particle(weight) { - m_RobotPositionX = robotX; - m_RobotPositionY = robotY; - m_RobotOrientation = robotTheta; -} - -SlamParticle::SlamParticle( SlamParticle& slamParticle ) -{ - m_RobotPositionX = slamParticle.m_RobotPositionX; - m_RobotPositionY = slamParticle.m_RobotPositionY; - m_RobotOrientation = slamParticle.m_RobotOrientation; -} - -SlamParticle::~SlamParticle() { -} - -void SlamParticle::setRobotPose(float robotX, float robotY, float robotTheta) { - m_RobotPositionX = robotX; - m_RobotPositionY = robotY; - m_RobotOrientation = robotTheta; -} - -void SlamParticle::getRobotPose(float& robotX, float& robotY, float& robotTheta) { - robotX = m_RobotPositionX; - robotY = m_RobotPositionY; - robotTheta = m_RobotOrientation; -} - diff --git a/homer_mapping/src/ParticleFilter/SlamParticle.h b/homer_mapping/src/ParticleFilter/SlamParticle.h deleted file mode 100644 index 71da4a81..00000000 --- a/homer_mapping/src/ParticleFilter/SlamParticle.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef SLAMPARTICLE_H -#define SLAMPARTICLE_H - -#include <iostream> -#include <fstream> - -#include "Particle.h" - -/** - * @class SlamParticle - * - * @author Malte Knauf, Stephan Wirth - * - * @brief This class defines a particle for the SlamFilter. - * - * This particle contains a weight (inherited from base class) and a Pose (position + orientation). - * The Pose describes a possible position and orientation of the robot. - * - * @see SlamFilter - * @see Particle - */ -class SlamParticle : public Particle -{ - - public: - /** - * This constructor assigns the given weight to the member m_Weight. - * @param weight The weight of the particle. - * @param robotX X-Position of the robot (world coordinates in m). - * @param robotY Y-Position of the robot (world coordinates in m). - * @param robotTheta Orientation of the robot (radiants). - */ - SlamParticle ( float weight = 1.0, float robotX = 0.0, float robotY = 0.0, float robotTheta = 0.0 ); - - ///@brief copy contructor - SlamParticle ( SlamParticle& slamParticle ); - - /** - * The destructor does nothing so far. - */ - ~SlamParticle(); - - /** - * Sets the three members m_RobotPositionX, m_RobotPositionY, m_RobotOrientation. - * @param robotX X-Position of the robot (world coordinates in m). - * @param robotY Y-Position of the robot (world coordinates in m). - * @param robotTheta Orientation of the robot (radiants). - */ - void setRobotPose ( float robotX, float robotY, float robotTheta ); - - /** - * Returns the content of the three members m_RobotPositionX, m_RobotPositionY, m_RobotOrientation. - * @param[out] robotX X-Position of the robot (world coordinates in m). - * @param[out] robotY Y-Position of the robot (world coordinates in m). - * @param[out] robotTheta Orientation of the robot (radiants). - */ - void getRobotPose ( float& robotX, float& robotY, float& robotTheta ); - - - private: - - /** - * These members store the pose of the robot. - */ - float m_RobotPositionX; - float m_RobotPositionY; - float m_RobotOrientation; - -}; - -#endif - diff --git a/homer_mapping/src/slam_node.cpp b/homer_mapping/src/slam_node.cpp deleted file mode 100644 index 6d196437..00000000 --- a/homer_mapping/src/slam_node.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include <sstream> -#include <vector> -#include <iostream> -#include <fstream> -#include <sstream> -#include <cmath> -#include <stdlib.h> - -#include "slam_node.h" - -//receive: -#include "sensor_msgs/LaserScan.h" -#include "nav_msgs/Odometry.h" -#include "nav_msgs/OccupancyGrid.h" -#include "tf/tf.h" - -#include "tools/loadRosConfig.h" - -#include "ParticleFilter/SlamFilter.h" -#include "ParticleFilter/HyperSlamFilter.h" -#include "Math/Box2D.h" -#include "OccupancyMap/OccupancyMap.h" - -SlamNode::SlamNode(ros::NodeHandle* nh) - : m_HyperSlamFilter( 0 ) -{ - init(); - - // subscribe to topics - m_LaserScanSubscriber = nh->subscribe("/scan", 1, &SlamNode::callbackLaserScan, this); - m_OdometrySubscriber = nh->subscribe<nav_msgs::Odometry>("/odom", 1, &SlamNode::callbackOdometry, this); - m_UserDefPoseSubscriber = nh->subscribe<geometry_msgs::Pose>("/homer_mapping/userdef_pose", 1, &SlamNode::callbackUserDefPose, this); - m_DoMappingSubscriber = nh->subscribe<std_msgs::Bool>("/homer_mapping/do_mapping", 1, &SlamNode::callbackDoMapping, this); - m_ResetMapSubscriber = nh->subscribe<std_msgs::Empty>("/map_manager/reset_maps", 1, &SlamNode::callbackResetMap, this); - m_LoadMapSubscriber = nh->subscribe<nav_msgs::OccupancyGrid>("/map_manager/loaded_map", 1, &SlamNode::callbackLoadedMap, this); - m_MaskingSubscriber = nh->subscribe<nav_msgs::OccupancyGrid>("/map_manager/mask_slam", 1, &SlamNode::callbackMasking, this); - m_ResetHighSubscriber = nh->subscribe<std_msgs::Empty>("/map_manager/reset_high", 1, &SlamNode::callbackResetHigh, this); - - m_InitialPoseSubscriber = nh->subscribe<geometry_msgs::PoseWithCovarianceStamped>("/initialpose", 1, &SlamNode::callbackInitialPose, this); - - // advertise topics - m_PoseStampedPublisher = nh->advertise<geometry_msgs::PoseStamped>("/pose", 1); - m_SLAMMapPublisher = nh->advertise<nav_msgs::OccupancyGrid>("/homer_mapping/slam_map", 1); -} - -void SlamNode::init() -{ - double waitTime; - loadConfigValue("/particlefilter/wait_time", waitTime); - m_WaitDuration = ros::Duration(waitTime); - loadConfigValue("/selflocalization/scatter_var_xy", m_ScatterVarXY); - loadConfigValue("/selflocalization/scatter_var_theta", m_ScatterVarTheta); - - m_DoMapping = true; - - int particleNum; - loadConfigValue("/particlefilter/particle_num", particleNum); - int particleFilterNum; - loadConfigValue("/particlefilter/hyper_slamfilter/particlefilter_num", particleFilterNum); - m_HyperSlamFilter = new HyperSlamFilter ( particleFilterNum, particleNum ); - - m_ReferenceOdometryTime = ros::Time(0); - m_LaserDataTime = ros::Time(0);; - - m_LastLaserMessageId = 0; - m_LastMapSendTime = ros::Time(0); - m_LastPositionSendTime = ros::Time(0); - m_LastMappingTime = ros::Time(0); -} - -SlamNode::~SlamNode() -{ - delete m_HyperSlamFilter; -} - -void SlamNode::processMeasurements ( ros::Time odoTime, Pose currentOdometryPose ) -{ - // laserscan in between current odometry reading and m_ReferenceOdometry - // -> calculate pose of robot during laser scan - ros::Duration d1 = m_LaserDataTime - m_ReferenceOdometryTime; - ros::Duration d2 = odoTime - m_ReferenceOdometryTime; - - float timeFactor; - if(d1.toSec()==0.0) - timeFactor = 0.0f; - else if(d2.toSec()==0.0) - timeFactor = 1.0f; - else - timeFactor = d1.toSec() / d2.toSec(); - ros::Duration duration = ros::Duration(0); - - Pose interpolatedPose = m_ReferenceOdometryPose.interpolate ( currentOdometryPose, timeFactor ); - m_HyperSlamFilter->filter( interpolatedPose, m_LastLaserData, m_LaserDataTime, duration); -} - -void SlamNode::resetMaps() -{ - ROS_INFO( "Resetting maps.." ); - - delete m_HyperSlamFilter; - m_HyperSlamFilter = 0; - init(); - - sendMapDataMessage(); - sendPositionDataMessage(); -} - -void SlamNode::callbackResetHigh(const std_msgs::Empty::ConstPtr& msg) -{ - m_HyperSlamFilter->resetHigh(); - -} - - -void SlamNode::sendPositionDataMessage() -{ - Pose pose = m_HyperSlamFilter->getBestSlamFilter()->getLikeliestPose(); - - geometry_msgs::PoseStamped poseMsg; - //header - poseMsg.header.stamp = ros::Time::now(); - poseMsg.header.frame_id = "map"; - - //position and orientation - poseMsg.pose.position.x = pose.x(); - poseMsg.pose.position.y = pose.y(); - poseMsg.pose.position.z = 0.0; - tf::Quaternion quatTF = tf::createQuaternionFromYaw(pose.theta()); - geometry_msgs::Quaternion quatMsg; - tf::quaternionTFToMsg(quatTF, quatMsg); //conversion from tf::Quaternion to geometry_msgs::Quaternion - poseMsg.pose.orientation = quatMsg; - m_PoseStampedPublisher.publish(poseMsg); - - //broadcast transform map -> base_link - tf::Transform transform(quatTF, - tf::Vector3(pose.x(), pose.y(), 0.0)); - m_tfBroadcaster.sendTransform(tf::StampedTransform(transform, poseMsg.header.stamp, "map", "base_link")); - m_LastLaserMessageId = 0; -} - -void SlamNode::sendMapDataMessage() -{ - std::vector<int8_t> mapData; - int width, height; - float resolution; - - OccupancyMap* occMap = m_HyperSlamFilter->getBestSlamFilter()->getLikeliestMap(); - occMap->getOccupancyProbabilityImage (mapData, width, height, resolution); - - if ( width != height ) - { - ROS_ERROR_STREAM("ERROR: Map is not quadratic! can not send map!"); - } - else - { - nav_msgs::OccupancyGrid mapMsg; - std_msgs::Header header; - header.stamp = ros::Time::now(); - header.frame_id = "map"; - mapMsg.header = header; - nav_msgs::MapMetaData mapMetaData; - mapMetaData.width = width; - mapMetaData.height = height; - mapMetaData.resolution = resolution; - mapMetaData.origin.position.x = -height*resolution/2; - mapMetaData.origin.position.y = -width*resolution/2; - mapMetaData.origin.orientation.w = 1.0; - mapMetaData.origin.orientation.x = 0.0; - mapMetaData.origin.orientation.y = 0.0; - mapMetaData.origin.orientation.z = 0.0; - mapMsg.info = mapMetaData; - mapMsg.data = mapData; - - m_SLAMMapPublisher.publish(mapMsg); - } -} - -void SlamNode::callbackUserDefPose( const geometry_msgs::Pose::ConstPtr& msg ) -{ - Pose userdef_pose(msg->position.x, msg->position.y, tf::getYaw(msg->orientation)); - m_HyperSlamFilter->setRobotPose( userdef_pose, m_ScatterVarXY, m_ScatterVarTheta ); -} - -void SlamNode::callbackLaserScan(const sensor_msgs::LaserScan::ConstPtr& msg) -{ - m_LaserDataTime = ros::Time::now();//msg->header.stamp; TODO use msg stamp - m_LastLaserData = msg; -} - -void SlamNode::callbackOdometry( const nav_msgs::Odometry::ConstPtr& msg) { - ros::Time currentOdometryTime = ros::Time::now();//msg->header.stamp; TODO use msg stamp once cu2wd node publishes time in odometry msg - - float odoX = msg->pose.pose.position.x; - float odoY = msg->pose.pose.position.y; - geometry_msgs::Quaternion quat = msg->pose.pose.orientation; - float odoTheta = tf::getYaw(quat); - - Pose currentOdometryPose ( odoX, odoY, odoTheta ); - - // check if we have a laserscan in between two odometry readings (or at the same time) - bool mappingPossible = ( currentOdometryTime - m_LastMappingTime > m_WaitDuration ) && - ( !m_ReferenceOdometryTime.isZero()) && - ( m_LaserDataTime >= m_ReferenceOdometryTime ) && - ( currentOdometryTime >= m_LaserDataTime ); - - if ( mappingPossible ) - { - ros::Time startTime = ros::Time::now(); - processMeasurements ( currentOdometryTime, currentOdometryPose ); - ros::Time finishTime = ros::Time::now(); - - // send map max. every 500 ms - if ( (finishTime - m_LastMapSendTime).toSec() > 0.5 ) - { - sendMapDataMessage(); - m_LastMapSendTime = finishTime; - } - sendPositionDataMessage(); - m_LastPositionSendTime=finishTime; - m_LastMappingTime=currentOdometryTime; - - ROS_DEBUG_STREAM( "Pos. data delay: " << (finishTime - startTime).toSec() << "s" ); - ROS_DEBUG_STREAM("Map send Interval: " << ( finishTime - m_LastPositionSendTime ).toSec() << "s" ); - } - m_ReferenceOdometryPose = currentOdometryPose; - m_ReferenceOdometryTime = currentOdometryTime; -} - -void SlamNode::callbackDoMapping(const std_msgs::Bool::ConstPtr &msg) -{ - m_DoMapping = msg->data; - m_HyperSlamFilter->setMapping ( m_DoMapping ); - ROS_INFO_STREAM( "Do mapping is set to " << ( m_DoMapping ) ); -} - -void SlamNode::callbackResetMap(const std_msgs::Empty::ConstPtr &msg) -{ - resetMaps(); -} - -void SlamNode::callbackLoadedMap(const nav_msgs::OccupancyGrid::ConstPtr &msg) -{ - float res = msg->info.resolution; - int height = msg->info.height; // cell size - int width = msg->info.width; //cell size - if(height!=width) { - ROS_ERROR("Height != width in loaded map"); - return; - } - - //convert map vector from ros format to robbie probability array - float* map = new float[msg->data.size()]; - //generate exploredRegion - int minX = INT_MIN; - int minY = INT_MIN; - int maxX = INT_MAX; - int maxY = INT_MAX; - for(size_t y = 0; y < msg->info.height; y++) - { - int yOffset = msg->info.width * y; - for(size_t x = 0; x < msg->info.width; x++) - { - int i = yOffset + x; - if(msg->data[i] == -1 ) - map[i] = 0.5; - else - map[i] = msg->data[i]/100.0; - - if(map[i]!=0.5) { - if(minX==INT_MIN || minX > (int)x) - minX = (int)x; - if(minY==INT_MIN || minY > (int)y) - minY = (int)y; - if(maxX==INT_MAX || maxX < (int)x) - maxX = (int)x; - if(maxY==INT_MAX || maxY < (int)y) - maxY = (int)y; - } - } - } - Box2D<int> exploredRegion = Box2D<int> ( minX, minY, maxX, maxY ); - OccupancyMap* occMap = new OccupancyMap(map, msg->info.origin, res, width, exploredRegion); - m_HyperSlamFilter->setOccupancyMap( occMap ); - m_HyperSlamFilter->setMapping( false ); //is this already done by gui message? - ROS_INFO_STREAM( "Replacing occupancy map" ); -} - - -void SlamNode::callbackInitialPose(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg) -{ - Pose userdef_pose(msg->pose.pose.position.x, msg->pose.pose.position.y, tf::getYaw(msg->pose.pose.orientation)); - m_HyperSlamFilter->setRobotPose( userdef_pose, m_ScatterVarXY, m_ScatterVarTheta ); -} - -void SlamNode::callbackMasking(const nav_msgs::OccupancyGrid::ConstPtr &msg) -{ - m_HyperSlamFilter->applyMasking(msg); -} - -/** - * @brief main function - */ -int main(int argc, char** argv) -{ - ros::init(argc, argv, "homer_mapping"); - ros::NodeHandle nh; - - SlamNode slamNode(&nh); - - ros::Rate loop_rate(12); - while (ros::ok()) - { - ros::spinOnce(); - loop_rate.sleep(); - } - return 0; -} - diff --git a/homer_mapping/src/slam_node.h b/homer_mapping/src/slam_node.h deleted file mode 100644 index 803c5c4b..00000000 --- a/homer_mapping/src/slam_node.h +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef SLAM_NODE_H -#define SLAM_NODE_H - -#include <vector> -#include <map> - -#include "Math/Pose.h" - -#include "tf/transform_broadcaster.h" - -#include "sensor_msgs/LaserScan.h" -#include "nav_msgs/Odometry.h" -#include "nav_msgs/OccupancyGrid.h" -#include "geometry_msgs/Pose.h" -#include "std_msgs/Empty.h" -#include "std_msgs/Bool.h" -#include "geometry_msgs/PoseWithCovarianceStamped.h" - - - - -class OccupancyMap; -class SlamFilter; -class HyperSlamFilter; - -/** - * @class SlamNode - * - * @author Malte Knauf, Stephan Wirth, Susanne Maur (RX), David Gossow (RX), - * Christian Fuchs (R12), Nicolai Wojke (R14), Susanne Thierfelder (R16) - * - * - * @brief The Simultaneous localization and mapping module - * - * This module receives odometry and laser data and computes the - * robot's position and a map out of this data. Then it sends a - * geometry_msgs/PoseStamped and nav_msgs/OccupancyGrid message. - */ -class SlamNode -{ - -public: - - /** - * The constructor adds the message types and prepares the module for receiving them. - */ - SlamNode(ros::NodeHandle *nh); - - /** - * This method initializes the member variables. - */ - virtual void init(); - - /** - * The destructor deletes the filter thread instance. - */ - virtual ~SlamNode(); - -private: - - /** - * Callback methods for all incoming messages - */ - void callbackLaserScan( const sensor_msgs::LaserScan::ConstPtr& msg ); - void callbackOdometry( const nav_msgs::Odometry::ConstPtr& msg ); - void callbackUserDefPose( const geometry_msgs::Pose::ConstPtr& msg ); - void callbackDoMapping( const std_msgs::Bool::ConstPtr& msg ); - void callbackResetMap( const std_msgs::Empty::ConstPtr& msg ); - void callbackLoadedMap( const nav_msgs::OccupancyGrid::ConstPtr& msg ); - void callbackMasking( const nav_msgs::OccupancyGrid::ConstPtr& msg ); - void callbackResetHigh(const std_msgs::Empty::ConstPtr& msg); - void callbackInitialPose(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg); - /** - * This function resets the current maps to the initial state. - */ - void resetMaps(); - - /** - * This function processes the current odometry data in combination with the - * last send odometry and laser informations to pass on corresponding data - * to the filter threads. - * - * @param odoTime timestamp of this odometry data - * @param currentOdometryPose the current odometry measurements of the robot - */ - void processMeasurements(ros::Time odoTime, Pose currentOdometryPose); - - /** - * This method retrieves the current map of the slam filter and sends a map - * data message containing the map. - */ - void sendMapDataMessage(); - - /** - * This method gets the current position from the filter thread and sends it - * in a position data message. - */ - void sendPositionDataMessage(); - - /** - * This variable stores the identification number of a GetPositionDataM. - * It is needed for a correct response message. - */ - unsigned int m_LastLaserMessageId; - - /** - * This variables stores the last odometry measurement as reference that is used - * to compute the pose of the robot during a specific laserscan. - */ - Pose m_ReferenceOdometryPose; - - /** - * This variable stores the time of the last odometry measurement as reference - * which is used to compute the pose of the robot during a specific laserscan. - */ - ros::Time m_ReferenceOdometryTime; - - /** - * This variable stores the time the last map message was sent to be able to - * compute the time for the next map send. - */ - ros::Time m_LastMapSendTime; - ros::Time m_LastPositionSendTime; - - /** - * This variable stores the last laser measurement. - */ - sensor_msgs::LaserScanConstPtr m_LastLaserData; - - /** - * This variable stores the time of last laser measurement. - */ - ros::Time m_LaserDataTime; - - /** - * time stamp of last particle filter step - */ - ros::Time m_LastMappingTime; - - - /** - * This variable stores a pointer to the hyper slam filter - */ - HyperSlamFilter* m_HyperSlamFilter; - - /** - * Scatter variances in self localization. - */ - double m_ScatterVarXY; - double m_ScatterVarTheta; - - /** - * This variabe is true, if the slam algorithm is used for mapping and - * keeps updating the map, false otherwise. - */ - bool m_DoMapping; - - /** - * duration to wait between two particle filter steps - */ - ros::Duration m_WaitDuration; - - /** - * Broadcasts the transform map -> base_link - */ - tf::TransformBroadcaster m_tfBroadcaster; - - /** - * subscribers and publishers - */ - ros::Subscriber m_LaserScanSubscriber; - ros::Subscriber m_OdometrySubscriber; - ros::Subscriber m_UserDefPoseSubscriber; - ros::Subscriber m_DoMappingSubscriber; - ros::Subscriber m_ResetMapSubscriber; - ros::Subscriber m_LoadMapSubscriber; - ros::Subscriber m_MaskingSubscriber; - ros::Subscriber m_ResetHighSubscriber; - ros::Subscriber m_InitialPoseSubscriber; - - ros::Publisher m_PoseStampedPublisher; - ros::Publisher m_SLAMMapPublisher; - -}; - -#endif diff --git a/homer_nav_libs/CHANGELOG.rst b/homer_nav_libs/CHANGELOG.rst deleted file mode 100644 index 9545218b..00000000 --- a/homer_nav_libs/CHANGELOG.rst +++ /dev/null @@ -1,38 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package homer_nav_libs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1.0.6 (2015-11-27) ------------------- -* added export tags -* added eigen as run_depend -* removed env HOMER_DIR from CMakeLists.txt -* Contributors: Niklas Yann Wettengel - -1.0.5 (2015-11-24) ------------------- -* added missing files -* Contributors: Niklas Yann Wettengel - -1.0.4 (2015-11-20) ------------------- -* changed build dependency from libeigen3-dev to eigen -* Contributors: Niklas Yann Wettengel - -1.0.3 (2015-11-20) ------------------- -* added libeigen3-dev build dependency -* Contributors: Niklas Yann Wettengel - -1.0.2 (2015-11-20) ------------------- -* added cmake_modules as build dependency in package.xml -* added Maintainers -* removed components -* Raphael as maintainer added -* Contributors: Niklas Yann Wettengel, Raphael Memmesheimer - -1.0.1 (2015-09-08) ------------------- -* init -* Contributors: Raphael Memmesheimer diff --git a/homer_nav_libs/CMakeLists.txt b/homer_nav_libs/CMakeLists.txt deleted file mode 100644 index 1909a3f9..00000000 --- a/homer_nav_libs/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) -project(homer_nav_libs) - -find_package(catkin REQUIRED - roscpp - geometry_msgs - tf - cmake_modules -) - -find_package(Eigen REQUIRED) - -catkin_package( - INCLUDE_DIRS src - LIBRARIES Explorer SpeedControl MappingMath - CATKIN_DEPENDS roscpp geometry_msgs tf - DEPENDS Eigen) - - -include_directories( - src - ${catkin_INCLUDE_DIRS} - ${Eigen_INCLUDE_DIRS} -) - -add_subdirectory(src/Explorer) -add_subdirectory(src/SpeedControl) -add_subdirectory(src/Math) diff --git a/homer_nav_libs/README.md b/homer_nav_libs/README.md deleted file mode 100644 index 4c31e40e..00000000 --- a/homer_nav_libs/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# nav_libs - -## Known Issues / Todo's - -Im Package nav_libs ist eine Kopie der Robbie-Bibliothek Math, umbenannt in MappingMath, die nur von homer_mapping benutzt werden soll, solange es keine vernünftige Alternative für die Pose gibt. - -## Introduction - -Das Package nav_libs enthält einige Bibliotheken, die vom Package homer_mapping und nav_libs verwendet werden. Außerdem enthält es im Ordner tools die Header-Datei tools.h, die Funktionen zum Transformieren in verschiedene Koordinatenframes enthält. All diese Funktionen befinden sich im namespace "map_tools". - -* Die Bibliothek `Explorer` wird von homer_mapping und homer_navigation verwendet und enthält die Pfadplanungsalgorithmen A-Stern sowie die dafür benötigte Datenstruktur der GridMap. -* Die Bibliothek `SpeedControl` wird von homer_navigation verwendet und ist dafür zuständig abhängig von den aktuellen Laserdaten die höchstzulässige Geschwindigkeit zu berechnen. -* Die Bibliothek `MappingMath` wird von homer_mapping verwendet und enthält die Datenstruktur Pose, in der die aktuelle Roboterposition innerhalb der Node gespeichert wird. diff --git a/homer_nav_libs/package.xml b/homer_nav_libs/package.xml deleted file mode 100644 index 0468e7d8..00000000 --- a/homer_nav_libs/package.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0"?> -<package> - <name>homer_nav_libs</name> - <version>1.0.6</version> - <description>The nav_libs package</description> - - <maintainer email="vseib@uni-koblenz.de">Viktor Seib</maintainer> - <maintainer email="niyawe@uni-koblenz.de">Niklas Yann Wettengel</maintainer> - <maintainer email="heuer@uni-koblenz.de">Gregor Heuer</maintainer> - <maintainer email="raphael@uni-koblenz.de">Raphael Memmesheimer</maintainer> - <author email="mknauf@uni-koblenz.de">Malte Knauf</author> - <license>GPLv3</license> - - <buildtool_depend>catkin</buildtool_depend> - <build_depend>geometry_msgs</build_depend> - <build_depend>roscpp</build_depend> - <build_depend>tf</build_depend> - <build_depend>cmake_modules</build_depend> - <build_depend>eigen</build_depend> - - <run_depend>roscpp</run_depend> - <run_depend>geometry_msgs</run_depend> - <run_depend>tf</run_depend> - <run_depend>eigen</run_depend> - - <export> - <cpp cflags="-I${prefix}/src" lflags="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -lExplorer"/> - <cpp cflags="-I${prefix}/src" lflags="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -lMappingMath"/> - <cpp cflags="-I${prefix}/src" lflags="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -lSpeedControl"/> - </export> - -</package> diff --git a/homer_nav_libs/readme.pdf b/homer_nav_libs/readme.pdf deleted file mode 100644 index 98fc92ccae14a8a818948ce4c73a8926f6ad2028..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79468 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%0Drz3+)|5F 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 B6{!FK diff --git a/homer_nav_libs/src/Explorer/CMakeLists.txt b/homer_nav_libs/src/Explorer/CMakeLists.txt deleted file mode 100644 index 4c5aee03..00000000 --- a/homer_nav_libs/src/Explorer/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(Explorer_SRC - Explorer.cpp -) - -add_library(Explorer ${Explorer_SRC}) diff --git a/homer_nav_libs/src/Explorer/Explorer.cpp b/homer_nav_libs/src/Explorer/Explorer.cpp deleted file mode 100644 index 65a447f2..00000000 --- a/homer_nav_libs/src/Explorer/Explorer.cpp +++ /dev/null @@ -1,1426 +0,0 @@ -#include <cmath> -#include <iostream> -#include <queue> -#include <sstream> - -#include "tools/tools.h" - -#include "Explorer.h" - -using namespace std; -using namespace ExplorerConstants; - -Explorer::Explorer ( double minAllowedObstacleDistance, double maxAllowedObstacleDistance, - double minSafeObstacleDistance, double maxSafeObstacleDistance, - double safePathWeight, double frontierSafenessFactor, int unknownThreshold ) -{ - ExplorerConstants::UNKNOWN = unknownThreshold; - - m_MinAllowedObstacleDistance = minAllowedObstacleDistance; - m_MaxAllowedObstacleDistance = maxAllowedObstacleDistance; - - m_MinSafeObstacleDistance = minSafeObstacleDistance; - m_MaxSafeObstacleDistance = maxSafeObstacleDistance; - - m_SafePathWeight = safePathWeight; - m_FrontierSafenessFactor = frontierSafenessFactor; - - m_OccupancyMap = 0; - m_ObstacleTransform = 0; - m_CostTransform = 0; - m_TargetMap = 0; - m_DrivingDistanceTransform = 0; - m_TargetDistanceTransform = 0; - m_PathTransform = 0; - m_ExplorationTransform = 0; - m_DesiredDistance = 0; -} - -Explorer::~Explorer() -{ - releaseMaps(); - releaseMap( m_OccupancyMap ); -} - -void Explorer::releaseMaps() -{ - releaseMap( m_TargetMap ); - releaseMap( m_ObstacleTransform ); - releaseMap( m_CostTransform ); - releaseMap( m_DrivingDistanceTransform ); - releaseMap( m_TargetDistanceTransform ); - releaseMap( m_PathTransform ); - releaseMap( m_ExplorationTransform ); -} - -// SETTERS //////////////////////////////////////////////////////////////////////////////////////////////// - -void Explorer::setUnknownThreshold(int unknownTresh) -{ - ExplorerConstants::UNKNOWN = unknownTresh; -} - -void Explorer::setAllowedObstacleDistance ( double min, double max ) -{ - m_MinAllowedObstacleDistance = min; - m_MaxAllowedObstacleDistance = max; - releaseMaps(); -} - -void Explorer::setSafeObstacleDistance ( double min, double max ) -{ - m_MinSafeObstacleDistance = min; - m_MaxSafeObstacleDistance = max; - releaseMaps(); -} - -void Explorer::setSafePathWeight ( double weight ) -{ - m_SafePathWeight = weight; - releaseMaps(); -} - -void Explorer::setFrontierSafenessFactor( double frontierSafenessFactor ) -{ - m_FrontierSafenessFactor = frontierSafenessFactor; - releaseMaps(); -} - -void Explorer::setOccupancyMap ( int width, int height, geometry_msgs::Pose origin, int8_t* data ) -{ - if ( !data ) { - ROS_ERROR( "Received 0-pointer." ); - return; - } - releaseMaps(); - releaseMap( m_OccupancyMap ); - //m_OccupancyMap = new GridMap<unsigned char> ( width, height, data, exploredRegion ); - m_OccupancyMap = new GridMap<int8_t> ( width, height, data ); - m_Origin = origin; -} - - -void Explorer::updateObstacles(int width, int height, geometry_msgs::Pose origin, int8_t* mapData) -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - if ( (width != m_OccupancyMap->width()) || (height != m_OccupancyMap->height()) ) { - ROS_ERROR_STREAM( "Wrong map size!" ); - return; - } - for ( unsigned i=0; i<m_OccupancyMap->width()*m_OccupancyMap->height(); i++ ) - { - int8_t* myMapData=m_OccupancyMap->getDirectAccess(0,0); - if ( myMapData[i] != UNKNOWN ) - { - myMapData[i]=mapData[i]; - } - } - releaseMaps(); -} - -void Explorer::resetExploration() -{ - m_DesiredDistance = 0; -} - -void Explorer::setStart ( Eigen::Vector2i start ) -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR_STREAM( "Occupancy map is missing." ); - return; - } - if (( start.x() <= 1 ) || ( start.y() <= 1 ) || ( start.x() >= m_OccupancyMap->width()-1 ) || ( start.y() >= m_OccupancyMap->height()-1 ) ) - { - ROS_ERROR_STREAM( "Invalid position!" ); - return; - } - computeWalkableMaps(); - - if ( !isWalkable( start.x(), start.y() ) ) - { - Eigen::Vector2i correctedStart=getNearestWalkablePoint( start ); - if ( !isWalkable( correctedStart.x(), correctedStart.y() ) ) - { - ROS_ERROR_STREAM( "No walkable position was found on the map!" ); - } else - { - ROS_INFO_STREAM("Start position " << start.x() << "," << start.y() << " was corrected to " << correctedStart.x() << "," << correctedStart.y()); - } - m_Start = correctedStart; - return; - } - m_Start = start; -} - - -Eigen::Vector2i Explorer::getNearestAccessibleTarget(Eigen::Vector2i target ) -{ - // TODO VS - ros::Time start = ros::Time::now(); - - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return target; - } - if ( ( target.x() <= 1 ) || ( target.y() <= 1 ) || ( target.x() >= m_OccupancyMap->width()-1 ) || ( target.y() >= m_OccupancyMap->height()-1 ) ) - { - ROS_ERROR( "Invalid position!" ); - return target; - } - - ROS_ERROR_STREAM("starting: computeApproachableMaps at " << (ros::Time::now() - start));// TODO VS - computeApproachableMaps(); - ROS_ERROR_STREAM("finished: computeApproachableMaps at " << (ros::Time::now() - start));// TODO VS - Eigen::Vector2i correctTarget=target; - - if ( !isApproachable( target.x(), target.y() ) ) - { - ROS_INFO_STREAM("target cell in drivingdistancetransform: " << m_DrivingDistanceTransform->getValue ( target.x(), target.y() )); - ROS_INFO_STREAM("target " << target << " is not approachable. Correcting target..."); - ROS_ERROR_STREAM("starting iteration over obstacle transform at " << (ros::Time::now() - start));// TODO VS - int minSqrDist=INT_MAX; - computeWalkableMaps(); - for ( int x = 0; x < m_ObstacleTransform->height(); x++ ) - { - for ( int y = 0; y < m_ObstacleTransform->width(); y++ ) - { - if ( isApproachable ( x,y ) && isWalkable( x , y) ) - { - int xDiff = target.x() - x; - int yDiff = target.y() - y; - int sqrDist = xDiff*xDiff + yDiff*yDiff; - if ( sqrDist < minSqrDist ) - { - correctTarget.x() = x; - correctTarget.y() = y; - minSqrDist = sqrDist; - } - } - } - } - ROS_ERROR_STREAM("finished iteration over obstacle transform at " << (ros::Time::now() - start));// TODO VS - } - ROS_DEBUG_STREAM("Target position " << target.x() << "," << target.y() << " was corrected to " << correctTarget.x() << "," << correctTarget.y()); - - return correctTarget; -} - - -Eigen::Vector2i Explorer::getNearestWalkablePoint( Eigen::Vector2i target ) -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return target; - } - if (( target.x() <= 1 ) || ( target.y() <= 1 ) || ( target.x() >= m_OccupancyMap->width()-1 ) || ( target.y() >= m_OccupancyMap->height()-1 ) ) - { - ROS_ERROR( "Invalid position!" ); - return target; - } - - computeWalkableMaps(); - Eigen::Vector2i correctTarget=target; - - - if ( !isWalkable( target.x(), target.y() ) ) - { - int minSqrDist=INT_MAX; - for ( int x = 0; x < m_ObstacleTransform->height(); x++ ) - { - for ( int y = 0; y < m_ObstacleTransform->width(); y++ ) - { - if ( isWalkable ( x,y ) ) - { - int xDiff = target.x() - x; - int yDiff = target.y() - y; - int sqrDist = xDiff*xDiff + yDiff*yDiff; - if ( sqrDist < minSqrDist ) - { - correctTarget.x() = x; - correctTarget.y() = y; - minSqrDist = sqrDist; - } - } - } - } - } - ROS_DEBUG_STREAM("Position " << target.x() << "," << target.y() << " was corrected to " << correctTarget.x() << "," << correctTarget.y()); - - return correctTarget; -} - - -void Explorer::setTarget (Eigen::Vector2i target ) -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - if ( ( target.x() <= 1 ) || ( target.y() <= 1 ) || ( target.x() >= m_OccupancyMap->width()-1 ) || ( target.y() >= m_OccupancyMap->height()-1 ) ) - { - ROS_ERROR( "Invalid position!" ); - return; - } - computeApproachableMaps(); - if ( !isApproachable ( target.x(), target.y() ) ) - { - ROS_WARN( "Target position is not approachable. Path computation will possibly fail." ); - } - m_Target = target; - m_DesiredDistance = 0; -} - - -void Explorer::setTarget (Eigen::Vector2i target, int desiredDistance ) -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - - if ( desiredDistance < 1 ) - { - setTarget( target ); - return; - } - - if ( target.x() + desiredDistance <= 1 || target.x() - desiredDistance >= m_OccupancyMap->width()-1 || - target.y() + desiredDistance <= 1 || target.y() - desiredDistance >= m_OccupancyMap->height()-1 ) - { - ROS_ERROR( "Invalid position" ); - return; - } - computeApproachableMaps(); - // TODO: check if region is approachable - m_Target = target; - m_DesiredDistance = desiredDistance; -} - - -// GETTERS //////////////////////////////////////////////////////////////////////////////////////////////// - -Eigen::Vector2i Explorer::getStart() const -{ - return m_Start; -} - -Eigen::Vector2i Explorer::getTarget() const -{ - return m_Target; -} - -GridMap<int8_t>* Explorer::getOccupancyMap() -{ - return m_OccupancyMap; -} - -GridMap<double>* Explorer::getObstacleTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computeObstacleTransform(); - return m_ObstacleTransform; -} - -GridMap<double>* Explorer::getCostTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computeCostTransform(); - return m_CostTransform; -} - -GridMap<bool>* Explorer::getTargetMap() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - - computeTargetMap(); - return m_TargetMap; -} - -GridMap<double>* Explorer::getDrivingDistanceTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computeDrivingDistanceTransform(); - return m_DrivingDistanceTransform; -} - -GridMap<double>* Explorer::getTargetDistanceTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computeTargetDistanceTransform(); - return m_TargetDistanceTransform; -} - -GridMap<double>* Explorer::getPathTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computePathTransform(); - return m_PathTransform; -} - -GridMap<double>* Explorer::getExplorationTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return 0; - } - computeExplorationTransform(); - return m_ExplorationTransform; -} - - - -// MAP GENERATION ////////////////////////////////////////////////////////////////////////////////////////////////7 - - -void Explorer::computeApproachableMaps() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - computeDrivingDistanceTransform(); -} - - -void Explorer::computeWalkableMaps() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - computeObstacleTransform(); -} - - -void Explorer::computeDrivingDistanceTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - - if ( m_DrivingDistanceTransform ) { return; } - - ROS_DEBUG( "Computing drivingDistanceTransform..." ); - resetMap( m_DrivingDistanceTransform ); - distanceFloodFill ( m_DrivingDistanceTransform, m_Start ); -} - - -void Explorer::computeTargetDistanceTransform() -{ - if ( !m_OccupancyMap ) - { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - - if ( m_TargetDistanceTransform ) { return; } - - ROS_DEBUG( "Computing targetDistanceTransform..." ); - resetMap( m_TargetDistanceTransform ); - distanceFloodFill ( m_TargetDistanceTransform, m_Target ); -} - - -void Explorer::computeRegionMap() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - - resetMap( m_TargetMap ); - ROS_DEBUG( "Computing target region map..." ); - - m_TargetMap->fill( false ); - const int desiredDistanceSquared = m_DesiredDistance * m_DesiredDistance; - int height = m_OccupancyMap->height(); - int width = m_OccupancyMap->width(); - - // draw a circle onto the ExplorationMap - const int firstX = m_Target.x() - m_DesiredDistance <= 1 ? 2 : m_Target.x() - m_DesiredDistance; - const int firstY = m_Target.y() - m_DesiredDistance <= 1 ? 2 : m_Target.y() - m_DesiredDistance; - const int lastX = m_Target.x() + m_DesiredDistance >= width-1 ? width-2 : m_Target.x() + m_DesiredDistance; - const int lastY = m_Target.y() + m_DesiredDistance >= height-1 ? height-2 : m_Target.y() + m_DesiredDistance; - - for ( int y = firstY; y <= lastY; ++y ) - { - for ( int x = firstX; x <= lastX; ++x ) - { - const int dx = x - m_Target.x(); - const int dy = y - m_Target.y(); - - if ( dx*dx + dy*dy <= desiredDistanceSquared ) - { - m_TargetMap->setValue( x, y, true ); - } - } - } -} - -void Explorer::computeFrontierMap() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Occupancy map is missing." ); - return; - } - - // if ( m_FrontierMap ) { return; } - - resetMap( m_TargetMap ); - - ROS_DEBUG( "Computing frontier map..." ); - m_TargetMap->fill ( 0 ); - // extract borders - for ( int y = 1; y < m_OccupancyMap->height() - 1; y++ ) - { - for ( int x = 1; x < m_OccupancyMap->width() - 1; x++ ) - { - int value = m_OccupancyMap->getValue ( x, y ); - int value_u = m_OccupancyMap->getValue ( x, y - 1 ); - int value_d = m_OccupancyMap->getValue ( x, y + 1 ); - int value_l = m_OccupancyMap->getValue ( x - 1, y ); - int value_r = m_OccupancyMap->getValue ( x + 1, y ); - bool isFree = value < UNKNOWN && value != NOT_SEEN_YET; - bool upUnknown = (value_u == UNKNOWN || value_u == NOT_SEEN_YET); - bool downUnknown = (value_d == UNKNOWN || value_u == NOT_SEEN_YET); - bool leftUnknown = (value_l == UNKNOWN || value_u == NOT_SEEN_YET); - bool rightUnknown = (value_r == UNKNOWN || value_u == NOT_SEEN_YET); - bool hasUnknownNeighbour = upUnknown || downUnknown || leftUnknown || rightUnknown; - bool isSafe = m_ObstacleTransform->getValue ( x, y ) > m_FrontierSafenessFactor * m_MinAllowedObstacleDistance; - if ( isFree && hasUnknownNeighbour && isSafe ) - { - m_TargetMap->setValue ( x, y, 1 ); - } - else - { - m_TargetMap->setValue ( x, y, 0 ); - } - } - } -} - -void Explorer::computeTargetMap() -{ - if ( m_DesiredDistance < 1 ) - { - computeFrontierMap(); - } - else - { - computeRegionMap(); - } -} - -void Explorer::computeObstacleTransform() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return; - } - - if ( m_ObstacleTransform ) { return; } - - resetMap( m_ObstacleTransform ); - - ROS_DEBUG( "Computing obstacle transform..." ); - for ( int x = 0; x < m_ObstacleTransform->width(); x++ ) - { - for ( int y = 0; y < m_ObstacleTransform->height(); y++ ) - { - if ( m_OccupancyMap->getValue ( x, y ) > UNKNOWN || - m_OccupancyMap->getValue(x, y) == NOT_SEEN_YET) - { - m_ObstacleTransform->setValue ( x, y, 0 ); - } - else - { - m_ObstacleTransform->setValue ( x, y, OBSTACLE ); - } - } - } - - int width = m_ObstacleTransform->width(); - int height = m_ObstacleTransform->height(); - double* f = new double[width > height ? width : height]; - - // transform along columns - for ( int x = 0; x < width; x++ ) - { - for ( int y = 0; y < height; y++ ) - { - // copy column - f[y] = m_ObstacleTransform->getValue ( x, y ); - } - // 1-D transform of column - double* d = distanceTransform1D ( f, height ); - // copy transformed 1-D to output image - for ( int y = 0; y < height; y++ ) - { - m_ObstacleTransform->setValue ( x, y, d[y] ); - } - delete [] d; - } - - // transform along rows - for ( int y = 0; y < height; y++ ) - { - for ( int x = 0; x < width; x++ ) - { - f[x] = m_ObstacleTransform->getValue ( x, y ); - } - double* d = distanceTransform1D ( f, width ); - for ( int x = 0; x < width; x++ ) - { - m_ObstacleTransform->setValue ( x, y, d[x] ); - } - delete [] d; - } - delete f; - - // take square roots - for ( int y = 0; y < m_ObstacleTransform->height(); y++ ) - { - for ( int x = 0; x < m_ObstacleTransform->width(); x++ ) - { - if ( isWalkable( x,y ) ) - { - float value = sqrt ( m_ObstacleTransform->getValue ( x, y ) ); - m_ObstacleTransform->setValue ( x, y, value ); - } - } - } -} - - -void Explorer::computeCostTransform() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return; - } - - if ( m_CostTransform ) { return; } - - computeObstacleTransform(); - computeApproachableMaps(); - - resetMap( m_CostTransform ); - m_CostTransform->fill( ExplorerConstants::MAX_COST ); - - for ( unsigned y=0; y<m_CostTransform->height(); y++) - { - for ( unsigned x=0; x<m_CostTransform->width(); x++) - { - if ( !isApproachable( x, y ) ) { - continue; - } - double dist = m_ObstacleTransform->getValue(x, y); - double cost = 0; - if ( dist < m_MinSafeObstacleDistance ) { - cost = m_MinSafeObstacleDistance - dist; - } - if ( dist > m_MaxSafeObstacleDistance ) { - cost = dist - m_MaxSafeObstacleDistance; - } - m_CostTransform->setValue( x, y, cost * cost ); - } - } -} - - -void Explorer::computePathTransform() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return; - } - - if ( m_PathTransform ) { return; } - - computeObstacleTransform(); - computeCostTransform(); - - resetMap( m_PathTransform ); - - ROS_DEBUG( "Computing path transform..." ); - GridMap<double>* map = m_PathTransform; - int width = map->width(); - int height = map->height(); - double maxDistance = MAX_DISTANCE; - map->fill ( maxDistance ); - - int fromX = m_Target.x(); - int fromY = m_Target.y(); - map->setValue ( fromX, fromY, 0 ); - - queue<int> xQueue; - queue<int> yQueue; - xQueue.push ( fromX + 1 ); - yQueue.push ( fromY ); - xQueue.push ( fromX - 1 ); - yQueue.push ( fromY ); - xQueue.push ( fromX ); - yQueue.push ( fromY - 1 ); - xQueue.push ( fromX ); - yQueue.push ( fromY + 1 ); - int xVal, yVal; - while ( !xQueue.empty() ) - { - xVal = xQueue.front(); - yVal = yQueue.front(); - xQueue.pop(); - yQueue.pop(); - if ( xVal > 0 && xVal < width - 1 && yVal > 0 && yVal < height - 1 && isWalkable( xVal, yVal ) ) - { - float value = map->getValue ( xVal, yVal ); - float value_u = map->getValue ( xVal, yVal - 1 ) + 1; - float value_d = map->getValue ( xVal, yVal + 1 ) + 1; - float value_l = map->getValue ( xVal - 1, yVal ) + 1; - float value_r = map->getValue ( xVal + 1, yVal ) + 1; - - float value_ur = map->getValue ( xVal + 1, yVal - 1 ) + 1.4142; - float value_ul = map->getValue ( xVal - 1, yVal - 1 ) + 1.4142; - float value_ll = map->getValue ( xVal - 1, yVal + 1 ) + 1.4142; - float value_lr = map->getValue ( xVal + 1, yVal + 1 ) + 1.4142; - - float min1 = value_u < value_d ? value_u : value_d; - float min2 = value_l < value_r ? value_l : value_r; - float min3 = value_ur < value_ul ? value_ur : value_ul; - float min4 = value_ll < value_lr ? value_ll : value_lr; - float min12 = min1 < min2 ? min1 : min2; - float min34 = min3 < min4 ? min3 : min4; - float min = min12 < min34 ? min12 : min34; - float newVal = min + m_SafePathWeight * m_CostTransform->getValue( xVal, yVal ); - if ( value > newVal ) - { - map->setValue ( xVal, yVal, newVal ); - if ( map->getValue ( xVal, yVal + 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal, yVal - 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal - 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal + 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal - 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal - 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal + 1 ); - } - } - } - } -} - - -void Explorer::computeExplorationTransform() -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return; - } - - if ( m_ExplorationTransform ) { return; } - - ROS_INFO_STREAM("computeExplorationTransform: before obstacle transform"); - computeObstacleTransform(); - ROS_INFO_STREAM("computeExplorationTransform: before cost transform"); - computeCostTransform(); - ROS_INFO_STREAM("computeExplorationTransform: before target map"); - computeTargetMap(); - ROS_INFO_STREAM("computeExplorationTransform: before walkable maps"); - computeWalkableMaps(); - ROS_INFO_STREAM("computeExplorationTransform: before exploration transform"); - resetMap( m_ExplorationTransform ); - - ROS_DEBUG( "Computing exploration transform..." ); - GridMap<double>* map = m_ExplorationTransform; - int width = map->width(); - int height = map->height(); - double maxDistance = MAX_DISTANCE; - map->fill ( maxDistance ); - queue<int> xQueue; - queue<int> yQueue; - // fill seeds: Mark the frontiers as targets - ROS_INFO_STREAM("computeExplorationTransform: before first loop"); - for ( int y = 0; y < m_TargetMap->height(); y++ ) - { - for ( int x = 0; x < m_TargetMap->width(); x++ ) - { - if ( m_TargetMap->getValue ( x, y ) == 1 ) - { - map->setValue ( x, y, 0 ); - xQueue.push ( x + 1 ); - yQueue.push ( y ); - xQueue.push ( x - 1 ); - yQueue.push ( y ); - xQueue.push ( x ); - yQueue.push ( y - 1 ); - xQueue.push ( x ); - yQueue.push ( y + 1 ); - } - } - } - ROS_INFO_STREAM("computeExplorationTransform: After first looop"); - // Now go through the coordinates in the queue - int xVal, yVal; - ROS_INFO_STREAM("computeExplorationTransform: before while loop"); - while ( !xQueue.empty() ) - { - xVal = xQueue.front(); - yVal = yQueue.front(); - xQueue.pop(); - yQueue.pop(); - if ( xVal > 0 && xVal < width - 1 && yVal > 0 && yVal < height - 1 && isWalkable ( xVal, yVal ) ) - { - // Get own cost and the cost of the 8 neighbor cells (neighbors plus the cost to go there) - float value = map->getValue ( xVal, yVal ); - float value_u = map->getValue ( xVal, yVal - 1 ) + 1; - float value_d = map->getValue ( xVal, yVal + 1 ) + 1; - float value_l = map->getValue ( xVal - 1, yVal ) + 1; - float value_r = map->getValue ( xVal + 1, yVal ) + 1; - float value_ur = map->getValue ( xVal + 1, yVal - 1 ) + 1.4142; - float value_ul = map->getValue ( xVal - 1, yVal - 1 ) + 1.4142; - float value_ll = map->getValue ( xVal - 1, yVal + 1 ) + 1.4142; - float value_lr = map->getValue ( xVal + 1, yVal + 1 ) + 1.4142; - float min1 = value_u < value_d ? value_u : value_d; - float min2 = value_l < value_r ? value_l : value_r; - float min3 = value_ur < value_ul ? value_ur : value_ul; - float min4 = value_ll < value_lr ? value_ll : value_lr; - float min12 = min1 < min2 ? min1 : min2; - float min34 = min3 < min4 ? min3 : min4; - float min = min12 < min34 ? min12 : min34; - float newVal = min + m_SafePathWeight * m_CostTransform->getValue( xVal, yVal ); - if ( value > newVal ) - { - // Cost is lower then the currently known cost: Reduce cost here - map->setValue ( xVal, yVal, newVal ); - // Add the neighbours that might profit in the queue - if ( map->getValue ( xVal, yVal + 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal, yVal - 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal - 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal + 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal - 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal - 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal + 1 ); - } - } - } - } - ROS_INFO_STREAM("computeExplorationTransform: after exploration transform"); -} - - -vector<Eigen::Vector2i> Explorer::sampleWaypointsFromPath ( std::vector<Eigen::Vector2i> pathPoints, float threshold ) -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return pathPoints; - } - if ( pathPoints.size() < 3 ) { - return pathPoints; - } - - computeObstacleTransform(); - - vector<Eigen::Vector2i> simplifiedPath; - simplifiedPath.reserve( pathPoints.size() ); - - Eigen::Vector2i lastAddedPoint = pathPoints[0]; - simplifiedPath.push_back ( lastAddedPoint ); - - for ( unsigned int i = 1; i < pathPoints.size() - 1; i++ ) - { - double distanceToNextPoint = map_tools::distance(lastAddedPoint, pathPoints.at(i)); - double obstacleDistanceLastAddedPoint = m_ObstacleTransform->getValue ( lastAddedPoint.x(), lastAddedPoint.y() ); - double obstacleDistancePossibleNextPoint = m_ObstacleTransform->getValue ( pathPoints[i].x(), pathPoints[i].y() ); - if (( distanceToNextPoint >= obstacleDistanceLastAddedPoint*threshold ) || - ( distanceToNextPoint >= obstacleDistancePossibleNextPoint*threshold ) ) - { - simplifiedPath.push_back ( pathPoints[i] ); - lastAddedPoint = pathPoints[i]; - } - } - simplifiedPath.push_back ( pathPoints[pathPoints.size() - 1] ); - return simplifiedPath; -} - - -std::vector<Eigen::Vector2i> Explorer::getPath(bool& success) -{ - success = false; - - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return vector<Eigen::Vector2i>(); - } - - if ( m_DesiredDistance > 0 ) { - // we are actually performing an exploration since the target - // is a region. - ROS_INFO_STREAM("Desired Distance > 0: Executing getExplorationTransformPath"); - return getExplorationTransformPath( success ); - } - ROS_INFO_STREAM("Computing Path Transform"); - computePathTransform(); - ROS_INFO_STREAM("Finished Path Transform"); - /* - ROS_INFO_STREAM("Explorer: Path Transform: " << m_TargetDistanceTransform->width() << " " << m_TargetDistanceTransform->height()); - ROS_INFO_STREAM("---------------------"); - for(int x = 0; x < 10; x++) { - std::stringstream str; - str << "|"; - for(int y = 0; y < 10; y++) { - str << (double)(m_TargetDistanceTransform->getValue(x, y)) << "|"; - } - ROS_INFO(str.str().c_str()); - } - ROS_INFO_STREAM("---------------------"); - */ - vector<Eigen::Vector2i> path; - - int x = m_Start.x(); - int y = m_Start.y(); - - int width = m_OccupancyMap->width(); - int height = m_OccupancyMap->height(); - - //special case: start and end point are equal, return single waypoint - if ( map_tools::distance( m_Start, m_Target ) < 2.0 ) - { - success = true; - path.push_back ( Eigen::Vector2i( m_Start.x(), m_Start.y() ) ); - return path; - } - - while ( x != m_Target.x() || y != m_Target.y() ) - { - path.push_back ( Eigen::Vector2i( x, y ) ); - int minPosX = x; - int minPosY = y; - double min = m_PathTransform->getValue ( x, y ); - - if ( ( x <= 1 ) || ( y <= 1 ) || ( x >= width-1 ) || ( y >= height-1 ) ) - { - ROS_ERROR( "Out of map bounds" ); - return vector<Eigen::Vector2i>(); - } - - for ( int i = -1; i <= 1; i++ ) - { - for ( int j = -1; j <= 1; j++ ) - { - double pt = m_PathTransform->getValue ( x + i, y + j ); - if ( pt < min ) - { - min = pt; - minPosX = x + i; - minPosY = y + j; - } - } - } - if ( minPosX == x && minPosY == y ) - { - ROS_WARN( "Target is unreachable!" ); - return vector<Eigen::Vector2i>(); - } - else - { - x = minPosX; - y = minPosY; - } - } - success = true; - - return path; -} - -vector<Eigen::Vector2i> Explorer::getExplorationTransformPath(bool& success) -{ - success = false; - - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return vector<Eigen::Vector2i>(); - } - - ROS_INFO_STREAM("Exploration Transform: Before obstacle transform"); - computeObstacleTransform(); - ROS_INFO_STREAM("Exploration Transform: Before exploration transform"); - computeExplorationTransform(); - ROS_INFO_STREAM("Exploration Transform: after obstacle transform"); - - //check if we are already there - if ( m_TargetMap->getValue ( m_Start.x(), m_Start.y() ) ) - { - success = true; - vector<Eigen::Vector2i> path; - path.push_back ( Eigen::Vector2i ( m_Start.x(), m_Start.y() ) ); - return path; - } - - int width = m_OccupancyMap->width(); - int height = m_OccupancyMap->height(); - - vector<Eigen::Vector2i> path; - int x = m_Start.x(); - int y = m_Start.y(); - - if ( m_ObstacleTransform->getValue ( x, y ) < m_MinAllowedObstacleDistance ) - { - // robot got stuck! - // find way out using ObstacleTransform... - int maxPosX = x; - int maxPosY = y; - - if ( ( x <= 1 ) || ( y <= 1 ) || ( x >= width-1 ) || ( y >= height-1 ) ) - { - ROS_ERROR( "Out of map bounds" ); - return vector<Eigen::Vector2i>(); - } - - while ( m_ObstacleTransform->getValue ( maxPosX, maxPosY ) < m_MinAllowedObstacleDistance ) - { - double max = m_ObstacleTransform->getValue ( x, y ); - for ( int i = -1; i <= 1; i++ ) - { - for ( int j = -1; j <= 1; j++ ) - { - double pt = m_ObstacleTransform->getValue ( x + i, y + j ); - if ( pt > max ) - { - max = pt; - maxPosX = x + i; - maxPosY = y + j; - } - } - } - if ( maxPosX == x && maxPosY == y ) // no ascentFound - { - break; - } - else - { - path.push_back ( Eigen::Vector2i ( maxPosX, maxPosY ) ); - x = maxPosX; - y = maxPosY; - } - } - } - // now path is "free" - bool descentFound = true; - while ( descentFound ) - { - descentFound = false; - int minPosX = x; - int minPosY = y; - double min = m_ExplorationTransform->getValue ( x, y ); - if ( ( x <= 1 ) || ( y <= 1 ) || ( x >= width-1 ) || ( y >= height-1 ) ) - { - ROS_ERROR( "Out of map bounds" ); - return vector<Eigen::Vector2i>(); - } - - for ( int i = -1; i <= 1; i++ ) - { - for ( int j = -1; j <= 1; j++ ) - { - double pt = m_ExplorationTransform->getValue ( x + i, y + j ); - if ( pt < min ) - { - min = pt; - minPosX = x + i; - minPosY = y + j; - } - } - } - if ( minPosX == x && minPosY == y ) // no descentFound - { - descentFound = false; - } - else - { - descentFound = true; - path.push_back ( Eigen::Vector2i ( minPosX, minPosY ) ); - x = minPosX; - y = minPosY; - } - } - success = true; - - ROS_INFO_STREAM("Exploration Transform: End of function"); - return path; - -#if 0 - // START P2AT HACK - vector< Eigen::Vector2i > newPath; - for ( unsigned start=0; start<path.size()-1; ++start ) - { - int maxVal = start+1; - for ( unsigned end=start+1; end<path.size(); ++end ) - { - bool ok = true; - // draw bresenham line and check wether an object is within maximum allowed distance - // THANKS TO WIKIPEDIA - int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err; - /* Entfernung in beiden Dimensionen berechnen */ - dx = path[end].x() - path[start].x(); - dy = path[end].y() - path[start].y(); - /* Vorzeichen des Inkrements bestimmen */ - incx = (dx > 0) ? 1 : (dx < 0) ? -1 : 0; - incy = (dy > 0) ? 1 : (dy < 0) ? -1 : 0; - if(dx<0) dx = -dx; - if(dy<0) dy = -dy; - /* feststellen, welche Entfernung größer ist */ - if (dx>dy) - { - /* x ist schnelle Richtung */ - pdx=incx; pdy=0; /* pd. ist Parallelschritt */ - ddx=incx; ddy=incy; /* dd. ist Diagonalschritt */ - es =dy; el =dx; /* Fehlerschritte schnell, langsam */ - } else - { - /* y ist schnelle Richtung */ - pdx=0; pdy=incy; /* pd. ist Parallelschritt */ - ddx=incx; ddy=incy; /* dd. ist Diagonalschritt */ - es =dx; el =dy; /* Fehlerschritte schnell, langsam */ - } - /* Initialisierungen vor Schleifenbeginn */ - x = path[start].x(); - y = path[start].y(); - err = el/2; - /* Pixel berechnen */ - for(t=0; t<el; ++t) /* t zaehlt die Pixel, el ist auch Anzahl */ - { - /* Aktualisierung Fehlerterm */ - err -= es; - if(err<0) - { - /* Fehlerterm wieder positiv (>=0) machen */ - err += el; - /* Schritt in langsame Richtung, Diagonalschritt */ - x += ddx; - y += ddy; - } else - { - /* Schritt in schnelle Richtung, Parallelschritt */ - x += pdx; - y += pdy; - } - - // --- start: check if obstacle around - if ( m_ObstacleTransform->getValue ( x, y ) < m_MinAllowedObstacleDistance ) - { - ok = false; - break; - } - // --- end : check if obstacle around - } // Pixel berechnen - - if ( ok ) - { - maxVal = end; - } - } // for: inner - newPath.push_back( path[maxVal] ); - start = maxVal; // incremented by foor loop to max+1 - } // for: outer - // END: P2AT HACK - - success = true; - return newPath; -#endif -} - - -bool Explorer::getNearestFrontier ( Eigen::Vector2i& nextFrontier ) -{ - if ( !m_OccupancyMap) { - ROS_ERROR( "Missing occupancy map. Aborting." ); - return false; - } - - computeFrontierMap(); - computeDrivingDistanceTransform(); - - bool found = false; - int distXPos = -1; - int distYPos = -1; - double dist = 10000000; - for ( int y = 0; y < m_TargetMap->height(); y++ ) - { - for ( int x = 0; x < m_TargetMap->width(); x++ ) - { - if ( m_TargetMap->getValue ( x, y ) == 1 && m_DrivingDistanceTransform->getValue ( x, y ) < 999999 ) - { - if ( m_DrivingDistanceTransform->getValue ( x, y ) < dist ) - { - found = true; - dist = m_DrivingDistanceTransform->getValue ( x, y ); - distXPos = x; - distYPos = y; - } - } - } - } - if ( found ) - { - nextFrontier.x() = distXPos; - nextFrontier.y() = distYPos; - return true; - } - else - { - return false; - } -} - - - -// HELPERS ////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -void Explorer::distanceFloodFill ( GridMap<double>* map, Eigen::Vector2i start ) -{ - if ( !map ) { - ROS_ERROR( "Received 0-pointer!" ); - } - - computeObstacleTransform(); - - int width = map->width(); - int height = map->height(); - map->fill ( MAX_DISTANCE ); - - int fromX = start.x(); - int fromY = start.y(); - map->setValue ( fromX, fromY, 0 ); - - queue<int> xQueue; - queue<int> yQueue; - xQueue.push ( fromX + 1 ); - yQueue.push ( fromY ); - xQueue.push ( fromX - 1 ); - yQueue.push ( fromY ); - xQueue.push ( fromX ); - yQueue.push ( fromY - 1 ); - xQueue.push ( fromX ); - yQueue.push ( fromY + 1 ); - int xVal, yVal; - while ( !xQueue.empty() ) - { - xVal = xQueue.front(); - yVal = yQueue.front(); - xQueue.pop(); - yQueue.pop(); - bool isFree = (m_OccupancyMap->getValue ( xVal, yVal ) < UNKNOWN || - m_OccupancyMap->getValue ( xVal, yVal ) != NOT_SEEN_YET); // only fill free cells - bool isSafe = m_ObstacleTransform->getValue ( xVal, yVal ) > m_MinAllowedObstacleDistance; - if ( xVal > 0 && xVal < width - 1 && yVal > 0 && yVal < height - 1 && isFree && isSafe ) - { - float value = map->getValue ( xVal, yVal ); - float value_u = map->getValue ( xVal, yVal - 1 ) + 1; - float value_d = map->getValue ( xVal, yVal + 1 ) + 1; - float value_l = map->getValue ( xVal - 1, yVal ) + 1; - float value_r = map->getValue ( xVal + 1, yVal ) + 1; - - float value_ur = map->getValue ( xVal + 1, yVal - 1 ) + 1.4142; - float value_ul = map->getValue ( xVal - 1, yVal - 1 ) + 1.4142; - float value_ll = map->getValue ( xVal - 1, yVal + 1 ) + 1.4142; - float value_lr = map->getValue ( xVal + 1, yVal + 1 ) + 1.4142; - - float min1 = value_u < value_d ? value_u : value_d; - float min2 = value_l < value_r ? value_l : value_r; - float min3 = value_ur < value_ul ? value_ur : value_ul; - float min4 = value_ll < value_lr ? value_ll : value_lr; - float min12 = min1 < min2 ? min1 : min2; - float min34 = min3 < min4 ? min3 : min4; - float min = min12 < min34 ? min12 : min34; - float newVal = min; - if ( value > newVal ) - { - map->setValue ( xVal, yVal, newVal ); - if ( map->getValue ( xVal, yVal + 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal, yVal - 1 ) > newVal + 1 ) - { - xQueue.push ( xVal ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal - 1, yVal ) > newVal + 1 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal ); - } - if ( map->getValue ( xVal + 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal - 1, yVal - 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal - 1 ); - } - if ( map->getValue ( xVal + 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal + 1 ); - yQueue.push ( yVal + 1 ); - } - if ( map->getValue ( xVal - 1, yVal + 1 ) > newVal + 1.4142 ) - { - xQueue.push ( xVal - 1 ); - yQueue.push ( yVal + 1 ); - } - } - } - } -} - - -// Implementation taken from http://www.cs.cmu.edu/~cil/vnew.html -double* Explorer::distanceTransform1D ( double *f, int n ) -{ - //int width = m_OccupancyMap->width(); - //int height = m_OccupancyMap->height(); - //double maxDistance = height > width ? height : width; - - double *d = new double[n]; - int *v = new int[n]; - double *z = new double[n+1]; - int k = 0; - v[0] = 0; - z[0] = -INT_MAX; - z[1] = INT_MAX; - for ( int q = 1; q <= n-1; q++ ) - { - double s = ( ( f[q]+ ( q*q ) )- ( f[v[k]]+ ( v[k]*v[k] ) ) ) / ( 2*q-2*v[k] ); - while ( s <= z[k] ) - { - k--; - s = ( ( f[q]+ ( q*q ) )- ( f[v[k]]+ ( v[k]*v[k] ) ) ) / ( 2*q-2*v[k] ); - } - k++; - v[k] = q; - z[k] = s; - z[k+1] = INT_MAX; - } - - k = 0; - for ( int q = 0; q <= n-1; q++ ) - { - while ( z[k+1] < q ) - k++; - d[q] = ( ( q-v[k] ) * ( q-v[k] ) ) + f[v[k]]; - } - - delete [] v; - delete [] z; - return d; -} diff --git a/homer_nav_libs/src/Explorer/Explorer.h b/homer_nav_libs/src/Explorer/Explorer.h deleted file mode 100644 index 29a51ccf..00000000 --- a/homer_nav_libs/src/Explorer/Explorer.h +++ /dev/null @@ -1,355 +0,0 @@ -#ifndef EXPLORER_H -#define EXPLORER_H - -#include <vector> -#include <geometry_msgs/Pose.h> - -#include "GridMap.h" -#include "tools/tools.h" - -namespace ExplorerConstants -{ - static int8_t UNKNOWN; - static const int8_t NOT_SEEN_YET = -1; - static const double MAX_DISTANCE = DBL_MAX; - static const double MAX_COST = DBL_MAX; - static const int OBSTACLE = INT_MAX; -} - -/** - * @class Explorer - * @author Malte Knauf, Stephan Wirth, David Gossow (RX) - * @brief Path planning & exploration class - * - * Usage: - * - * - Call setOccupancyMap() to set the base map for path finding. - * - Set a start point by calling setStart() - * - * - For path planning: - * +Choose a target by calling setTarget() - * +To correct a target to the nearest approachable position, - * call getNearestAccessibleTarget - * +Call getPathTransformPath() - * - * -For exploration: - * +Call resetExploration() - * +Call getExplorationTransformPath() - * +The calculated target is the last element in the returned path - * - * - Call sampleWaypointsFromPath() to extract waypoints from a calculated path - * - * This class uses a couple of "maps" for computation and storing data: - * - * - m_OccupancyMap stores the occupancy probabilities in double values. A value of 100 means - * totally occupied, 0 totally free. - * - m_ObstacleDistanceMap stores in each cell the distance (one unit = one cell) to the nearest obstacle. - * This map is computed by an eucledian distance transformation from m_OccupancyMap. - * - m_FrontierMap is a bool map which has 1 in frontier cells and 0 in all others. A frontier - * is defined as a free cell that has one of its four direct neighbours in unknown space and is "safe" for - * the robot (m_ObstacleDistanceMap is used for that). - * - m_DrivingDistanceMap is a double map that stores for each cell the distance to m_Start. It is computed - * by a flood-fill (seed-fill) algorithm. The values are therefor only an approximation and not exact. - * m_DrivingDistanceMap is used to search the nearest frontier when requesting an auto target. - * - m_TargetMap is a double map that stores for each cell the distance to m_Target. It is computed - * like m_DrivingDistanceMap. This map is used as heuristic for the A*-Pathfinding algorithm. - * - m_NavigationMap is used to mark the cells that are touched by the A*-Pathfinding algorithm. - * - * - * The coordinate system and units that are used in this class are based on map cells. - * @see GridMap - * - */ -class Explorer -{ - - public: - - /** - * @brief Default constructor. - * @param minAllowedObstacleDistance,maxAllowedObstacleDistance Range of allowed distances to next obstacle [Pixels] - * @param minSafeObstacleDistance,maxSafeObstacleDistance Range of distances to next obstacle considered as safe [Pixels] - * @param safePathWeight Weight for safer path - */ - Explorer ( double minAllowedObstacleDistance, double maxAllowedObstacleDistance, - double minSafeObstacleDistance, double maxSafeObstacleDistance, - double safePathWeight, double frontierSafenessFactor=1.0, int unknownThreshold=50 ); - - /** - * @brief Destructor deletes all dynamically allocated memory used by the maps - */ - ~Explorer(); - - void setUnknownThreshold(int unknownTresh); - void setAllowedObstacleDistance ( double min, double max ); - void setSafeObstacleDistance ( double min, double max ); - void setFrontierSafenessFactor ( double frontierSafenessFactor ); - void setSafePathWeight ( double weight ); - /** - * @brief Copies and sets the occupancy map. - * @param width Width of the map - * @param height Height of the map - * @param origin Real-world pose of the cell (0,0) in the map - * @param data GridMap-data (occupancy probabilities: 0 = free, 100 = occupied) of size width * height - */ - void setOccupancyMap ( int width, int height, geometry_msgs::Pose origin, int8_t* mapData); - - /** only update occupied areas in current occupancy map */ - void updateObstacles ( int width, int height, geometry_msgs::Pose origin, int8_t* mapData ); - - /** - * @brief Sets the start position for the path finding algorithm. - * m_Start is set to the given value. - * If startPixel lies outside the map, m_Start remains untouched. - * @param startPixel Start position for path finding in pixel (map-) coordinates. - */ - void setStart ( Eigen::Vector2i start ); - - /** - * @brief Resets the internal state of the exploration mode. - * Sets m_DesiredDistance to 0, such that getExplorationTransformPath() triggers - * a frontier exploration if there is no prior call of setTarget(point, distance). - * Call this method once before every exploration. - */ - void resetExploration(); - - /** - * Sets the target position for path finding. m_Target is set to the given value. - * If endPixel lies outside of the map, m_Target remains untouched. - * computeTargetDistanceMap() is called at the end of this method. m - * @param targetPixel Target to reach from startPixel - */ - void setTarget ( Eigen::Vector2i targetPixel ); - - /** - * Sets the target region for path finding. m_ExplorationMap is set to the given region. - * If targetPixel lies outside of the map, the exploration map is set empty. - * @param targetPixel Center of the target region to reach from startPixel - * @param radius Radius of the target region in pixels - */ - void setTarget( Eigen::Vector2i targetPixel, int radius ); - - /** - * @brief find the nearest position to target that is approachble from the start position - */ - Eigen::Vector2i getNearestAccessibleTarget ( Eigen::Vector2i target ); - - /** - * @brief find the nearest position to target surpassing the minimum obstacle distance - */ - Eigen::Vector2i getNearestWalkablePoint ( Eigen::Vector2i target ); - - /** - * @brief Returns the map-coordinates of the nearest frontier to m_Start. - * Uses m_DrivingDistanceMap and m_ObstacleDistanceMap. If there is no frontier left, - * nextFrontier remains untouched. - * @param[out] nextFrontier Nearest frontier in map-coordinates. - * @return true if frontier found and stored in nextFrontier, false if no frontier found (nextFrontier - * remains untouched). - */ - bool getNearestFrontier ( Eigen::Vector2i& nextFrontier ); - - /** - * Computes the path from m_Start to m_Target with path transform. - * The result is returned. If the returned vector contains no elements, there is no path. - * @return vector with path points - */ - std::vector<Eigen::Vector2i> getPath( bool &success ); - - /** - * Computes the path from m_Start to the next frontier using exploration transform. - * The result is returned. If the returned vector contains no elements, there is no path. - * @return vector with path points - */ - std::vector<Eigen::Vector2i> getExplorationTransformPath( bool &success ); - - /** - * @brief Returns a version of the path that contains less vertices. - * @note The nearer the next obstacle, the more waypoints are created. - * @param path List of vertices to be simplified - * @param treshold[0..1] a lower threshold results in more waypoints (default:1.0) - * @return Vector of (sampled) waypoints. - */ - std::vector<Eigen::Vector2i> sampleWaypointsFromPath ( std::vector<Eigen::Vector2i> path, float threshold=1.0 ); - - /** - * Getters for the different transforms (see constructor for description) - */ - GridMap<int8_t>* getOccupancyMap(); - GridMap<double>* getObstacleTransform(); - GridMap<double>* getCostTransform(); - GridMap<bool>* getTargetMap(); - GridMap<double>* getDrivingDistanceTransform(); - GridMap<double>* getTargetDistanceTransform(); - GridMap<double>* getPathTransform(); - GridMap<double>* getExplorationTransform(); - - /** - * @return Start position - */ - Eigen::Vector2i getStart() const; - - /** - * @return Target position - */ - Eigen::Vector2i getTarget() const; - - private: - - /** @brief Delete the given map and set pointer to 0 */ - template <class T> - void releaseMap ( GridMap<T>*& map ) - { - if ( map ) - { - delete map; - map=0; - } - } - - /** @brief Delete and re-create given map */ - template <class T> - void resetMap ( GridMap<T>*& map ) - { - if ( !m_OccupancyMap ) - { - ROS_ERROR ( "Occupancy map is missing." ); - return; - } - releaseMap ( map ); - map = new GridMap<T> ( m_OccupancyMap->width(), m_OccupancyMap->height() ); - } - - /** - * @return true if the robot can stand on the given position without touching an obstacle, false otherwise - * @warning Call computeWalkableMaps before - */ - inline bool isWalkable ( int x, int y ) const - { - return ( ( m_OccupancyMap->getValue ( x, y ) < ExplorerConstants::UNKNOWN ) && - ( m_ObstacleTransform->getValue ( x, y ) > m_MinAllowedObstacleDistance ) ); - } - - /** - * @return true if point is approachable from the current start position, false otherwise. - * @warning m_OccupancyMap, m_ObstacleTransform and m_DrivingDistanceTransform have to be present! - * @warning Call computeApproachableMaps before - */ - inline bool isApproachable ( int x, int y ) const - { - return ( m_DrivingDistanceTransform->getValue ( x, y ) < ExplorerConstants::MAX_DISTANCE ); - } - - /** @brief Releases all memory of the member maps */ - void releaseMaps(); - - /** - * @brief Helper function for computeDistanceTransformation. - * @param f 1D-Array for distance transformation - * @param n Number of elements in f - * @return Distance transformation of f - */ - double* distanceTransform1D ( double *f, int n ); - - /** - * @brief Fills the given map from given start point with distance values to this point. - * The filling will only be performed on cells that are marked as free in m_OccupancyMap and - * that have an obstacle distance value between m_MinimumObstacleDistance and m_MaximumObstacleDistance. - * The map that is passed as argument will be fully overwritten by this function. - * @param map GridMap to fill - * @param start Start point for the fill algorithm - */ - void distanceFloodFill ( GridMap<double>* map, Eigen::Vector2i start ); - - /** @brief Compute map needed for path calculation */ - void computePathTransform(); - - /** @brief Compute map needed for exploration path calculation */ - void computeExplorationTransform(); - - /** @brief Compute the distances to the next obstacle with eucledian distance transform from m_OccupancyMap. */ - void computeObstacleTransform(); - - /** @brief Compute cost function based on obstacle transform */ - void computeCostTransform(); - - /** @brief Compute the frontiers between free and unknown space. Depends on OccupancyMap and ObstacleTransform. */ - void computeFrontierMap(); - - /** @brief Compute the target region (a circle of radius m_DesiredDistance around m_Target). */ - void computeRegionMap(); - - /** @brief Compute the target map, which is either a frontier map or a region map. */ - void computeTargetMap(); - - /** @brief Compute a map of driving distances from the start point */ - void computeDrivingDistanceTransform(); - - /** @brief Compute a map of driving distances to the target point */ - void computeTargetDistanceTransform(); - - /** @brief Compute maps needed for isWalkable */ - void computeWalkableMaps(); - - /** @brief Compute maps needed for isApproachable */ - void computeApproachableMaps(); - - /** @brief Start point for the way search algorithm. */ - Eigen::Vector2i m_Start; - - /** @brief Target for the way search algorithm */ - Eigen::Vector2i m_Target; - - /** @brief Desired distance to target in pixels */ - int m_DesiredDistance; - - /** @brief Occupancy map */ - GridMap<int8_t>* m_OccupancyMap; - - /** @see computeObstacleTransform */ - GridMap<double>* m_ObstacleTransform; - - /** @see computeCostTransform */ - GridMap<double>* m_CostTransform; - - /** @see computeTargetMap */ - GridMap<bool>* m_TargetMap; - - /** computeDrivingDistanceTransform */ - GridMap<double>* m_DrivingDistanceTransform; - - /** @see computeTargetDistanceTransform */ - GridMap<double>* m_TargetDistanceTransform; - - /** @see computePathTransform */ - GridMap<double>* m_PathTransform; - - /** @see computeExplorationTransform */ - GridMap<double>* m_ExplorationTransform; - - /** @see constructor */ - double m_MinAllowedObstacleDistance; - double m_MaxAllowedObstacleDistance; - - double m_MinSafeObstacleDistance; - double m_MaxSafeObstacleDistance; - - /** - * Weight for safer path - */ - double m_SafePathWeight; - - /** - * Factor for minObstacleDistance that determines if a frontier pixel is valid - */ - double m_FrontierSafenessFactor; - - /** - * Real-world pose of the point (0,0) in the map - */ - geometry_msgs::Pose m_Origin; - -}; - -#endif - diff --git a/homer_nav_libs/src/Explorer/GridMap.h b/homer_nav_libs/src/Explorer/GridMap.h deleted file mode 100644 index 64b3469e..00000000 --- a/homer_nav_libs/src/Explorer/GridMap.h +++ /dev/null @@ -1,575 +0,0 @@ -#ifndef GridMap_H -#define GridMap_H - -#include <float.h> -#include <iostream> -#include <sstream> - -#include "ros/ros.h" - -#include <Eigen/Geometry> - -#define GRIDMAP_SAFE_ACCESS - -/** - * @class GridMap - * @author Malte Knauf, Stephan Wirth, David Gossow (RX) - * @brief GridMap data structure. Implemeted as template class. The template type - * defines the data type of each map cell. - */ - -template<class DataT> -class GridMap -{ - - public: - - /// Initialize empty map - GridMap(); - - /** - * @param width Width of the map. - * @param height Height of the map. - * @param data Pointer to map data, must be of size width*height. - * @param copyData if true, the map data will be copied - * if false, GridMap takes ownership of the pointer - * @param cellSize physical size of each map cell [m] - * @param centerX,centerY center of the map in world coordinates - */ - GridMap ( int width, int height, DataT* data = 0, bool copyData = true, float cellSize = 1, float centerX = 0, float centerY = 0 ); - - /// Copy data from given region - GridMap ( int width, int height, DataT* data, Eigen::AlignedBox2i extractRegion ); - - /// Copy data from given map - GridMap<DataT> ( const GridMap<DataT>& other ) { m_Data=0; *this = other; } - - /// Copy data from given map - GridMap<DataT>& operator= ( const GridMap<DataT>& other ); - - ~GridMap(); - - /// Convert map coordinates to world coordinates - void mapToWorld ( int mapX, int mapY, float& worldX, float& worldY ); - - /// Convert world coordinates to map coordinates - void worldToMap ( float worldX, float worldY, int& mapX, int& mapY ); - - /// @brief set value at given position - inline void setValue ( int x, int y, DataT val ); - - /// @brief replace content with given value - void fill ( DataT val ); - - /// @brief Draw a filled polygon into the map (world coords) - void drawPolygon ( std::vector<Eigen::Vector2d> vertices, DataT value ); - - /// @brief Draw a filled circle into the map (world coords) - void drawCircle( Eigen::Vector2d center, float radius, DataT value ); - - /// @return Value at the given position. - inline DataT getValue ( int x, int y ) const; - - /// @return Pointer to given pixel - inline DataT* getDirectAccess ( int x, int y ); - - /// @return width in grid cells - int width() const { return m_Width; } - - /// @return height in grid cells - int height() const { return m_Height; } - - /// @return center of the map in world coordinates - Eigen::Vector2d center() const {return Eigen::Vector2d(m_CenterX,m_CenterY);} - - /// @return side length of one cell in mm - float cellSize() { return m_CellSize; } - - private: - - void drawLine ( DataT *data, int startX, int startY, int endX, int endY, DataT value ); - void fillPolygon ( DataT* data, int x, int y, char value ); - - int m_Width; - int m_Height; - int m_DataSize; - DataT* m_Data; - float m_CellSize; - float m_CenterX; - float m_CenterY; -}; - - -template<class DataT> -GridMap<DataT>::GridMap() -{ - m_Width = 0; - m_Height = 0; - m_DataSize = 0; - m_Data = 0; - m_CellSize = 0; - m_CenterX = 0; - m_CenterY = 0; -} - -template<class DataT> -GridMap<DataT>::GridMap ( int width, int height, DataT* data, bool copyData, float cellSize, float centerX, float centerY ) -{ - m_Width = width; - m_Height = height; - m_CellSize = cellSize; - m_DataSize = width * height; - m_CenterX = centerX; - m_CenterY = centerY; - m_Data = 0; - - if ( data ) - { - if ( copyData ) - { - m_Data = new DataT[m_DataSize]; - - for ( int i = 0; i < m_DataSize; i++ ) - { - m_Data[i] = data[i]; - } - } - else - { - m_Data = data; - } - } - else - { - m_Data = new DataT[m_DataSize]; - - for ( int i = 0; i < m_DataSize; i++ ) - { - m_Data[i] = 0; - } - } -} - -template<class DataT> -GridMap<DataT>::GridMap (int width, int height, DataT* data, Eigen::AlignedBox2i extractRegion ) -{ - m_Width = extractRegion.sizes().x(); - m_Height = extractRegion.sizes().y(); - m_DataSize = m_Width * m_Height; - m_Data = new DataT[m_DataSize]; - m_CellSize = 1; - m_CenterX = 0; - m_CenterY = 0; - - for ( int y = extractRegion.min().y(); y <= extractRegion.max().y(); y++ ) - { - int yOffset = m_Width * y; - - for ( int x = extractRegion.min().x(); x <= extractRegion.max().x(); x++ ) - { - int i = x + yOffset; - m_Data[i] = data[i]; - } - } -} - - -template<class DataT> -inline DataT* GridMap<DataT>::getDirectAccess ( int x, int y ) -{ -#ifdef GRIDMAP_SAFE_ACCESS - if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height ) - { - return &m_Data[y * m_Width + x]; - } - else - { - throw; - } -#else - return &m_Data[y * m_Width + x]; -#endif -} - - -template<class DataT> -GridMap<DataT>& GridMap<DataT>::operator= ( const GridMap<DataT>& other ) -{ - delete[] m_Data; - m_Width = other.m_Width; - m_Height = other.m_Height; - m_DataSize = other.m_DataSize; - m_Data = new DataT[m_DataSize]; - memcpy ( m_Data, other.m_Data, sizeof ( DataT ) *m_DataSize ); - m_CellSize = other.m_CellSize; - m_CenterX = other.m_CenterX; - m_CenterY = other.m_CenterY; - return *this; -} -/* TODO -template<class DataT> -GridMap<DataT>::GridMap ( ExtendedInStream& strm ) -{ - short version; - strm >> version; - strm >> m_Width; - strm >> m_Height; - strm >> m_CellSize; - strm >> m_CenterX; - strm >> m_CenterY; - m_DataSize = m_Width * m_Height; - m_Data = new DataT[m_DataSize]; - strm.get ( m_Data, m_DataSize ); -} -*/ -template<class DataT> -GridMap<DataT>::~GridMap() -{ - if ( m_Data ) - { - delete m_Data; - m_Data = 0; - } -} -/* -template<class DataT> -void GridMap<DataT>::storer ( ExtendedOutStream& strm ) const -{ - strm << short ( 12 ); - strm << m_Width; - strm << m_Height; - strm << m_CellSize; - strm << m_CenterX; - strm << m_CenterY; - strm.put ( m_Data, m_DataSize ); -} -*/ - -template<class DataT> -void GridMap<DataT>::mapToWorld ( int mapX, int mapY, float& worldX, float& worldY ) -{ - worldX = m_CenterX + m_CellSize * ( mapX - m_Width / 2 ); - worldY = m_CenterY + m_CellSize * ( mapY - m_Height / 2 ); -} - -template<class DataT> -void GridMap<DataT>::worldToMap ( float worldX, float worldY, int& mapX, int& mapY ) -{ - mapX = float ( m_Width ) / 2.0 - ( ( worldY - m_CenterY ) / m_CellSize + 0.5 ); - mapY = float ( m_Height ) / 2.0 - ( ( worldX - m_CenterX ) / m_CellSize + 0.5 ); - - if ( mapX < 0 || mapX >= m_Width || mapY < 0 || mapY >= m_Height ) - { - //ROS_WARN_STREAM ( "Index out of bounds: " << mapX << "," << mapY ); //TODO - - if ( mapX < 0 ) - { - mapX = 0; - } - - if ( mapX >= m_Width ) - { - mapX = m_Width - 1; - } - - if ( mapY < 0 ) - { - mapY = 0; - } - - if ( mapY >= m_Height ) - { - mapY = m_Height - 1; - } - } -} - - -template<class DataT> -inline void GridMap<DataT>::setValue ( int x, int y, DataT val ) -{ -#ifdef GRIDMAP_SAFE_ACCESS - if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height ) - { - m_Data[y * m_Width + x] = val; - } - else - { - throw; - } -#else - m_Data[y * m_Width + x] = val; -#endif -} - -template<class DataT> -inline DataT GridMap<DataT>::getValue ( int x, int y ) const -{ -#ifdef GRIDMAP_SAFE_ACCESS - if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height ) - { - return m_Data[y * m_Width + x]; - } - else - { - ROS_ERROR_STREAM( "Accessing map pixels " << x << "," << y << ": out of bounds (0,0," << m_Width-1 << "," << m_Height-1 << ")" ); //TODO - throw; - } -#else - return m_Data[y * m_Width + x]; -#endif -} - -template<class DataT> -void GridMap<DataT>::fill ( DataT val ) -{ - for ( int i = 0; i < m_DataSize; i++ ) - { - m_Data[i] = val; - } -} - -/* TODO do we need image representation? -template<class DataT> -puma2::ColorImageRGB8* GridMap<DataT>::getImage ( DataT specialValue, DataT clipRangeLow, DataT clipRangeHigh ) -{ - puma2::ColorImageRGB8* image = new puma2::ColorImageRGB8 ( m_Width, m_Height ); - double maxVal = 0.0001; - double minVal = 0.0; - - for ( int i = 0; i < m_DataSize; i++ ) - { - if ( ( m_Data[i] < minVal ) && ( m_Data[i] != specialValue ) ) - { - minVal = m_Data[i]; - } - - if ( ( m_Data[i] > maxVal ) && ( m_Data[i] != specialValue ) ) - { - maxVal = m_Data[i]; - } - } - - std::ostringstream stream; - - stream << " Min: " << minVal << "Max: " << maxVal; - stream << " ClipMin: " << double ( clipRangeLow ) << " ClipMax: " << double ( clipRangeHigh ); - ROS_DEBUG_STREAM ( stream.str() ); //TODO: was TRACE_SYSTEMINFO - - if ( maxVal > clipRangeHigh ) - { - maxVal = clipRangeHigh; - } - - if ( minVal < clipRangeLow ) - { - minVal = clipRangeLow; - } - - double range = maxVal - minVal; - - puma2::ColorImageRGB8::PixelType* imageData; - imageData = image->unsafeRowPointerArray() [0]; - - for ( int i = 0; i < m_DataSize; i++ ) - { - DataT currentValue = m_Data[i]; - - if ( currentValue == specialValue ) - { - imageData[i][0] = 40; - imageData[i][1] = 220; - imageData[i][2] = 120; - continue; - } - - if ( currentValue > clipRangeHigh ) - { - imageData[i][0] = 200; - imageData[i][1] = 200; - imageData[i][2] = 128; - continue; - } - - if ( currentValue < clipRangeLow ) - { - imageData[i][0] = 40; - imageData[i][1] = 40; - imageData[i][2] = 180; - continue; - } - - double valueDouble = ( ( double ) ( currentValue - minVal ) ) / range; - - unsigned char value = ( unsigned char ) ( valueDouble * 255 ); - - imageData[i][0] = value; - imageData[i][1] = value; - imageData[i][2] = value; - } - - return image; -} -*/ - - - -template<class DataT> -void GridMap<DataT>::drawCircle(Eigen::Vector2d center, float radius, DataT value ) -{ - int centerMapX,centerMapY; - worldToMap( center.x(), center.y(), centerMapX, centerMapY ); - - int radiusCells = radius / m_CellSize; - int radiusCells2 = radiusCells*radiusCells; - - Eigen::AlignedBox2i bBox( Eigen::Vector2i(centerMapX - radiusCells, centerMapY - radiusCells), Eigen::Vector2i(centerMapX + radiusCells, centerMapY + radiusCells) ); - Eigen::AlignedBox2i bBoxGrid( Eigen::Vector2i(0,0), Eigen::Vector2i(m_Width-1,m_Height-1) ); - bBox.clamp( bBoxGrid ); - - for ( int y = bBox.min().y(); y <= bBox.max().y(); y++ ) - { - for ( int x = bBox.min().x(); x <= bBox.max().x(); x++ ) - { - int xC = x-centerMapX; - int yC = y-centerMapY; - if ( xC*xC+yC*yC <= radiusCells2 ) - { - setValue( x, y, value ); - } - } - } -} - - -template<class DataT> -void GridMap<DataT>::drawPolygon (std::vector<Eigen::Vector2d> vertices, DataT value ) -{ - if ( vertices.size() == 0 ) - { - ROS_INFO( "No vertices given!" ); - return; - } - //make temp. map - DataT* data = new DataT[ m_DataSize ]; - for ( int i = 0; i < m_DataSize; i++ ) - { - data[i] = 0; - } - - //draw the lines surrounding the polygon - for ( unsigned int i = 0; i < vertices.size(); i++ ) - { - int i2 = ( i+1 ) % vertices.size(); - int startX,startY,endX,endY; - worldToMap( vertices[i].x(), vertices[i].y(), startX, startY ); - worldToMap( vertices[i2].x(), vertices[i2].y(), endX, endY ); - drawLine ( data, startX, startY, endX, endY, 1 ); - } - //claculate a point in the middle of the polygon - float midX = 0; - float midY = 0; - for ( unsigned int i = 0; i < vertices.size(); i++ ) - { - midX += vertices[i].x(); - midY += vertices[i].y(); - } - midX /= vertices.size(); - midY /= vertices.size(); - int midMapX,midMapY; - worldToMap( midX, midY, midMapX, midMapY ); - //fill polygon - fillPolygon ( data, midMapX, midMapY, 1 ); - - //copy polygon to map - for ( int i = 0; i < m_DataSize; i++ ) - { - if ( data[i] != 0 ) - { - m_Data[i] = value; - } - } - - delete[] data; -} - -template<class DataT> -void GridMap<DataT>::fillPolygon ( DataT* data, int x, int y, char value ) -{ - int index = x + m_Width * y; - if ( value != data[index] ) - { - data[index] = value; - fillPolygon ( data, x + 1, y, value ); - fillPolygon ( data, x - 1, y, value ); - fillPolygon ( data, x, y + 1, value ); - fillPolygon ( data, x, y - 1, value ); - } -} - - -template<class DataT> -void GridMap<DataT>::drawLine ( DataT *data, int startX, int startY, int endX, int endY, DataT value ) -{ - //bresenham algorithm - int x, y, t, dist, xerr, yerr, dx, dy, incx, incy; - // compute distances - dx = endX - startX; - dy = endY - startY; - - // compute increment - if ( dx < 0 ) - { - incx = -1; - dx = -dx; - } - else - { - incx = dx ? 1 : 0; - } - - if ( dy < 0 ) - { - incy = -1; - dy = -dy; - } - else - { - incy = dy ? 1 : 0; - } - - // which distance is greater? - dist = ( dx > dy ) ? dx : dy; - // initializing - x = startX; - y = startY; - xerr = dx; - yerr = dy; - - // compute cells - for ( t = 0; t < dist; t++ ) - { - data[x + m_Width * y] = value; - - xerr += dx; - yerr += dy; - if ( xerr > dist ) - { - xerr -= dist; - x += incx; - } - if ( yerr > dist ) - { - yerr -= dist; - y += incy; - } - } -} - - - -#endif - -#ifdef GRIDMAP_SAFE_ACCESS -#undef GRIDMAP_SAFE_ACCESS -#endif diff --git a/homer_nav_libs/src/Math/Box2D.h b/homer_nav_libs/src/Math/Box2D.h deleted file mode 100644 index 5979b68a..00000000 --- a/homer_nav_libs/src/Math/Box2D.h +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * Box2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: Box2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef Box2D_H -#define Box2D_H - -#include "Point2D.h" -#include <vector> - -/** - * @class Box2D - * @author David Gossow (RX) - * @brief Represents a box given by the upper-left and lower-right corner - */ -template<class T=float> -class Box2D -{ - - public: - - /** @brief Creates a box given by top-left (minX,minY) and lower-right (maxX,maxY) coordinates */ - Box2D(T minX=0, T minY=0, T maxX=0, T maxY=0); - - /** @brief The destructor */ - ~Box2D() {}; - - inline void setMinX(T value) { m_MinX=value; } - inline void setMaxX(T value) { m_MaxX=value; } - inline void setMinY(T value) { m_MinY=value; } - inline void setMaxY(T value) { m_MaxY=value; } - - inline T minX() const { return m_MinX; } - inline T maxX() const { return m_MaxX; } - inline T minY() const { return m_MinY; } - inline T maxY() const { return m_MaxY; } - - inline T width() const { return m_MaxX-m_MinX; } - inline T height() const { return m_MaxY-m_MinY; } - - std::vector< Point2D > vertices(); - - /** @brief Clip the box to fit into clipArea */ - void clip( Box2D<T> clipArea ); - - /** @return true if the given point is inside the box */ - bool contains( T x, T y ); - - /** @brief enlarge the box by 'size' units in all directions */ - void expand( T size ); - - /** @brief shrink the box by 'size' units in all directions */ - void shrink( T size ); - - /** @brief expand the box so that it contains the given point */ - void enclose( Point2D point ); - void enclose( T x, T y ); - - template<class OtherT> - void enclose( Box2D<OtherT> box ); - - Point2D centerPoint() - { - Point2D center; - center.setX(m_MinX + ( (m_MaxX - m_MinX) / 2 ) ); - center.setY(m_MinY + ( (m_MaxY - m_MinY) / 2 ) ); - return center; - } - - /** @brief area covered by the box */ - T area(); - - Box2D<T>& operator/= ( T div ) { m_MinX/=div; m_MinY/=div; m_MaxX/=div; m_MaxY/=div; return *this; } - Box2D<T>& operator*= ( T div ) { m_MinX*=div; m_MinY*=div; m_MaxX*=div; m_MaxY*=div; return *this; } - - private: - - T m_MinX; - T m_MaxX; - T m_MinY; - T m_MaxY; - -}; - -template<class T> -Box2D<T>::Box2D(T minX, T minY, T maxX, T maxY) -{ - m_MinX=minX; - m_MinY=minY; - m_MaxX=maxX; - m_MaxY=maxY; -} - -template<class T> -void Box2D<T>::clip( Box2D<T> clipArea ) -{ - if (m_MinX < clipArea.minX()) { m_MinX=clipArea.minX(); } - if (m_MinY < clipArea.minY()) { m_MinY=clipArea.minY(); } - if (m_MaxX > clipArea.maxX()) { m_MaxX=clipArea.maxX(); } - if (m_MaxY > clipArea.maxY()) { m_MaxY=clipArea.maxY(); } -} - -template<class T> -bool Box2D<T>::contains( T x, T y ) -{ - return ( (x>=m_MinX) && (x<=m_MaxX) && (y>=m_MinY) && (y<=m_MaxY) ); -} - -template<class T> - void Box2D<T>::expand( T size ) -{ - m_MinX-=size; - m_MaxX+=size; - m_MinY-=size; - m_MaxY+=size; -} - -template<class T> -void Box2D<T>::shrink( T size ) -{ - m_MinX+=size; - m_MaxX-=size; - m_MinY+=size; - m_MaxY-=size; -} - -template<class T> -T Box2D<T>::area() -{ - T width = m_MaxX - m_MinX; - T height = m_MaxY - m_MinY; - - T capacity = width * height; - - return (T) capacity; -} - -template<class T> -void Box2D<T>::enclose( Point2D point ) -{ - if ( m_MinX > point.x() ) { m_MinX=point.x(); } - if ( m_MinY > point.y() ) { m_MinY=point.y(); } - if ( m_MaxX < point.x() ) { m_MaxX=point.x(); } - if ( m_MaxY < point.y() ) { m_MaxY=point.y(); } -} - -template<class T> -void Box2D<T>::enclose( T x, T y ) -{ - if ( m_MinX > x ) { m_MinX=x; } - if ( m_MinY > y ) { m_MinY=y; } - if ( m_MaxX < x ) { m_MaxX=x; } - if ( m_MaxY < y ) { m_MaxY=y; } -} - -template<class T> -template<class OtherT> -void Box2D<T>::enclose( Box2D<OtherT> box ) -{ - enclose( box.minX(), box.minY() ); - enclose( box.maxX(), box.maxY() ); -} - - -template<class T> -std::vector< Point2D > Box2D<T>::vertices() -{ - std::vector<Point2D> myVertices(5); - myVertices[0]=Point2D( m_MinX-0.5, m_MinY-0.5 ); - myVertices[1]=Point2D( m_MinX-0.5, m_MaxY+0.5 ); - myVertices[2]=Point2D( m_MaxX+0.5, m_MaxY+0.5 ); - myVertices[3]=Point2D( m_MaxX+0.5, m_MinY-0.5 ); - myVertices[4]=myVertices[0]; - return myVertices; -} - - -#endif diff --git a/homer_nav_libs/src/Math/CMakeLists.txt b/homer_nav_libs/src/Math/CMakeLists.txt deleted file mode 100644 index b9f092ea..00000000 --- a/homer_nav_libs/src/Math/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(Math_SRC - Line2D.cpp - Transformation2D.cpp - Pose.cpp - Math.cpp - Point2D.cpp -) - -add_library(MappingMath ${Math_SRC}) diff --git a/homer_nav_libs/src/Math/Line2D.cpp b/homer_nav_libs/src/Math/Line2D.cpp deleted file mode 100644 index f5807c31..00000000 --- a/homer_nav_libs/src/Math/Line2D.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * Line2D.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Information on Code Review state: - * Author: SM; DevelTest: Date; Reviewer: Initials; Review: Date; State: NOK - * - * Additional information: - * $Id: Line2D.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#include "Line2D.h" -#include "vec2.h" - -#define THIS Line2D - -float THIS::gradient() const -{ - float gradient = 10000000.0; - if ( m_Vec[0] != 0.0 ) - { - gradient = m_Vec[1]/m_Vec[0]; - } - return gradient; -} - -std::vector< Point2D > THIS::vertices ( unsigned substeps ) -{ - unsigned steps = substeps+2; - std::vector<Point2D> myVertices ( steps ); - for ( unsigned i=0; i<steps; i++ ) - { - float t= float ( i ) / float ( steps-1 ); - myVertices[i] = m_Start + t*m_Vec; - } - return myVertices; -} - -Point2D THIS::getClosestPoint ( Point2D point ) const -{ - float t = ( point-m_Start ) * m_Vec; - t /= m_Vec * m_Vec; - if ( t > 1.0 ) - { - t = 1.0; - } - else if ( t < 0.0 ) - { - t = 0.0; - } - Point2D pointOnLine = m_Start + ( t * m_Vec ); - return pointOnLine; -} - -Point2D THIS::getIntersectionPoint ( Line2D line ) const -{ - Point2D intersecPoint; - double det1 = m_Vec.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * m_Vec.y(); - // lines are not parallel - if ( det1 != 0 ) - { - CVec2 startToStart = line.start() -m_Start; - // calculate intersection - double lambda = ( startToStart.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * startToStart.y() ) / det1; - intersecPoint = m_Start + lambda* m_Vec; - } - - return intersecPoint; -} - -float THIS::getIntersectionPointParameter ( Line2D line ) const -{ - double lambda = 0.0; - double det1 = m_Vec.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * m_Vec.y(); - // lines are not parallel - if ( det1 != 0 ) - { - CVec2 startToStart = line.start() -m_Start; - // calculate intersection - lambda = ( startToStart.x() * ( -line.vec().y() ) - ( -line.vec().x() ) * startToStart.y() ) / det1; - } - - return lambda; -} - -std::string THIS::toString() const -{ - std::ostringstream str; -// str << "Startpoint: " << m_Start.x() << " " << m_Start.y() << " Endpoint: " << end().x() << " " << end().y() << -// " Vector: " << m_Vec.x() << " " << m_Vec.y() << " "; - str << m_Start.x() << " " << m_Start.y() << std::endl << end().x() << " " << end().y() << std::endl; - return str.str(); -} - diff --git a/homer_nav_libs/src/Math/Line2D.h b/homer_nav_libs/src/Math/Line2D.h deleted file mode 100644 index e8c210bb..00000000 --- a/homer_nav_libs/src/Math/Line2D.h +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * Line2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Information on Code Review state: - * Author: SM; DevelTest: Date; Reviewer: Initials; Review: Date; State: NOK - * - * Additional information: - * $Id: Line2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef LINE2D_H -#define LINE2D_H - -#include "vec2.h" -#include "mat2.h" -#include "Point2D.h" -#include <vector> - -/** - * @class Line2D - * - * @author Susanne Maur - * - */ -class Line2D -{ - - public: - - /** - * Creates a new line. - * @param start Start point of the line. - * @param end End point of the line. - */ - inline Line2D ( Point2D start, Point2D end ) - { - m_Start = start; - m_Vec = end-m_Start; - } - - - /** - * Creates a new line. - * @param start Start point of the line. - * @param vec The vector from start to end point of the line. - */ - inline Line2D ( Point2D start, CVec2 vec ) - { - m_Start = start; - m_Vec = vec; - } - - /** - * Destructor does nothing. - */ - inline ~Line2D() {} - - /** - * Sets the start point of the line to a new value. - * @param start Start point of the line. - */ - inline void setStart ( const Point2D start ) - { - Point2D end = m_Start + m_Vec; - m_Start = start; - m_Vec = end-m_Start; - } - - /** - * Sets the end point of the line to a new value. - * @param end End point of the line. - */ - - inline void setEnd ( const Point2D end ) - { - m_Vec = end - m_Start; - } - - /** - * Returns the start point of the line. - * @return Start point of the line. - */ - inline Point2D start() const - { - return m_Start; - } - - /** - * Returns the end point of the line. - * @return End point of the line. - */ - inline Point2D end() const - { - return m_Start + m_Vec; - } - - /** - * Returns a vector from the start to the end of the line. - * @return Vector to the end point of the line. - */ - inline CVec2 vec() const - { - return m_Vec; - } - - inline bool operator== ( const Line2D& line ) const - { - return ( m_Start == line.start() && end() == line.end() ); - } - - /** - * Returns the gradient of the line. - * @return Gradient of the line. - */ - float gradient() const ; - - /** - * Returns the length of the line. - * @return Length of the line. - */ - inline float length() const { - return m_Vec.magnitude(); - } - - /** - * Returns the minimum euclidean distance of the given point to the line. - * @param point Point of which the distance to the line will be calculated. - * @return Distance of point to line. - */ - inline float distance ( Point2D point ) const - { - Point2D pointOnLine = getRootPoint ( point ); - return ( point - pointOnLine ).magnitude(); - } - - /** - * Rotates the line round the origin. - * @param angle The angle of rotation in radiants. - */ - inline void rotate ( float angle ) - { - CMat2 rotMat = CMat2 ( angle ); - m_Start = rotMat * m_Start; - m_Vec = rotMat * m_Vec; - } - - /** - * Returns the point of the line with the minimal distance to a given point. - * This algorithm may return a point which lies on the extension of the line and not on itself. - * See also: getClosestPoint. - * @param point Point to which the distance is calculated. - * @return Root point of the line. - */ - inline Point2D getRootPoint ( Point2D point ) const - { - float t = ( point-m_Start ) * m_Vec; - t /= m_Vec * m_Vec; - Point2D pointOnLine = m_Start + ( t * m_Vec ); - return pointOnLine; - } - - /** - * Returns the normal of the line. - * @return Normal of the line. - */ - inline CVec2 getNormal() const { - return m_Vec.getNormal()/m_Vec.magnitude(); - } - - /** - * Returns the point of the line with the minimal distance to a given point. - * This algorithm returns always a point which lies on the line. - * Therefor it is not always the root point. - * See also: getRootPoint. - * @param point Point to which the distance is calculated. - * @return Root point of the line. - */ - Point2D getClosestPoint ( Point2D point ) const; - - /** - * Returns the intersection point of this line with a second line. - * The intersection point is element of this line. - * @param line The line with which the intersection is calculated. - * @return Intersection point. - */ - Point2D getIntersectionPoint ( Line2D line ) const; - - /** - * Returns the parameter t which identifies the intersection point of this line with a second line. - * The intersection point is element of this line. - * @param line The line with which the intersection is calculated. - * @return Parameter t which identifies the intersection point on the line. - */ - float getIntersectionPointParameter ( Line2D line ) const; - - /** - * @return Vertices, e.g. for use in a VectorObject - * @param substeps number of linear interpolation steps between start and end - */ - std::vector< Point2D > vertices ( unsigned substeps=0 ); - - /** - * @overwrite - */ - std::string toString() const; - - private: - - /** - * Start point of the line. - */ - Point2D m_Start; - - /** - * Vector from the start to the end of the line. - */ - CVec2 m_Vec; -}; - -#endif diff --git a/homer_nav_libs/src/Math/Math.cpp b/homer_nav_libs/src/Math/Math.cpp deleted file mode 100644 index 3f31c5bf..00000000 --- a/homer_nav_libs/src/Math/Math.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * Math.cpp - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include <limits.h> -#include "Math.h" -#include <math.h> - -#include "vec2.h" - -#define THIS Math - -THIS::THIS() -{ -} - -THIS::~THIS() -{ -} - -float THIS::meanAngle( const std::vector<float>& angles ) -{ - //calculate vectors from angles - CVec2 vectorSum(0,0); - for ( unsigned i=0; i<angles.size(); i++ ) - { - vectorSum = vectorSum + CVec2( cos( angles[i] ), sin ( angles[i] ) ); - } - //return vectorSum.getAngle( CVec2(1,0) ); - if ( vectorSum.magnitude() == 0 ) { return 0; } - return atan2( vectorSum.y(), vectorSum.x() ); -} - - -float THIS::meanAngleWeighted( const std::vector< WeightedValue >& weightedAngles ) -{ - //calculate vectors from angles - CVec2 vectorSum(0,0); - for ( unsigned i=0; i<weightedAngles.size(); i++ ) - { - vectorSum = vectorSum + weightedAngles[i].weight * CVec2( cos( weightedAngles[i].value ), sin ( weightedAngles[i].value ) ); - } - //return vectorSum.getAngle( CVec2(1,0) ); - if ( vectorSum.magnitude() == 0 ) { return 0; } - return atan2( vectorSum.y(), vectorSum.x() ); -} - - -float THIS::angleVariance( float meanAngle, const std::vector<float>& angles ) -{ - float quadSum=0; - for( unsigned i=0; i < angles.size(); i++ ) - { - float turnAngle=minTurnAngle( angles[i], meanAngle ); - quadSum += turnAngle*turnAngle; - } - return quadSum / float ( angles.size() ); -} - - -float THIS::minTurnAngle( float angle1, float angle2 ) -{ -/* CVec2 vector1( cos( angle1 ), sin ( angle1 ) ); - CVec2 vector2( cos( angle2 ), sin ( angle2 ) ); - return vector1.getAngle( vector2 ); - */ - angle1 *= 180.0/M_PI; - angle2 *= 180.0/M_PI; - //if(angle1 < 0) angle1 += M_PI * 2; - //if(angle2 < 0) angle2 += M_PI * 2; - int diff= angle2 - angle1; - diff = (diff + 180) % 360 - 180; - - //float sign=1; - //if ( diff < 0 ) { sign=-1; } - //minimal turn angle: - //if the absolute difference is above 180°, calculate the difference in other direction - //if ( fabs(diff) > M_PI ) { - // diff = 2*M_PI - fabs(diff); - // diff *= sign; - //} - - float ret = static_cast<double>(diff) * M_PI/180.0; - return ret; -} - -Point2D THIS::center( std::vector<Point2D>& points ) -{ - double numPoints = double( points.size() ); - double sumX=0, sumY=0; - for( unsigned i=0; i < points.size(); i++ ) - { - sumX += points[i].x(); - sumY += points[i].y(); - } - return Point2D( sumX / numPoints, sumY / numPoints ); -} - - -double THIS::randomGauss(float variance) -{ - if (variance < 0) { - variance = -variance; - } - double x1, x2, w, y1; - do { - x1 = 2.0 * random01() - 1.0; - x2 = 2.0 * random01() - 1.0; - w = x1 * x1 + x2 * x2; - } while ( w >= 1.0 ); - - w = sqrt((-2.0 * log(w)) / w); - y1 = x1 * w; - // now y1 is uniformly distributed - return sqrt(variance) * y1; -} - -double THIS::random01(unsigned long init) -{ - static unsigned long n; - if (init > 0) { - n = init; - } - n = 1664525 * n + 1013904223; - // create double from unsigned long - return (double)(n/2) / (double)LONG_MAX; -} - -#undef THIS diff --git a/homer_nav_libs/src/Math/Math.h b/homer_nav_libs/src/Math/Math.h deleted file mode 100644 index bf00135a..00000000 --- a/homer_nav_libs/src/Math/Math.h +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Math.h - * - * (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#ifndef Math_H -#define Math_H - -#include <vector> -#include "Point2D.h" - -/** - * @class Math - * @brief Generic math and statistics functions - * @author David Gossow (RX) - */ -class Math -{ - public: - - struct WeightedValue - { - float value; - float weight; - }; - - static const double Pi = 3.14159265358979323846; - - /** @return mean value */ - template<class ContainerT> - static double mean ( const ContainerT& values ); - - /** @return variance of given values */ - template<class ContainerT> - static double variance ( const ContainerT& values ); - - /** @return mean angle of given values - * @note there are always two possible choices for the mean angle. This function returns the one with the smallest deviation - * @note Works for angles in [-Pi..Pi], negative angles are treated - */ - static float meanAngle ( const std::vector<float>& angles ); - - static float meanAngleWeighted ( const std::vector< WeightedValue >& weightedAngles ); - - /** @return variance for given mean */ - static float angleVariance ( float meanAngle, const std::vector<float>& angles ); - - /** @return minimal angle needed to turn from angle 1 to angle 2 [-Pi..Pi] */ - static float minTurnAngle ( float angle1, float angle2 ); - - static Point2D center ( std::vector<Point2D>& points ); - - static float deg2Rad ( float deg ) { return deg / 180.0*Pi; } - - static float rad2Deg ( float rad ) { return rad / Pi*180.0; } - - static double randomGauss ( float variance = 1.0 ); - - static double random01 ( unsigned long init = 0 ); - - /** @return ratio between one dimension seen under old viewangle and dimension under new viewangle*/ - static double angleToPercent ( double newAngle, double oldAngle ) { return tan ( ( Pi / 180.0 ) * newAngle / 2 ) / tan ( ( Pi / 180.0 ) * oldAngle / 2 ); }; - - /** @return angle under which the ratio between dimension seen under old viewangle and new viewangle equals percent*/ - static double percentToAngle ( double percent, double angle ) { return 2* atan ( tan ( ( Pi / 180.0 ) * angle / 2 ) * percent ) * ( 180 / Pi ); }; - - /** @return horizontal view angle corresponding to diagonal view angle and aspect ratio (e.g. 4.0/3.0)*/ - static double horizontalViewAngle ( double diagonalAngle, double aspectRatio ) { return verticalViewAngle ( diagonalAngle, 1.0 / aspectRatio ); }; - - /** @return vertical view angle corresponding to diagonal view angle and aspect ratio (e.g. 4.0/3.0)*/ - static double verticalViewAngle ( double diagonalAngle, double aspectRatio ) - { - return percentToAngle ( 1.0 / sqrt ( pow ( aspectRatio, 2 ) + 1.0 ), diagonalAngle ); - }; - - template<class ValueT> - static inline ValueT min ( ValueT a, ValueT b ) { return a < b ? a : b; } - - template<class ValueT> - static inline ValueT max ( ValueT a, ValueT b ) { return a > b ? a : b; } - - private: - - /** @brief The constructor */ - Math(); - - /** @brief The destructor */ - ~Math(); - -}; - -template<class ContainerT> -double Math::mean ( const ContainerT& values ) -{ - typename ContainerT::const_iterator it; - it = values.begin(); - double sum = 0; - while ( it != values.end() ) - { - sum += *it; - it++; - } - return sum / double ( values.size() ); -} - - -template<class ContainerT> -double Math::variance ( const ContainerT& values ) -{ - double mean = mean ( values ); - typename ContainerT::const_iterator it; - it = values.begin(); - double sum = 0; - while ( it != values.end() ) - { - double diff = *it - mean; - sum += diff * diff; - it++; - } - return sum / double ( values.size() ); -} - - -#endif diff --git a/homer_nav_libs/src/Math/Pixel.h b/homer_nav_libs/src/Math/Pixel.h deleted file mode 100644 index 026fd3a6..00000000 --- a/homer_nav_libs/src/Math/Pixel.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Pixel.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pixel.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef PIXEL_H -#define PIXEL_H - -#include "Point2D.h" -#include <vector> - -/** @class Pixel - * @brief Stores discrete pixel coordinates - * @author Stephan Wirth, David Gossow (RX) - */ -class Pixel { - - public: - - inline Pixel( int x = 0, int y = 0) { m_X = x; m_Y = y; }; - inline ~Pixel() {}; - - inline int x() const { return m_X; } - inline int y() const { return m_Y; } - - inline void setX( int x ) { m_X = x; } - inline void setY( int y ) { m_Y = y; } - - inline bool operator ==( Pixel& rhs ) { return ( m_X == rhs.m_X ) && ( m_Y == rhs.m_Y ); } - inline bool operator !=( Pixel& rhs ) { return ( m_X != rhs.m_X ) || ( m_Y != rhs.m_Y ); } - inline Pixel operator *( float rhs ) { return Pixel( m_X * rhs, m_Y * rhs ); } - inline Pixel operator /( float rhs ) { return Pixel( m_X / rhs, m_Y / rhs ); } - - inline Point2D toPoint2D() { return Point2D( m_X, m_Y ); } - - inline std::vector<Point2D> vertices() - { - std::vector<Point2D> result(5); - result[0]=Point2D( m_X-0.5, m_Y-0.5 ); - result[1]=Point2D( m_X+0.5, m_Y-0.5 ); - result[2]=Point2D( m_X+0.5, m_Y+0.5 ); - result[3]=Point2D( m_X-0.5, m_Y+0.5 ); - result[4]=result[0]; - return result; - } - - private: - - int m_X; - int m_Y; - -}; - - -#endif diff --git a/homer_nav_libs/src/Math/Point2D.cpp b/homer_nav_libs/src/Math/Point2D.cpp deleted file mode 100644 index c8ae09b7..00000000 --- a/homer_nav_libs/src/Math/Point2D.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Point2D.cpp - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Additional information: - * $Id: $ - *******************************************************************************/ - -#include "Point2D.h" - -#define THIS Point2D - -float THIS::getPolarAngle () const -{ - float angle = atan ( m_Y /m_X ); - if ( m_X < 0 ) - { - angle = - ( M_PI - angle ); - } - while ( angle >= M_PI ) - { - angle -= 2*M_PI; - } - while ( angle < -M_PI ) - { - angle += 2*M_PI; - } - return angle; -} - -#undef THIS diff --git a/homer_nav_libs/src/Math/Point2D.h b/homer_nav_libs/src/Math/Point2D.h deleted file mode 100644 index 94810ef9..00000000 --- a/homer_nav_libs/src/Math/Point2D.h +++ /dev/null @@ -1,312 +0,0 @@ -/******************************************************************************* - * Point2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Point2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#include "vec2.h" -#include <float.h> - -#ifndef POINT2D_H -#define POINT2D_H - -/** - * @class Point2D - * - * @author Susanne Maur - * - */ -class Point2D -{ - - public: - - /** - * Creates a new point in 2D with x- and y-coordinat set to zero. - */ - inline Point2D() - { - m_X = 0.0; - m_Y = 0.0; - } - - /** - * Creates a new point in 2D. - * @param x x-coordinate of the point. - * @param y y-coordinate of the point. - */ - inline Point2D ( double x, double y ) - { - m_X = x; - m_Y = y; - } - - - - /** - * Copy construcor - */ - inline Point2D (const Point2D& p){ - m_X = p.x(); - m_Y = p.y(); - } - - /** - * Creates a new point in 2D. - * @param v Vector form origin to the point. - */ - inline Point2D ( const CVec2& v ) - { - m_X = v[0]; - m_Y = v[1]; - } - - /** - * Destructor, does nothing. - */ - inline ~Point2D() - { - } - - /** - * Returns the x-coordinate of the point. - * @return the x-coordinate of the point. - */ - inline double x() const - { - return m_X; - } - - /** - * Returns the y-coordinate of the point. - * @return the y-coordinate of the point. - */ - inline double y() const - { - return m_Y; - } - - /** - * Sets the x- and y-coordinate of the point to new values. - * @param x the new value of the x coordinate. - * @param y the new value of the x coordinate. - */ - inline void set ( double x, double y ) - { - m_X = x; - m_Y = y; - } - - /** - * Sets the x-coordinate of the point to a new value. - * @param x the new value of the x coordinate. - */ - inline void setX ( double x ) - { - m_X = x; - } - - /** - * Sets the y-coordinate of the point to a new value. - * @param y the new value of the x coordinate. - */ - inline void setY ( double y ) - { - m_Y = y; - } - - /** - * Overloaded operators. - */ - - inline Point2D& operator= ( const Point2D& p) { - m_X = p.x(); - m_Y = p.y(); - return *this; - } - - inline Point2D operator+ ( const CVec2& v ) const - { - return Point2D ( m_X + v[0], m_Y + v[1] ); - } - - inline Point2D operator+ ( const Point2D& p ) const - { - return Point2D ( m_X + p.x(), m_Y + p.y() ); - } - - inline CVec2 operator- ( const Point2D& p ) const - { - return CVec2 ( m_X - p.x(), m_Y - p.y() ); - } - - inline Point2D operator- ( const CVec2& v ) const - { - return Point2D ( m_X - v[0], m_Y - v[1] ); - } - - inline Point2D operator* ( double scalar ) const - { - return Point2D ( m_X * scalar, m_Y * scalar ); - } - - inline Point2D operator/ ( double scalar ) const - { - return Point2D ( m_X / scalar, m_Y / scalar ); - } - - inline Point2D& operator+= ( const CVec2& v ) - { - m_X += v[0]; - m_Y += v[1]; - return ( *this ); - } - - inline Point2D& operator-= ( const CVec2& v ) - { - m_X -= v[0]; - m_Y -= v[1]; - return ( *this ); - } - - inline Point2D& operator*= ( double scalar ) - { - m_X *= scalar; - m_Y *= scalar; - return ( *this ); - } - - inline Point2D& operator/= ( double scalar ) - { - m_X /= scalar; - m_Y /= scalar; - return ( *this ); - } - - inline double operator [] ( unsigned int i ) const - { - return ( ( double* ) this ) [i]; - } - - inline double& operator [] ( unsigned int i ) - { - return ( ( double* ) this ) [i]; - } - - inline bool operator== ( const Point2D& point ) const - { - return ( fabs(m_X - point.x()) < 0.001 && fabs(m_Y - point.y()) < 0.001 ); - } - - inline bool operator!= ( const Point2D& point ) const - { - return !((*this)== point); - } - - /** - * Returns the distance to a given point. - * @param point The point to calculate the distance to. - * @return the distance between point the two points. - */ - inline double distance ( const Point2D& point ) const - { - return sqrt ( ( m_X-point.x() ) * ( m_X-point.x() ) + ( m_Y-point.y() ) * ( m_Y-point.y() ) ); - } - - /** - * Returns the distance to origin. - * @return the distance between point the two points. - */ - inline double distance ( ) const - { - return sqrt ( m_X * m_X + m_Y * m_Y ); - } - - /** - * Checks whether two points are equal. - * @param p The point to check equality. - * @return true if points are equal, false otherwise. - */ - inline bool equal ( const Point2D& point ) const - { - if ( ( *this - point ).magnitude() < 0.0001 ) - { - return true; - } - else - { - return false; - } - } - - /** - * Returns the vector which represents the point in 2D. - * @return vector which represents the point in 2D. - */ - inline CVec2 toVector() const - { - return CVec2 ( m_X, m_Y ); - } - - /** - * Returns the angle of the corresponding polar coordinates. - * @return polar angle. - */ - float getPolarAngle () const; - - /** - * Rotate by angle (in radiants) around center. - * @param center Center of rotation - * @param angle Angle in radiants - */ - inline void rotate ( const Point2D& center, float angle ) - { - double x0=m_X-center.m_X; - double y0=m_Y-center.m_Y; - double xRot = x0*cos ( angle ) - y0*sin ( angle ); - double yRot = x0*sin ( angle ) + y0*cos ( angle ); - m_X = xRot+center.m_X; - m_Y = yRot+center.m_Y; - } - - /** - * Rotate by angle (in radiants) around (0,0). - * @param angle Angle in radiants - */ - inline void rotate ( float angle ) - { - double xRot = m_X*cos ( angle ) - m_Y*sin ( angle ); - double yRot = m_X*sin ( angle ) + m_Y*cos ( angle ); - m_X = xRot; - m_Y = yRot; - } - - /** - * Returns the string representation of the point. - * @return string representation of the point. - */ - inline std::string toString() const - { - std::ostringstream str; - str << m_X << " " << m_Y; - return str.str(); - } - - /** @return "invalid" Point (used as end marker in vector drawings) **/ - static Point2D invalidPoint() { return Point2D( DBL_MAX, DBL_MAX ); } - - bool isValid() { return ( ( m_X != DBL_MAX ) || ( m_Y != DBL_MAX ) ); } - - protected: - - double m_X; - double m_Y; -}; - -#endif diff --git a/homer_nav_libs/src/Math/Pose.cpp b/homer_nav_libs/src/Math/Pose.cpp deleted file mode 100644 index 6011f280..00000000 --- a/homer_nav_libs/src/Math/Pose.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************* - * Pose.cpp - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pose.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include <cmath> - -#include "Pose.h" -#include "Transformation2D.h" - -using namespace std; - - -#define THIS Pose - -THIS::THIS(float x, float y, float theta) : Point2D(x, y) { - m_Theta = theta; -} - -THIS::THIS() { - m_Theta = 0.0; -} - -THIS::~THIS() { -} - -float THIS::theta() const { - return m_Theta; -} - -void THIS::setTheta(float theta) { - m_Theta = theta; -} - -Pose THIS::operator+ ( const Transformation2D& transformation ) const { - float x, y, theta; - x = m_X + transformation.x(); - y = m_Y + transformation.y(); - theta = m_Theta + transformation.theta(); - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Pose(x, y, theta); -} - -Pose THIS::operator- ( const Transformation2D& transformation ) const { - float x, y, theta; - x = m_X - transformation.x(); - y = m_Y - transformation.y(); - theta = m_Theta - transformation.theta(); - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Pose(x, y, theta); -} - -Transformation2D THIS::operator- ( const Pose& pose ) const { - float x, y, theta; - x = m_X - pose.x(); - y = m_Y - pose.y(); - - float s1, s2; - if (m_Theta > pose.theta()) { - s1 = -( 2 * M_PI - m_Theta + pose.theta()); - s2 = m_Theta - pose.theta(); - } else { - s1 = 2 * M_PI - pose.theta() + m_Theta; - s2 = -(pose.theta() - m_Theta); - } - if (fabs(s1) > fabs(s2)) { - theta = s2; - } else { - theta = s1; - } - while (theta >= M_PI) theta -= 2*M_PI; - while (theta < -M_PI) theta += 2*M_PI; - - return Transformation2D(x, y, theta); -} - -Pose THIS::interpolate(const Pose& referencePose, float t) const { - - float newX = m_X + t * (referencePose.x() - m_X); - float newY = m_Y + t * (referencePose.y() - m_Y); - - // Calculate mean angle by adding the vem_Thetaors in unit circle - float x1 = cosf(m_Theta); - float y1 = sinf(m_Theta); - float x2 = cosf(referencePose.theta()); - float y2 = sinf(referencePose.theta()); - float newTheta = atan2 (y1*(1-t)+y2*t, x1*(1-t)+x2*t); - - return Pose(newX, newY, newTheta); -} - -//THIS::THIS( ExtendedInStream& extStrm ) -//{ -// char version; -// extStrm >> version; -// extStrm >> m_X; -// extStrm >> m_Y; -// extStrm >> m_Theta; -//} - -//void THIS::storer( ExtendedOutStream& extStrm ) const -//{ -// char version=10; -// extStrm << version; -// extStrm << m_X; -// extStrm << m_Y; -// extStrm << m_Theta; -//} - diff --git a/homer_nav_libs/src/Math/Pose.h b/homer_nav_libs/src/Math/Pose.h deleted file mode 100644 index d0f6574c..00000000 --- a/homer_nav_libs/src/Math/Pose.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * Pose.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Pose.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef POSE_H -#define POSE_H - -#include "Point2D.h" -//#include "Architecture/Serializer/ExtendedOutStream.h" // TODO kann wahrscheinlich weg -//#include "Architecture/Serializer/ExtendedInStream.h" - -class Transformation2D; - -/** - * @class Pose - * - * @author Stephan Wirth, Susanne Maur (RX), David Gossow (RX) - * @brief Class to describe and hold a pose of the robot (x, y)-Position + Orientation - * in world-coordinates - */ -class Pose : public Point2D { - -public: - - /** - * Constructor which initializes the members with the given values. - * @param x x-position - * @param y y-position - * @param theta orientation in radiants - */ - Pose(float x, float y, float theta); - - /** - * Default constructor, initializes members to 0. - */ - Pose(); - - /** - * The destructor is empty. - */ - ~Pose(); - - float theta() const; - - void setTheta(float theta); - - Pose operator+ ( const Transformation2D& transformation ) const; - Pose operator- ( const Transformation2D& transformation ) const; - Transformation2D operator- ( const Pose& pose ) const; - - /** - * Interpolates between two poses and returns a pose which correlates with - * current pose + t * (reference pose - current pose) - * @param referencePose The second pose to interpolate between. - * @param t The factor of interpolation. - * @return Interpolated pose - */ - Pose interpolate(const Pose& referencePose, float t) const; - -// Pose( ExtendedInStream& extStrm ); - -// void storer( ExtendedOutStream& extStrm ) const; - -protected: - - float m_Theta; -}; - -#endif diff --git a/homer_nav_libs/src/Math/Transformation2D.cpp b/homer_nav_libs/src/Math/Transformation2D.cpp deleted file mode 100644 index 693c7a39..00000000 --- a/homer_nav_libs/src/Math/Transformation2D.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/******************************************************************************* - * Transformation2D.cpp - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Transformation2D.cpp 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#include "Transformation2D.h" - -#include <cmath> -#include <vector> -#include <iostream> -#include <sstream> -#include "vec2.h" // TODO das sieht nach baselib aus ggf. durch baselib ersetzen -#include "mat2.h" // TODO das sieht nach baselib aus ggf. durch baselib ersetzen -#include "Point2D.h" -#include "Line2D.h" - -#define THIS Transformation2D -#define BASE CVec2 - -THIS::Transformation2D() : BASE() -{ - m_Theta = 0.0; -} - -THIS::Transformation2D ( double x, double y, double theta ) : BASE ( x,y ) -{ - m_Theta = theta; -} - -THIS::Transformation2D ( const CVec2& vec, double theta ) : BASE ( vec ) -{ - m_Theta = theta; -} - -THIS::~Transformation2D() -{ -} - -void THIS::set ( double x, double y, double theta ) -{ - m_X = x; - m_Y = y; - m_Theta = theta; -} - -double THIS::theta() const -{ - return m_Theta; -} - -Transformation2D THIS::operator+ ( Transformation2D t ) const -{ - double theta = m_Theta + t.theta(); - // TODO comment only for scan matching test -// while ( theta >= M_PI ) theta -= 2*M_PI; -// while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X + t.x(), m_Y + t.y(), theta ); -} - -Transformation2D& THIS::operator+= ( Transformation2D t ) -{ - m_X += t.x(); - m_Y += t.y(); - m_Theta += t.theta(); - // TODO comment only for scan matching test -// while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; -// while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; - return ( *this ); -} - -Transformation2D THIS::operator- ( Transformation2D t ) const -{ - float s1, s2, theta; - if ( m_Theta > t.theta() ) - { - s1 = - ( 2 * M_PI - m_Theta + t.theta() ); - s2 = m_Theta - t.theta(); - } - else - { - s1 = 2 * M_PI - t.theta() + m_Theta; - s2 = - ( t.theta() - m_Theta ); - } - if ( fabs ( s1 ) > fabs ( s2 ) ) - { - theta = s2; - } - else - { - theta = s1; - } - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; -// double theta = m_Theta - t.theta(); -// while ( theta >= M_PI ) theta -= 2*M_PI; -// while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X - t.x(), m_Y - t.y(), theta ); -} - -Transformation2D& THIS::operator-= ( Transformation2D t ) -{ - m_X -= t.x(); - m_Y -= t.y(); - - float s1, s2, theta; - if ( m_Theta > t.theta() ) - { - s1 = - ( 2 * M_PI - m_Theta + t.theta() ); - s2 = m_Theta - t.theta(); - } - else - { - s1 = 2 * M_PI - t.theta() + m_Theta; - s2 = - ( t.theta() - m_Theta ); - } - if ( fabs ( s1 ) > fabs ( s2 ) ) - { - theta = s2; - } - else - { - theta = s1; - } - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; - m_Theta = theta; - - return ( *this ); - -// m_X -= t.x(); -// m_Y -= t.y(); -// m_Theta -= t.theta(); -// while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; -// while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; -// return ( *this ); -} - -Transformation2D THIS::operator* ( float factor ) const -{ - - double theta = m_Theta * factor; - while ( theta >= M_PI ) theta -= 2*M_PI; - while ( theta < -M_PI ) theta += 2*M_PI; - return Transformation2D ( m_X * factor, m_Y * factor, theta ); -} - -Transformation2D& THIS::operator*= ( float factor ) -{ - m_X *= factor; - m_Y *= factor; - m_Theta *= factor; - while ( m_Theta >= M_PI ) m_Theta -= 2*M_PI; - while ( m_Theta < -M_PI ) m_Theta += 2*M_PI; - return ( *this ); -} - - -Transformation2D THIS::operator/ ( float factor ) const -{ - double theta = m_Theta / factor; - return Transformation2D ( m_X / factor, m_Y / factor, theta ); -} - -Transformation2D& THIS::operator/= ( float factor ) -{ - m_X /= factor; - m_Y /= factor; - m_Theta /= factor; - return ( *this ); -} - -bool THIS::operator== ( Transformation2D t ) const -{ - if ( t.x() == m_X && t.y() == m_Y && t.theta() == m_Theta ) - { - return true; - } - else - { - return false; - } -} - -bool THIS::operator!= ( Transformation2D t ) const -{ - return ! ( ( *this ) ==t ); -} - -bool THIS::operator<= ( Transformation2D t ) const -{ - return ( this->magnitude() <= t.magnitude() ) && ( m_Theta <= t.theta() ); -} - -bool THIS::operator>= ( Transformation2D t ) const -{ - return ( this->magnitude() >= t.magnitude() ) && ( m_Theta >= t.theta() ); -} - -bool THIS::operator< ( Transformation2D t ) const -{ - return ( m_X < t.x() ) || ( m_Y < t.y() ) || ( ( m_Theta < t.theta() ) && ( *this <= t ) ); -} - -bool THIS::operator> ( Transformation2D t ) const -{ - return ( m_X > t.x() ) || ( m_Y > t.y() ) || ( ( m_Theta > t.theta() ) && ( *this >= t ) ); -} - -Transformation2D THIS::abs() const -{ - return Transformation2D ( std::abs ( m_X ), std::abs ( m_Y ), std::abs ( m_Theta ) ); -} - -Transformation2D THIS::inverse() const -{ - return ( *this ) * ( -1.0 ); -} - -Point2D THIS::transform ( const Point2D& point ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - Point2D transformedPoint = rotMat * ( point ); - transformedPoint += transVec; - return transformedPoint; -} - -std::vector<Point2D> THIS::transform ( const std::vector<Point2D>& points ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - std::vector<Point2D> transformedPoints; - std::vector<Point2D>::const_iterator iter = points.begin(); - while ( iter != points.end() ) - { - Point2D currPoint = rotMat * ( *iter ); - currPoint += transVec; - transformedPoints.push_back ( currPoint ); - iter++; - } - return transformedPoints; -} - -// // Reihenfolge rotation/translation vertauscht !!! -// Point2D THIS::transform ( Point2D point ) const -// { -// CMat2 rotMat = CMat2 ( m_Theta ); -// CVec2 transVec = CVec2 ( m_X, m_Y ); -// Point2D transformedPoint = point+transVec; -// transformedPoint = rotMat * point; -// return transformedPoint; -// } -// -// // Reihenfolge rotation/translation vertauscht !!! -// std::vector<Point2D> THIS::transform ( std::vector<Point2D> points ) const -// { -// CMat2 rotMat = CMat2 ( m_Theta ); -// CVec2 transVec = CVec2 ( m_X, m_Y ); -// std::vector<Point2D> transformedPoints; -// std::vector<Point2D>::const_iterator iter = points.begin(); -// while ( iter != points.end() ) -// { -// Point2D currPoint = ( *iter )+ transVec; -// currPoint = rotMat * currPoint; -// transformedPoints.push_back ( currPoint ); -// iter++; -// } -// return transformedPoints; -// } - -Line2D THIS::transform ( const Line2D& line ) const -{ - CMat2 rotMat = CMat2 ( m_Theta ); - CVec2 transVec = CVec2 ( m_X, m_Y ); - Line2D transformedLine = Line2D ( rotMat * line.start() + transVec, rotMat * line.end() + transVec ); - return transformedLine; -} - -std::vector<Line2D> THIS::transform ( const std::vector<Line2D>& lines ) const -{ - //CMat2 rotMat = CMat2 ( m_Theta ); - //CVec2 transVec = CVec2 ( m_X, m_Y ); - std::vector<Line2D> transformedLines; - std::vector<Line2D>::const_iterator iter = lines.begin(); - while ( iter != lines.end() ) - { - transformedLines.push_back ( transform(*iter) ); - iter++; - } - return transformedLines; -} - -std::string THIS::toString() const -{ - std::ostringstream str; - str << "deltaX: " << m_X << ", deltaY: " << m_Y << ", deltaTheta: " << m_Theta; - return str.str(); -} - - - -#undef THIS -#undef BASE - diff --git a/homer_nav_libs/src/Math/Transformation2D.h b/homer_nav_libs/src/Math/Transformation2D.h deleted file mode 100644 index 59a54d82..00000000 --- a/homer_nav_libs/src/Math/Transformation2D.h +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * Transformation2D.h - * - * (C) 2008 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * $Id: Transformation2D.h 44313 2011-04-06 22:46:28Z agas $ - *******************************************************************************/ - -#ifndef TRANSFORMATION2D_H -#define TRANSFORMATION2D_H - -#include <cmath> -#include <vector> -//#include "Workers/Math/Vec.h" -#include "Point2D.h" -#include "Line2D.h" - - -/** - * @class Transformation2D - * - * @author Susanne Maur - * - * @brief Class to describe a transformation of poses in 2D. - * This inplies a translation in x and y direction each and a rotation. - */ -class Transformation2D : public CVec2 -{ - - public: - - /** - * Constructor that initializes the members. - * @param x translation in x direction in m - * @param y translation in y direction in m - * @param theta rotation in radiants - */ - Transformation2D ( double x, double y, double theta ); - - /** - * Constructor that initializes the members. - * @param vec a vector which represents the translation in x and y direction - * @param theta rotation in radiants - */ - Transformation2D ( const CVec2& vec, double theta ); - - /** - * Default constructor sets all members to 0.0. - */ - Transformation2D(); - - /** - * Default destructor. - */ - ~Transformation2D(); - - /** - * Sets the values of transformation. - * @param x translation in x direction in mm - * @param y translation in y direction in mm - * @param theta rotation in radiants - */ - void set ( double x, double y, double theta ); - - /** - * Returns the rotation in radiants. - * @return rotation in radiants - */ - double theta() const; - - /** - * Adds two transformations. - */ - Transformation2D operator+ ( Transformation2D t ) const; - Transformation2D& operator+= ( Transformation2D t ); - - /** - * Subtracts two transformations. - */ - Transformation2D operator- ( Transformation2D t ) const; - Transformation2D& operator-= ( Transformation2D t ); - - /** - * Scales a transformation by a factor - */ - Transformation2D operator* ( float factor ) const; - Transformation2D& operator*= ( float factor ); - - /** - * Scales a transformation by a factor - */ - Transformation2D operator/ ( float factor ) const; - Transformation2D& operator/= ( float factor ); - - /** - * Test equality of transformations. - */ - bool operator== ( Transformation2D t ) const; - bool operator!= ( Transformation2D t ) const; - - /** - * Compare transformations. - * (attention: algebraic signs are taken into account, if necessary use fabs()) - */ - bool operator<= ( Transformation2D t ) const; - bool operator>= ( Transformation2D t ) const; - bool operator< ( Transformation2D t ) const; - bool operator> ( Transformation2D t ) const; - - /** - * Applies abs() on every attribute. - */ - Transformation2D abs() const; - - /** - * Inverts the transformation, scales every attribute with -1. - */ - Transformation2D inverse() const; - - /** - * Transformes points by first rotation, then translating. - */ - Point2D transform ( const Point2D& point ) const; - std::vector<Point2D> transform ( const std::vector<Point2D>& points ) const; - - /** - * Transformes lines by first rotation, then translating. - */ - Line2D transform ( const Line2D& line ) const; - std::vector<Line2D> transform ( const std::vector<Line2D>& lines ) const; - - /** - * Returns the string representation of the transformation. - * @return string representation of the transformation. - */ - std::string toString() const; - - private: - double m_Theta; -}; - -#endif - diff --git a/homer_nav_libs/src/Math/mat2.h b/homer_nav_libs/src/Math/mat2.h deleted file mode 100644 index 254e8dc6..00000000 --- a/homer_nav_libs/src/Math/mat2.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * mat2.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#ifndef MAT2_H -#define MAT2_H - -#include <math.h> -#include "Point2D.h" -#include "vec2.h" - -class CMat2 -{ - public: - CMat2(); - CMat2(float rot); - ~CMat2(); - - CMat2 operator *(const CMat2 &mat) const; - - CVec2 operator *(const CVec2& v) const; - - Point2D operator *(const Point2D& p) const; - - float& operator [] (unsigned int position) { - return fMatrix[position]; - } - - CMat2 operator +(const CMat2 rhs) const { - CMat2 newMatrix; - for (unsigned int i = 0; i < 4; i++) { - newMatrix[i] = valueAt(i) + rhs.valueAt(i); - } - return newMatrix; - } - - CMat2 operator -(const CMat2 rhs) const { - CMat2 newMatrix; - for (unsigned int i = 0; i < 4; i++) { - newMatrix[i] = valueAt(i) - rhs.valueAt(i); - } - return newMatrix; - } - - float valueAt(unsigned int position) const{ - return fMatrix[position]; - } - - union - { - float fMatrix[4]; - float m[2][2]; - struct - { - float xx, xy; - float yx, yy; - }; - }; - - void transpose(); - void loadIdentity(); - - void makeRotation(float fA); - - bool invert(); -}; - - - -#include "mat2_inl.h" - -#endif diff --git a/homer_nav_libs/src/Math/mat2_inl.h b/homer_nav_libs/src/Math/mat2_inl.h deleted file mode 100644 index e3f77e16..00000000 --- a/homer_nav_libs/src/Math/mat2_inl.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * mat2_inl.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus - *******************************************************************************/ - -#include <assert.h> - -inline CMat2::CMat2(){ - for (unsigned int i = 0; i < 4; i++) { - fMatrix[i] = 0; - } -} - -inline CMat2::~CMat2() -{} - -inline CMat2::CMat2(float rot) -{ - makeRotation(rot); -} - -inline CMat2 CMat2::operator * ( const CMat2 & mat ) const -{ - CMat2 retValue; - for (unsigned int line = 0; line < 2; line++) { - for (unsigned int column = 0; column < 2; column++) { - retValue[line*2 + column] = valueAt(line*2 + column) + mat.valueAt(column*2 + line); - } - } - return retValue; -} - -inline CVec2 CMat2::operator * ( const CVec2& v ) const -{ - return CVec2(xx*v[0] + xy*v[1],yx*v[0] + yy*v[1]); -} - -inline Point2D CMat2::operator * ( const Point2D& p ) const -{ - return Point2D(xx*p.x() + xy*p.y(), yx*p.x() + yy*p.y()); -} - -inline void CMat2::transpose() -{ - float t=xy; - xy=yx; - yx=t; -} - -inline void CMat2::loadIdentity() -{ - xx=1.0f; xy=0.0f; - yx=0.0f; yy=1.0f; -} - -inline void CMat2::makeRotation ( float fA ) -{ - xx=yy=cosf(fA); - yx=sinf(fA); - xy=-yx; -} - -inline bool CMat2::invert() -{ - CMat2 tmp; - float det = fMatrix[0]*fMatrix[3] - fMatrix[1]*fMatrix[2]; - - if(fabs(det) < 0.001f) return false; - - det = 1.0 / det; - tmp.fMatrix[0] = fMatrix[3]*det; - tmp.fMatrix[1] = -fMatrix[1]*det; - tmp.fMatrix[2] = -fMatrix[2]*det; - tmp.fMatrix[3] = fMatrix[0]*det; - - (*this)=tmp; - return true; -} - - - - diff --git a/homer_nav_libs/src/Math/vec2.h b/homer_nav_libs/src/Math/vec2.h deleted file mode 100644 index 39a72c8e..00000000 --- a/homer_nav_libs/src/Math/vec2.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * vec2.h - * - * (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de> - * Universitaet Koblenz-Landau - * - * Author: Frank Neuhaus, Susanne Maur - *******************************************************************************/ - -#include <iostream> -#include <sstream> - -#ifndef VEC2_H -#define VEC2_H - -#include <math.h> - -class CVec2 -{ - public: - - inline CVec2() - { - m_X = 0; m_Y = 0; - } - - inline CVec2 ( double x, double y ) - { - m_X=x; m_Y=y; - } - - inline CVec2 ( const CVec2& vec ) - { - m_X=vec.x(); m_Y=vec.y(); - } - - inline CVec2 operator+ ( const CVec2& vVector ) const - { - return CVec2 ( vVector[0] + m_X, vVector[1] + m_Y ); - }; - - inline CVec2 operator- ( const CVec2& vVector ) const - { - return CVec2 ( m_X - vVector[0], m_Y - vVector[1] ); - }; - - inline CVec2 operator- ( ) const - { - return CVec2 ( - m_X, - m_Y ); - }; - - inline CVec2 operator* ( double num ) const - { - return CVec2 ( m_X * num, m_Y * num ); - }; - - inline double operator* ( const CVec2& vVector ) const - { - return m_X*vVector[0]+m_Y*vVector[1]; - } - - inline CVec2 operator/ ( double num ) const - { - return CVec2 ( m_X / num, m_Y / num ); - } - - inline void set ( double fx, double fy ) - { - m_X=fx; m_Y=fy; - } - - inline double x() const - { - return m_X; - } - - inline double y() const - { - return m_Y; - } - - inline double magnitude() const - { - double sumOfSquares = m_X*m_X + m_Y*m_Y; - return sqrt ( sumOfSquares ); - } - - inline double operator [] ( unsigned int i ) const - { - return ( ( double* ) this ) [i]; - } - - inline double& operator [] ( unsigned int i ) - { - return ( ( double* ) this ) [i]; - } - - inline CVec2& operator/= ( double num ) - { - double inv=1.0f/num; - m_X*=inv; - m_Y*=inv; - return ( *this ); - } - - inline CVec2& operator*= ( double num ) - { - m_X*=num; - m_Y*=num; - return ( *this ); - } - - inline CVec2& normalize() - { - return ( *this/=magnitude() ); - } - - inline CVec2& makePerp() - { - double xn=m_X; - m_X=-m_Y; - m_Y=xn; - return *this; - } - - inline CVec2 getNormal() const - { - return CVec2 ( m_Y, -m_X ); //? - } - - inline CVec2 getNormalized() const - { - return ( *this ) /magnitude(); - } - - inline double sqr() const - { - return ( *this ) * ( *this ); - } - - inline double dot ( const CVec2& vec ) const - { - return ( m_X*vec[0] ) + ( m_Y*vec[1] ); - } - - inline double getAngle ( const CVec2& vec ) const - { - return acos ( dot ( vec ) / ( magnitude() *vec.magnitude() ) ); - } - - /// @param angle Rotation angle in radiants - inline CVec2 rotate ( float angle ) const - { - double xRot = m_X*cos ( angle ) - m_Y*sin ( angle ); - double yRot = m_X*sin ( angle ) + m_Y*cos ( angle ); - return CVec2 ( xRot, yRot ); - } - - inline bool equal ( CVec2 vec ) const - { - return ( m_X==vec.x() && m_Y==vec.y() ); - } - - /** - * Returns the string representation of the vector. - * @return string representation of the point. - */ - inline std::string toString() const - { - std::ostringstream str; - str << m_X << " " << m_Y; - return str.str(); - } - - protected: - double m_X, m_Y; -}; - -inline CVec2 operator* ( double f, const CVec2& v ) -{ - return v*f; -} - -inline CVec2 normalize ( const CVec2& v ) -{ - return v/v.magnitude(); -} - -#endif diff --git a/homer_nav_libs/src/SpeedControl/CMakeLists.txt b/homer_nav_libs/src/SpeedControl/CMakeLists.txt deleted file mode 100644 index 154b60eb..00000000 --- a/homer_nav_libs/src/SpeedControl/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(SpeedControl_SRC - SpeedControl.cpp -) - -add_library(SpeedControl ${SpeedControl_SRC}) diff --git a/homer_nav_libs/src/SpeedControl/SpeedControl.cpp b/homer_nav_libs/src/SpeedControl/SpeedControl.cpp deleted file mode 100644 index c33eff33..00000000 --- a/homer_nav_libs/src/SpeedControl/SpeedControl.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include <cmath> -#include <iostream> - -#include <ros/ros.h> -#include "SpeedControl.h" -#include "tools/loadRosConfig.h" - -using namespace std; - -// Robot dimensions in m -// -// -// /-------------\ <-- MAX_X -// | x | -// | | | -// | | | -// | y----- | -// | | -// | ROBOT | -// | | -// \-------------/ <-- MIN_X -// ^ ^ -// | | -// MAX_Y MIN_Y -// -float ROBOT_MIN_X = -0.45; -float ROBOT_MAX_X = 0.30; -float ROBOT_MIN_Y = -0.27; -float ROBOT_MAX_Y = 0.27; - - -namespace { - Eigen::AlignedBox2f InnerDangerZone, - OuterDangerZone; - float InnerDangerZoneFactor, - OuterDangerZoneFactor; - - inline Eigen::AlignedBox2f loadRect(const string& path) - { - pair<float, float> pX, pY; - loadConfigValue(path + "/x_min", pX.first); - loadConfigValue(path + "/x_max", pX.second); - loadConfigValue(path + "/y_min", pY.first); - loadConfigValue(path + "/y_max", pY.second); - - Eigen::Vector2f first(pX.first, pY.first), second(pX.second, pY.second); - return Eigen::AlignedBox2f(first, second); - } -} - -void SpeedControl::loadDimensions() -{ - InnerDangerZone = loadRect("/homer_navigation/speed_control/inner_danger_zone"); - InnerDangerZoneFactor; - loadConfigValue("/homer_navigation/speed_control/inner_danger_zone/speed_factor", InnerDangerZoneFactor); - OuterDangerZone = loadRect("/homer_navigation/speed_control/inner_danger_zone"); - OuterDangerZoneFactor; - loadConfigValue("/homer_navigation/speed_control/outer_danger_zone/speed_factor", OuterDangerZoneFactor); - if(!OuterDangerZone.contains(InnerDangerZone)) - ROS_WARN_STREAM("InnerDangerZone is not contained in OuterDangerZone"); -} - -float SpeedControl::getSpeedFactor(const vector<geometry_msgs::Point>& points, float minVal, float maxVal ) -{ - float minFactor = 1.0; - for (unsigned i = 0; i < points.size(); i++) - { - Eigen::Vector2f point(points[i].x, points[i].y); - if(InnerDangerZone.contains(point)) - { - minFactor = InnerDangerZoneFactor; - break; - } - if(OuterDangerZone.contains(point)) - minFactor = OuterDangerZoneFactor; - } - minFactor = sqrt(minFactor); - float range = maxVal - minVal; - minFactor = minVal + range*minFactor; - return minFactor; -} - -float SpeedControl::getMaxMoveDistance(vector<geometry_msgs::Point> points) -{ - float minDistance = 4; // distance in m to nearest obstacle in front - for (unsigned int i = 0; i < points.size(); i++) - { - if(points[i].y > ROBOT_MIN_Y && points[i].y < ROBOT_MAX_Y && points[i].x > ROBOT_MAX_X) - { - float distance = sqrt((points[i].x * points[i].x) + (points[i].y * points[i].y)); - if (distance < minDistance) - { - minDistance = distance; - } - } - } - float maxMoveDist = minDistance - ROBOT_MAX_X; - if (maxMoveDist < 0) { - maxMoveDist = 0.0; - } - return maxMoveDist; -} - -float SpeedControl::getMaxMoveDistance(std::vector< Eigen::Vector3d >* kinectData, float minObstacleHeight, float minObstacleFromRobotDistance, float maxObstacleFromRobotDistance) -{ - // Check for obstacles in Kinect image: Look for closest point - - float minDistance = 4; // distance to nearest obstacle in front - - for(int i=0;i<kinectData->size();++i) - { - Eigen::Vector2d p = Eigen::Vector2d(kinectData->at(i).x(), kinectData->at(i).y()); - if(!std::isnan(p.x())) - { - // Filter point cloud - if(p.x() > minObstacleFromRobotDistance && p.x() < maxObstacleFromRobotDistance && kinectData->at(i).z() > minObstacleHeight) - { - // Check for collisions outside of robot - if(p.y() > ROBOT_MIN_Y && p.y() < ROBOT_MAX_Y && p.x() > ROBOT_MAX_X) - { - float distance = sqrt((p.x() * p.x()) + (p.y() * p.y())); - if (distance < minDistance) - { - minDistance = distance; - } - } - } - } - } - - float maxMoveDist = minDistance - ROBOT_MAX_X; - if (maxMoveDist < 0) { - maxMoveDist = 0.0; - } - return maxMoveDist; -} - -float SpeedControl::getTurnSpeedFactor( float speedFactor, float turnAngle, float minVal, float maxVal ) -{ - //turn faster for larger angles - float angleDependentFactor = sqrt( fabs(turnAngle) / M_PI ); - angleDependentFactor = minVal + angleDependentFactor*(maxVal-minVal); - return sqrt( speedFactor * angleDependentFactor ); -} - -float SpeedControl::getMinTurnAngle(std::vector<geometry_msgs::Point> laserData, float minAngle, float maxAngle, float minDistance, float maxDistance) -{ - float turn_factor = 1.0; - for (unsigned int i = 0; i < laserData.size(); i++) - { - if(laserData[i].y > ROBOT_MIN_Y && laserData[i].y < ROBOT_MAX_Y && laserData[i].x > ROBOT_MAX_X) - { - float distance = sqrt((laserData[i].x * laserData[i].x) + (laserData[i].y * laserData[i].y)); - if (distance < minDistance + ROBOT_MAX_X) - { - turn_factor = 0.0; - } - else if(distance > maxDistance + ROBOT_MAX_X) - { - turn_factor = 1.0; - } - else - { - turn_factor = (distance - minDistance)/maxDistance; - } - } - } - float range = maxAngle - minAngle; - return minAngle + turn_factor * range; -} - -SpeedControl::SpeedControl() { -} - -SpeedControl::~SpeedControl() { -} - diff --git a/homer_nav_libs/src/SpeedControl/SpeedControl.h b/homer_nav_libs/src/SpeedControl/SpeedControl.h deleted file mode 100644 index 7bef0e9a..00000000 --- a/homer_nav_libs/src/SpeedControl/SpeedControl.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef SPEEDCONTROL_H -#define SPEEDCONTROL_H - -#include <vector> -#include <Eigen/Geometry> -#include <geometry_msgs/Point.h> - -/** - * @class SpeedControl - * @author Malte Knauf, Stephan Wirth - * @brief Class for computing a speed factor with respect to a given laser measurement. - */ -class SpeedControl { - - public: - - /** - * @brief Loads robot and safety zone dimensions config values - */ - static void loadDimensions(); - - /** - * Calculates the speed factor for the robot. If a measured obstacle lies in the "danger zone" - * that is defined in SpeedControl.cpp, the speed factor will be below maxVal. The nearer the obstacle, - * the smaller the speed factor. - * @param laserData Laser measurement - * @param minVal,maxVal range of return values - * @return Speed factor, value between minVal and maxVal. The higher the speed factor, the safer is it to drive fast. - */ - static float getSpeedFactor(const std::vector<geometry_msgs::Point>& points, float minVal=0.2, float maxVal=1.0); - - /** - * Calculates the maximum distance the robot can move without touching an obstacle. - * @param laserPoints Current laser measurement transformed to (valid) points in map frame - * @param laserConf The configuration of the LRF that took the measurement - * @return maximum distance (m) the robot can move based on the given laserscan. - */ - static float getMaxMoveDistance(std::vector<geometry_msgs::Point> laserData); - - static float getMaxMoveDistance(std::vector< Eigen::Vector3d >* kinectData, float minObstacleHeight, float minObstacleFromRobotDistance, float maxObstacleFromRobotDistance); - - /// @return if the angle is larger, the turn speed factor will be higher - static float getTurnSpeedFactor( float speedFactor, float turnAngle, float minVal, float maxVal ); - - /** - * Calculates the minimum angle between the robot's orientation and the next waypoint which is necessary - * to trigger a rotation instead of a straight line - * @brief getMinTurnAngle - * @param laserData - * @param minAngle - * @param maxAngle - * @return - */ - static float getMinTurnAngle(std::vector<geometry_msgs::Point> laserData, float minAngle, float maxAngle, - float minDistance, float maxDistance); - - private: - - /** - * Constructor is empty and private because this class will never be instanciated. - */ - SpeedControl(); - - /** - * Destructor is empty. - */ - ~SpeedControl(); - -}; -#endif - diff --git a/homer_nav_libs/src/tools/loadRosConfig.h b/homer_nav_libs/src/tools/loadRosConfig.h deleted file mode 100644 index a51a99ed..00000000 --- a/homer_nav_libs/src/tools/loadRosConfig.h +++ /dev/null @@ -1,46 +0,0 @@ - -#ifndef LOAD_ROS_CONFIG_H -#define LOAD_ROS_CONFIG_H - -#include <ros/ros.h> -#include <string> - -template <typename T> -inline bool loadConfigValue(std::string valueName, T &variable, T default_variable = T() ) -{ - if(ros::param::has(valueName)) - { - ros::param::get(valueName, variable); - ROS_INFO_STREAM(valueName << ": " << variable); - return true; - } - else - { - ROS_WARN_STREAM("No Parameter: " << valueName << ". Defaulting to "<<default_variable<<"."); - variable = default_variable; - return false; - } -} - -template <typename T> -inline bool loadConfigValue(std::string valueName, std::vector<T> &variable) -{ - if(ros::param::has(valueName)) - { - ros::param::get(valueName, variable); - ROS_INFO_STREAM(valueName << ":"); - - for (int i = 0; i < variable.size(); ++i) - ROS_INFO_STREAM("Value "<< i << " :" << variable[i]); - - return true; - } - else - { - ROS_WARN_STREAM("No Parameter: " << valueName << ". Defaulting to empty vector."); - variable.clear(); - return false; - } -} - -#endif diff --git a/homer_nav_libs/src/tools/tools.h b/homer_nav_libs/src/tools/tools.h deleted file mode 100644 index e1067450..00000000 --- a/homer_nav_libs/src/tools/tools.h +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef TOOLS_H -#define TOOLS_H - -#include <Eigen/Geometry> -#include <geometry_msgs/Point.h> -#include <geometry_msgs/Pose.h> -#include <tf/transform_listener.h> -#include <ros/ros.h> - -/** - * @author Malte Knauf (2014) - * Convenience functions that are often used in the mapping and navigation process - */ -namespace map_tools -{ - - /** - * @brief Converts a point p in world frame /map to the respective cell position in the map - * @param p Point in world frame - * @param origin Origin of the map - * @param resolution Resolution of the map - * @return Cell position of the point - */ - Eigen::Vector2i toMapCoords(geometry_msgs::Point p, geometry_msgs::Pose origin, float resolution) - { - int x_idx = (p.x - origin.position.x)/resolution + 0.51; - int y_idx = (p.y - origin.position.y)/resolution + 0.51; - Eigen::Vector2i ret(x_idx, y_idx); - return ret; - } - - /** - * @brief Converts the cell position of a point to its respective position in the world frame - * @param idx Cell position of the point - * @param origin Origin of the map - * @param resolution Resolution of the map - * @return Point in world frame - */ - geometry_msgs::Point fromMapCoords(Eigen::Vector2i idx, geometry_msgs::Pose origin, float resolution) - { - geometry_msgs::Point ret; - ret.x = origin.position.x + (idx.x() - 0.5) * resolution; - ret.y = origin.position.y + (idx.y() - 0.5) * resolution; - return ret; - } - - /** - * @brief Converts the QT pixel position of a point to its respective position in the world frame - * @param idx Cell position of the point - * @param origin Origin of the map - * @param resolution Resolution of the map - * @return Point in world frame - */ - geometry_msgs::Point qtFromMapCoords(Eigen::Vector2i idx, geometry_msgs::Pose origin, float resolution) - { - geometry_msgs::Point ret; - ret.x = -(origin.position.x + idx.y()) * resolution; - ret.y = -(origin.position.y + idx.x()) * resolution; - return ret; - } - - /** - * @brief map_index returns for a given point in the map real-world frame the respective index in the map - * @param p Point in the real-world frame (usually the frame /map or /world) - * @param origin Pose of the point (0,0) of the map in the real-world frame - * @param width Width of the map - * @param resolution Resolution in meters/cell of the map - * @return index of point in the map - */ - int map_index(geometry_msgs::Point p, geometry_msgs::Pose origin, float width, float resolution) - { - return (int)(width * - ((p.y - origin.position.y)/resolution + 0.51) + - ((p.x - origin.position.x)/resolution + 0.51)); - } - - /** - * @brief point_in_map returns true if given point is in the map. False otherwise - * @param p Point in the real-world frame (usually the frame /map or /world) - * @param origin Pose of the point (0,0) of the map in the real-world frame - * @param width Width of the map - * @param resolution Resolution in meters/cell of the map - * @return true or false - */ - bool point_in_map(geometry_msgs::Point p, geometry_msgs::Pose origin, float width, float resolution) - { - int x_idx = (p.x - origin.position.x)/resolution + 0.51; - int y_idx = (p.y - origin.position.y)/resolution + 0.51; - if(x_idx < 0 || y_idx < 0 || x_idx >= width || y_idx >= width) return false; - return true; - } - - /** - * @brief transformPoint wrapper to transform points between coordinate frames - * @param point input point in from_frame - * @param listener transform listener - * @param from_frame input frame - * @param to_frame output frame - * @return transformed point in to_frame - */ - geometry_msgs::Point transformPoint(geometry_msgs::Point point, tf::TransformListener &listener, - std::string from_frame, std::string to_frame) - { - geometry_msgs::PointStamped pin; - geometry_msgs::PointStamped pout; - pin.header.frame_id = from_frame; - pin.point = point; - try - { - listener.transformPoint(to_frame, pin, pout); - return pout.point; - } - catch (tf::TransformException ex){ - ROS_ERROR("%s",ex.what()); - } - } - - /** - * @brief laser_range_to_point converts a single given laser scan range in polar coordinates - * to the respective point in euclidean coordinates in the target frame - * @param laser_range range of the laser point to convert - * @param index - * @param start_angle - * @param angle_step - * @param listener - * @param from_frame - * @param to_frame - * @return - */ - geometry_msgs::Point laser_range_to_point(float laser_range, int index, float start_angle, - float angle_step, tf::TransformListener &listener, - std::string from_frame, std::string to_frame) - { - float alpha = start_angle + index * angle_step; - geometry_msgs::PointStamped pin; - geometry_msgs::PointStamped pout; - pin.header.frame_id = from_frame; - pin.point.x = cos(alpha) * laser_range; - pin.point.y = sin(alpha) * laser_range; - - try - { - listener.transformPoint(to_frame, pin, pout); - return pout.point; - } - catch (tf::TransformException ex){ - //ROS_ERROR("%s",ex.what()); - } - } - - /** - * @brief laser_ranges_to_points converts a given laser scan in polar coordinates - * to the respective points in euclidean coordinates in the target frame - * @param laser_data laser data ranges - * @param start_angle angle of the first measurement - * @param angle_step angle increment between two consecutive laser measurements - * @param range_min minimum valid range - * @param range_max maximum valid range - * @return vector containing the laser measurements in euclidean points - */ - std::vector<geometry_msgs::Point> laser_ranges_to_points(const std::vector<float>& laser_data, float start_angle, - float angle_step, float range_min, float range_max, - tf::TransformListener &listener, - std::string from_frame, std::string to_frame) - { - std::vector<geometry_msgs::Point> ret; - float alpha = start_angle; - for (int i = 0; i < laser_data.size(); i++) { - if(laser_data[i] < range_min || laser_data[i] > range_max) - { - alpha += angle_step; - continue; - } - geometry_msgs::Point point; - point.x = cos(alpha) * laser_data.at(i); - point.y = sin(alpha) * laser_data.at(i); - - geometry_msgs::PointStamped pin; - pin.header.frame_id = from_frame; - pin.point = point; - geometry_msgs::PointStamped pout; - try - { - listener.transformPoint(to_frame, pin, pout); - ret.push_back(pout.point); - } - catch (tf::TransformException ex){ - //ROS_ERROR("%s",ex.what()); - } - - alpha += angle_step; - } - return ret; - } - - /** - * @brief Calculates the euclidean distance (in cells) between to points in the map - * @param a Point a - * @param b point b - * @return euclidean distance in cells - */ - double distance(const Eigen::Vector2i& a, const Eigen::Vector2i& b) - { - return sqrt((a.x() - b.x()) * (a.x() - b.x()) + (a.y() - b.y()) * (a.y() - b.y())); - } - - /** - * @brief Calculates the euclidean distance (in m) between to points in the world - * @param a Point a - * @param b point b - * @return euclidean distance in m - */ - double distance(const geometry_msgs::Point& a, const geometry_msgs::Point& b) - { - return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); - } - -/** - * @brief findValue - * @param map Pointer to the map to search - * @param width Width of the map - * @param height Height of the map - * @param center_x \__ Center point of circle to search within - * @param center_y / - * @param value Value to search for in given map - * @param radius Radius of the circle - * @return true if the given value could be found within the given radius around (x,y) - */ - bool findValue(const std::vector<int8_t>* map, int width, int height, int center_x, int center_y, unsigned char value, float radius) - { - - int start_x = int ( center_x - radius ); - int start_y = int ( center_y - radius ); - int end_x = int ( center_x + radius ); - int end_y = int ( center_y + radius ); - - if ( start_x < 0 ) { start_x = 0; } - if ( start_y < 0 ) { start_y = 0; } - if ( end_x >= int ( width ) ) { end_x = width - 1; } - if ( end_y >= int ( height ) ) { end_y = height - 1; } - - float sqr_radius = radius*radius; - - for ( int y = start_y; y <= end_y; y++ ) - for ( int x = start_x; x <= end_x; x++ ) - { - if ( map->at(x+width*y) > value ) - { - float sqr_dist = float ( x - center_x ) * float ( x - center_x ) + float ( y - center_y ) * float ( y - center_y ); - if ( sqr_dist <= sqr_radius ) { return true; } - } - } - - return false; - } -} - -#endif // TOOLS_H diff --git a/homer_navigation/CHANGELOG.rst b/homer_navigation/CHANGELOG.rst deleted file mode 100644 index 7d225c0c..00000000 --- a/homer_navigation/CHANGELOG.rst +++ /dev/null @@ -1,34 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package homer_navigation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1.0.6 (2015-11-27) ------------------- -* removed env HOMER_DIR from CMakeLists.txt -* Contributors: Niklas Yann Wettengel - -1.0.5 (2015-11-24) ------------------- -* added missing files -* Contributors: Niklas Yann Wettengel - -1.0.4 (2015-11-20) ------------------- -* changed build dependency from libeigen3-dev to eigen -* Contributors: Niklas Yann Wettengel - -1.0.3 (2015-11-20) ------------------- -* added libeigen3-dev build dependency -* Contributors: Niklas Yann Wettengel - -1.0.2 (2015-11-20) ------------------- -* added cmake_modules as build dependency in package.xml -* added Maintainers -* Contributors: Niklas Yann Wettengel - -1.0.1 (2015-09-08) ------------------- -* init -* Contributors: Raphael Memmesheimer diff --git a/homer_navigation/CMakeLists.txt b/homer_navigation/CMakeLists.txt deleted file mode 100644 index e2aac45a..00000000 --- a/homer_navigation/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) -project(homer_navigation) - -find_package(catkin REQUIRED COMPONENTS - roscpp roslib nav_msgs sensor_msgs homer_mapnav_msgs homer_nav_libs tf cmake_modules robbie_architecture -) - -find_package(Eigen REQUIRED) - -set(CMAKE_BUILD_TYPE Release) - -catkin_package( - INCLUDE_DIRS include -) - -include_directories( - include - ${catkin_INCLUDE_DIRS} - ${Eigen_INCLUDE_DIRS} -) - -add_executable(homer_navigation src/homer_navigation_node.cpp) -add_dependencies(homer_navigation ${catkin_EXPORTED_TARGETS}) - -target_link_libraries(homer_navigation - ${catkin_LIBRARIES} - ${Eigen_LIBRARIES} - ) diff --git a/homer_navigation/README.md b/homer_navigation/README.md deleted file mode 100644 index ae2cb85d..00000000 --- a/homer_navigation/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# homer_navigation - - -## Known Issues / Todo's - -Die Pfadplanung dauert im Gegensatz zur alten Robbie-Implementierung zu lange. Je mehr freie Fläche vorhanden ist, desto länger dauert die Berechnung eines Pfades. - -## Introduction - -Das Package "homer_navigation" mit seiner gleichnamigen Node ist für die Navigation des Roboters zuständig. Es hält stets die aktuelle Karte des Roboters vor, die z.B. vom map_manager veschickt wurde und berechnet anhand von dieser Karte einen Pfad vom Roboter zu einem gegebenen Zielpunkt. Dafür verwendet die Navigation die sogenannte Pfad-Transformation - eine Kombination aus Distanz-Transformation und Hindernistransformation -, in Verbindung mit A-Stern, um einen optimalen Pfad zu finden. Das Verhältnis zwischen Distanz- und Hindernis-Transformation kann über einen Parameter angepasst werden. -Nach der Pfadberechnung ist das Package außerdem dafür zuständig den Roboter diesen Pfad zum Ziel abfahren zu lassen. - -## Topics - - - -#### Publisher -* `/robot_platform/MoveRobot (robot_platform/MoveRobot)`: Über dieses Topic wird der aktuelle Fahrbefehl an die Roboterplattform geschickt. -* `/robot_platform/TurnRobot (robot_platform/TurnRobot)`: Über dieses Topic wird der aktuelle Drehbefehl an die Roboterplattform geschickt. -* `/robot_platform/StopRobot (robot_platform/StopRobot)`: Über dieses Topic wird der Roboter am Ziel beziehungsweise vor einem Hindernis gestoppt. -* `/homer_navigation/target_reached (std_msgs/Empty)`: Wenn der Roboter sein Ziel erreicht hat, wird eine Message über dieses Topic veschickt. -* `/homer_navigation/target_unreachable (map_messages/TargetUnreachable)`: Über dieses Topic wird mitgeteilt, wenn der Roboter sein Ziel nicht erreichen kann und die Navigation abgebrochen wurde. Ein Statuscode wird mitgeliefert (siehe Package map_messages). -* `/homer_navigation/path (nav_msgs/Path)`: Hierüber wird der aktuelle Pfad zur Visualisierung an die GUI geschickt. - -#### Subscriber -* `/map (nav_msgs/OccupancyGrid)`: Die jeweils aktuelle Map wird empfangen, um sie für die Pfadplanung und Hindernisvermeidung während der Navigation zu verwenden. -* `/pose (geometry_msgs/PoseStamped)`: Die aktuelle Pose des Roboters wird als Startpunkt der Pfadplanung verwendet. -* `/scan (nav_msgs/LaserScan)`: Der aktuelle LaserScan wird zur Hindernisvermeidung verwendet. -* `/robot_platform/task_finished (std_msgs/Empty)`: Wird vom Roboter nach erfolgter AUsführung einer Bewegung verschickt. Die Navigation verwendet dies am Ende der Navigation, um nach der letzten Drehung auf dem Zielpunkt die TargetReached-Nachricht zu versenden. -* `/homer_navigation/start_navigation (map_messages/StartNavigation)`: Startet die Pfadplanung und anschließend die Navigation zur mitgelieferten Zielpose -* `/homer_navigation/stop_navigation (map_messages/StopNavigation)`: Stoppt die aktuelle Navigation. -* `/homer_navigation/navigate_to_POI (map_messages/NavigateToPOI)`: Startet die Pfadplanung und anschließend die Navigation zum POI mit angegebenen Namen. Der entsprechende POI wird anschließend vom map_manager erfragt. -* `/homer_navigation/unknown_threshold (std_msgs/Int8)`: Über dieses Topic kann der Schwellwert verändert werden, ab dem ein Zellwahrscheinlichkeit als belegt und damit unbefahrbar markiert wird. Standard ist 50 (%). - -## Launch Files - -* `homer_navigation.launch:` Startet die Navigation und lädt alle Navigations-Paramter in den Parameterserver. - - -## Parameter - - -### homer_navigation - - - - -* `/homer_navigation/safe_path_weight:` Gewicht, um Bevorzugung sicherer (d.h. größerer Abstand zu Hindernissen) Pfade im Gegensatz zu kürzeren Pfaden einzustellen. 0 bedeutet kürzester Pfad, aber keine Sicherheit. Je höher, desto sicherer. -* `/homer_navigation/allowed_obstacle_distance/min:` Mindestdistanz zum nächsten Hindernis, die der Roboter bei der Navigation besitzen muss. -* `/homer_navigation/allowed_obstacle_distance/max:` Maximaldistanz zum nächsten Hindernis, die der Roboter bei der Navigation besitzen muss (wichtig für die Lokalisierung, abhängig von der Reichweite der Abstandssensoren). -* `/homer_navigation/safe_obstacle_distance/min:` Mindestdistanz des Roboters zum nächsten Hindernis für eine sichere Navigation. Gewichtung wird mit safe_path_weight eingestellt. -* `/homer_navigation/safe_obstacle_distance/max:` Maximaldistanz des Roboters zum nächsten Hindernis. -* `/homer_navigation/frontier_safeness_factor:` Faktor der minimal erlaubten Distanz zum nächsten Hindernis, den eine Grenzzelle zu unbekanntem Gebiet mindestens haben muss, um als sicher und damit befahrbar zu gelten. -* `/homer_navigation/collision_distance:` Wenn die Distanz zum nächsten Hindernis in Metern (gemessen ab der Front des Roboters) kleiner wird als der angegebene Parameter, wird der aktuelle Fahrbefehl gestoppt und die Pfadplanung neugestartet. -* `/homer_navigation/collision_distance_near_target:` Nähe in Metern zum Ziel, ab der der Roboter bei einer Kollision nicht mehr zurückfährt und neuplant, sondern stoppt und eine TargetReached-Nachricht versendet. -* `/homer_navigation/backward_distance:` Strecke in Metern, die der Roboter bei einer bevorstehenden Kollision zurückfährt, bevor er einen neuen Pfad plant. -* `/homer_navigation/check_path:` Wenn auf "true" gesetzt, wird der aktuell geplante Pfad auf neu hinzukommende Hindernisse geprüft und gegebenenfalls neugeplant. -* `/homer_navigation/check_path_max_errors:` Wenn Pfade gecheckt werden, wird umgeplant, sobald sich "check_path_max_errors"-mal hintereinander ein Hindernis in der ankommenden Karte im Pfad befindet. -* `/homer_navigation/check_path_max_distance:` Der Pfad wird nur in der Nähe des Roboters bis zur im Parameter angegebenen Distanz auf neu hinzukommende Hindernisse überprüft -* `/homer_navigation/turn_threshold_angle:` Wenn der Winkel zwischen der Orientierung des Roboters und der Strecke zum nächsten Wegpunkt unter dem angegebenen Wert liegt, soll geradeaus gefahren werden, ansonsten soll sich der Roboter um diesen Winkel in Richtung des Wegpunkts drehen. -* `/homer_navigation/waypoint_sampling_threshold:` Parameter, um Anzahl der Wegpunkte im Pfad zu minimieren. 0 bedeutet keine Reduzierung. Je höher der Wert, desto mehr Wegpunkte werden gelöscht. -* `/homer_navigation/speed_control/last_speedfactor_count:` Größe des Vektors, der die zuletzt berechneten Geschwindigkeitsfaktoren berechnet. Wird benutzt, um aus dem Mittelwert zusammen mit der aktuellen Distanz zum nächsten Hindernis die aktuelle Geschwindigkeit zu berechnen. -* `/homer_navigation/speed_control/min_move_speedfactor:` Minimaler Faktor der maximal möglichen Geschwindigkeit, mit der der Roboter jemals fahren darf. -* `/homer_navigation/speed_control/min_turn_speedfactor_moving:` Minimaler Faktor der maximal möglichen Drehgeschwindigkeit, mit der der Roboter sich während einer Geradeausfahrt drehen darf (aktuell mit dem cu2wd nicht möglich). -* `/homer_navigation/speed_control/min_turn_speedfactor_standing:` Minimaler Faktor der maximal möglichen Drehgeschwindigkeit, mit der sich der Roboter im Stand drehen darf. -* `/homer_navigation/speed_control/inner_danger_zone/x_min:` Wenn sich in der mit den nächsten vier Parametern beschriebenen Boundingbox um den Roboter ein Hindernis befindet, darf sich der Roboter nur mit der vorher eingestellten nachfolgend eingestellten Geschwindigkeit bewegen. -* `/homer_navigation/speed_control/inner_danger_zone/x_max:` -* `/homer_navigation/speed_control/inner_danger_zone/y_min:` -* `/homer_navigation/speed_control/inner_danger_zone/y_max:` -* `/homer_navigation/speed_control/inner_danger_zone/speed_factor:` Faktor der maximalen Geschwindigkeit, mit der sich der Roboter in seiner inneren Gefahrenzone bewegen darf. -* `/homer_navigation/speed_control/outer_danger_zone/x_min:` Eine zweite Boundingbox, die die innere umschließen muss. -* `/homer_navigation/speed_control/outer_danger_zone/x_max:` -* `/homer_navigation/speed_control/outer_danger_zone/y_min:` -* `/homer_navigation/speed_control/outer_danger_zone/y_max:` -* `/homer_navigation/speed_control/outer_danger_zone/speed_factor:` Faktor der maximalen Geschwindigkeit, mit der sich der Roboter in seiner äußeren Gefahrenzone bewegen darf. -* `/homer_navigation/max_rot_vel:` Maximal mögliche Rotationsgeschwindigkeit des Roboters in Radiants/Sekunde. -* `/homer_navigation/max_trans_vel:` Maximal mögliche Geschwindigkeit des Roboters in Metern/Sekunde. - - diff --git a/homer_navigation/config/homer_navigation.yaml b/homer_navigation/config/homer_navigation.yaml deleted file mode 100644 index a9e7aff8..00000000 --- a/homer_navigation/config/homer_navigation.yaml +++ /dev/null @@ -1,48 +0,0 @@ -/homer_navigation/safe_path_weight: 1.5 #weight for safer path in relation to shortest path -/homer_navigation/allowed_obstacle_distance/min: 0.32 #m robot must move within these bounds -/homer_navigation/allowed_obstacle_distance/max: 5.0 #m -/homer_navigation/safe_obstacle_distance/min: 0.7 #m if possible robot should move within these bounds -/homer_navigation/safe_obstacle_distance/max: 5.0 #m - -/homer_navigation/frontier_safeness_factor: 1.5 #factor of distance to an obstacle of a frontier cell which is considered safe - -/homer_navigation/collision_distance: 0.20 #m - -/homer_navigation/collision_distance_near_target: 0.4 #m distance to target where obstacle avoidance won't be executed, to avoid strange for- and backward moving activities near a target -/homer_navigation/backward_distance: 0.07 #m - -/homer_navigation/check_path: true -/homer_navigation/check_path_max_errors: 2 -/homer_navigation/check_path_max_distance: 2.0 #m - -/homer_navigation/turn_threshold_angle: 15 #° - -/homer_navigation/waypoint_sampling_threshold: 2 - -/homer_navigation/speed_control/last_speedfactor_count: 10 -/homer_navigation/speed_control/min_move_speedfactor: 1.0 -/homer_navigation/speed_control/min_turn_speedfactor_moving: 1.0 -/homer_navigation/speed_control/min_turn_speedfactor_standing: 0.5 - -/homer_navigation/speed_control/inner_danger_zone/x_min: -0.35 -/homer_navigation/speed_control/inner_danger_zone/x_max: 1.1 -/homer_navigation/speed_control/inner_danger_zone/y_min: -0.35 -/homer_navigation/speed_control/inner_danger_zone/y_max: 0.35 - -/homer_navigation/speed_control/inner_danger_zone/speed_factor: 0.3 - -/homer_navigation/speed_control/outer_danger_zone/x_min: -0.45 -/homer_navigation/speed_control/outer_danger_zone/x_max: 1.6 -/homer_navigation/speed_control/outer_danger_zone/y_min: -0.45 -/homer_navigation/speed_control/outer_danger_zone/y_max: 0.45 - -/homer_navigation/speed_control/outer_danger_zone/speed_factor: 0.6 - -/homer_navigation/max_rot_vel: 0.4 # rad/s -/homer_navigation/max_trans_vel: 0.3 # m/s - -/homer_navigation/use_cmd_vel: true # test -/homer_navigation/min_turn_angle: 0.15 # 0.17 -/homer_navigation/max_turn_speed: 0.6 # rad/s 0.6 -/homer_navigation/max_move_speed: 0.4 # m/s 0.4 -/homer_navigation/max_drive_angle: 0.6 # if above that value only turn diff --git a/homer_navigation/config/homer_navigation_followme.yaml b/homer_navigation/config/homer_navigation_followme.yaml deleted file mode 100644 index 7b13dfc3..00000000 --- a/homer_navigation/config/homer_navigation_followme.yaml +++ /dev/null @@ -1,14 +0,0 @@ -#/homer_navigation/collision_distance: 0.23 #m -/homer_navigation/collision_distance: 0.47 #m - -/homer_navigation/collision_distance_near_target: 0.2 #m distance to target where obstacle avoidance won't be executed, to avoid strange for- and backward moving activities near a target -/homer_navigation/backward_distance: 0.07 #m -/homer_navigation/check_path_max_errors: 5 - -/homer_navigation/min_turn_angle/min: 20 #° -/homer_navigation/min_turn_angle/max: 20 -/homer_navigation/min_turn_angle/min_distance: 0.5 #m -/homer_navigation/min_turn_angle/max_distance: 2.0 #m - -/homer_navigation/waypoint_sampling_threshold: 4 - diff --git a/homer_navigation/include/homer_navigation/homer_navigation_node.h b/homer_navigation/include/homer_navigation/homer_navigation_node.h deleted file mode 100644 index d0d95b1b..00000000 --- a/homer_navigation/include/homer_navigation/homer_navigation_node.h +++ /dev/null @@ -1,372 +0,0 @@ -#ifndef FastNavigationModule_H -#define FastNavigationModule_H - -#include <vector> -#include <string> -#include <map> -#include <deque> - -#include <Eigen/Geometry> - -#include <ros/ros.h> -#include <tf/transform_listener.h> - -#include "Architecture/StateMachine/StateMachine.h" - -#include <nav_msgs/OccupancyGrid.h> -#include <geometry_msgs/PoseStamped.h> -#include <sensor_msgs/LaserScan.h> -#include <sensor_msgs/PointCloud2.h> -#include <homer_mapnav_msgs/StartNavigation.h> -#include <homer_mapnav_msgs/StopNavigation.h> -#include <homer_mapnav_msgs/NavigateToPOI.h> -#include <std_msgs/Int8.h> - -class Explorer; -/** - * @class HomerNavigationNode - * @author Malte Knauf, Stephan Wirth, David Gossow (RX) - * @brief Performs autonomous exploration and navigation - */ -class HomerNavigationNode { - - public: - - /** - * @brief States of the state machines - */ - enum MapType - { - SLAM_MAP, - NAVIGATION_MAP - }; - - enum ProcessState - { - IDLE, - AWAITING_EXPLORATION_MAP, - AWAITING_PATHPLANNING_MAP, - FOLLOWING_PATH, - AVOIDING_COLLISION, - FINAL_TURN, - TARGET_REACHED, - TILTED, - STALLED - }; - - /** - * The constructor - */ - HomerNavigationNode(); - - /** - * The destructor - */ - virtual ~HomerNavigationNode(); - - /** @brief Is called in constant intervals. */ - void idleProcess(); - - - protected: - - /** @brief Handles incoming messages. */ - //virtual std::set<Message*> processMessages(); - void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg); - void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); - void laserDataCallback(const sensor_msgs::LaserScan::ConstPtr& msg); - void backLaserCallback(const sensor_msgs::LaserScan::ConstPtr& msg); - void startNavigationCallback(const homer_mapnav_msgs::StartNavigation::ConstPtr& msg); - void stopNavigationCallback(const homer_mapnav_msgs::StopNavigation::ConstPtr& msg); - void navigateToPOICallback(const homer_mapnav_msgs::NavigateToPOI::ConstPtr& msg); - void unknownThresholdCallback(const std_msgs::Int8::ConstPtr& msg); - void moveBaseSimpleGoalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); - - - /** @brief initializes and refreshs parameters */ - void loadParameters(); - - /** @brief Is called when all modules are loaded and thread has started. */ - virtual void init(); - - - /** @brief Detect & handle possible collision */ - void handleCollision(); - - private: - - - /** @brief Start navigation to m_Target on last_map_data_ */ - void startNavigation(); - - /** @brief Start exploration on last_map_data_ */ - void startExploration(); - - /** @brief Check if obstacles are blocking the way in last_map_data_ */ - void checkPath(); - - /** @brief calculate path from current robot position to target approximation */ - void calculatePath(); - - /** @brief Send message containing current navigation path */ - void sendPathData(); - - /** @brief Sends target reached and stops the robot. */ - void sendTargetReachedMsg(); - - /** - * @brief Sends a target unreachable with given reason and stops the robot. - * @param reason reason for unreachable target (see homer_mapnav_msgs::TargetUnreachable for possible reasons) - */ - void sendTargetUnreachableMsg( int8_t reason ); - - void refreshParamsCallback(const std_msgs::Empty::ConstPtr& msg); - - /** @brief Navigate robot to next waypoint */ - void performNextMove(); - - /** @brief Finishes navigation or starts turning to target direction if the target position has been reached */ - void targetPositionReached(); - - /** @return Distance from robot_pose_ to point */ - double distanceTo(geometry_msgs::Point point); - - /** @return Angle from robot_pose_ to point in degrees */ - int angleToPointDeg(geometry_msgs::Point point); - - /** @brief Set status info */ - void actualizeStatusInfo(); - - /** @brief Calculates current maximal speed based on laser data */ - float calcSpeedFactor(); - - /** @brief Calculates current maximal backwards distance on map Data */ - float obstacleBackwardDistance(); - - - /** - * @brief Send move message - * @param distance_m distance to drive in m - * @param speed_mPerSec driving speed in m/s - * @param drive permanently until stopped - */ - - void sendMoveMessage(double distance_m , double speed_mPerSec, bool permanent = false); - - /** - * @brief Send TurnMessage and set current turn action - * @param theta angle to turn (in degrees) - * @param speed turning speed - * @param turn permanently until stopped - */ - void sendTurnMessage(double theta, double speed, bool permanent = false); - - void sendStopRobot(); - - /** - * @brief Sets each cell of the map to -1 outside the bounding box - * containing the robot pose and the current target - */ - void maskMap(); - - /** - * @brief Current path was finished (either successful or not), - * sets state machine to path planning to check if the robot is already at the goal - */ - void currentPathFinished(); - - //convenience math functions - /** - * Computes mean of given input values - * @param values Container with values from which to compute mean - * @return mean value - */ - template<class ContainerT> - static double mean ( const ContainerT& values ); - - /** - * Computes minimum turn angle from angle 1 to angle 2 - * @param angle1 from angle - * @param angle2 to angle - * @return minimal angle needed to turn from angle 1 to angle 2 [-Pi..Pi] - */ - static float minTurnAngle ( float angle1, float angle2 ); - - /** - * converts value from degree to radiant - * @param deg Value in degree - * @return value in radiants - */ - static float deg2Rad ( float deg ) { return deg / 180.0*M_PI; } - - /** - * converts value from radiants to degrees - * @param rad Value in radiants - * @return value in degrees - */ - static float rad2Deg ( float rad ) { return rad / M_PI*180.0; } - - /// @brief Worker instances - - Explorer* explorer_; - - /// @brief State machines - - StateMachine<MapType> m_MapTypeMachine; - StateMachine<ProcessState> m_MainMachine; - - /// @brief Navigation options & data - - /** list of waypoints subsampled from m_PixelPath */ - std::vector<geometry_msgs::PoseStamped> waypoints_; - - /** Path planned by Explorer, pixel accuracy */ - std::vector<Eigen::Vector2i> pixel_path_; - - /** target point */ - geometry_msgs::Point target_point_; - - /** approximation of the target point is target is in an occupied cell */ - Eigen::Vector2i target_approx_; - - /** orientation the robot should have at the target point */ - double target_orientation_; - - /** allowed distance to target */ - float desired_distance_; - - /** check if the final turn should be skipped */ - bool skip_final_turn_; - - /** - * check if navigation should perform fast planning. In this mode a path is only planned within - * a bounding box containing the robot pose and the target point - */ - bool fast_path_planning_; - - /** current pose of the robot */ - geometry_msgs::Pose robot_pose_; - - /** current laser scan */ - std::vector<geometry_msgs::Point> laser_points_; - std::vector<geometry_msgs::Point> m_laser_points_map; - std::vector<geometry_msgs::Point> m_back_laser; - - /** time stamp of the last incoming laser scan */ - ros::Time last_laser_time_; - - /** Distance factor of a frontier cell considered save for exploration */ - float m_FrontierSafenessFactor; - - /** stores the last m_SpeedFactorMeanFilterSize speed factors */ - std::deque<float> m_LastSpeedFactors; - /** stores the mean of the last speed factors */ - std::deque<float> m_LastMeanSpeedFactors; - /** maximal count of stored last speed factors bevore oldest one will be overwritten */ - int m_SpeedFactorMeanFilterSize; - - /** minimal speed factor while moving */ - float m_MinMoveSpeedFactor; - - /** minimal turn speed factor while moving */ - float m_MinTurnSpeedFactorMoving; - - /** minimal turn speed factor while standing */ - float m_MinTurnSpeedFactorStanding; - - double m_SafePathWeight; - - /** Number of subsequent times that an obstacle was detected in the planned path */ - int invalid_path_count_; - - ///map parameters - double resolution_; - double width_; - double height_; - geometry_msgs::Pose origin_; - - /// @brief Configuration parameters - - /** maximum move speed of the robot */ - float m_MaxTransVel; - /** maximum turn speed of the robot */ - int m_MaxRotVel; - - bool m_use_cmd_vel_; - - /** Allowed distances of obstacles to robot. Robot must move within these bounds */ - std::pair<float,float> m_AllowedObstacleDistance; - /** Safe distances of obstacles to robot. If possible, robot should move within these bounds */ - std::pair<float,float> m_SafeObstacleDistance; - - /** threshold to sample down waypoints */ - float waypoint_sampling_threshold_; - - /** if distance to nearest obstacle is below collision distance trigger collision avoidance */ - float collision_distance_; - /** do not drive back in collision avoidance when this near target */ - float collision_distance_near_target_; - /** drive this distance backwards when avoiding collision */ - float backward_distance_; - - /** threshold angle between robot and next waypoint when to turn instead of driving forward */ - double turn_threshold_angle_; - - /** if true, obstacles in path will be detected and path will be replanned */ - bool check_path_; - /** path will be replanned, if obstacle is present in at least check_path_max_errors consecutive incoming maps */ - int check_path_max_errors_; - - /** waypoints will only be checked for obstacles if they are closer than check_path_max_distance to robot */ - float check_path_max_distance_; - - bool m_avoided_collision; - - double m_min_turn_angle; - double m_max_turn_speed; - double m_max_move_speed; - double m_max_drive_angle; - - float m_act_speed; - float m_act_angle; - - bool m_path_reaches_target; - - /** timestamp of last incoming map */ - ros::Time last_map_timestamp_; - - /** last map data */ - std::vector<int8_t> * last_map_data_; - - //ros specific members - tf::TransformListener transform_listener_; - - //subscribers - ros::Subscriber map_sub_; - ros::Subscriber pose_sub_; - ros::Subscriber laser_data_sub_; - ros::Subscriber laser_back_data_sub_; - ros::Subscriber robot_data_sub_; - ros::Subscriber task_finished_sub_; - ros::Subscriber start_navigation_sub_; - ros::Subscriber stop_navigation_sub_; - ros::Subscriber navigate_to_poi_sub_; - ros::Subscriber unknown_threshold_sub_; - ros::Subscriber refresh_param_sub_; - ros::Subscriber m_move_base_simple_goal_sub_; - - //publishers - ros::Publisher move_robot_pub_; - ros::Publisher turn_robot_pub_; - ros::Publisher stop_robot_pub_; - ros::Publisher cmd_vel_pub_; - ros::Publisher target_reached_pub_; - ros::Publisher target_unreachable_pub_; - ros::Publisher path_pub_; - - - //service clients - ros::ServiceClient get_POIs_client_; -}; - -#endif diff --git a/homer_navigation/launch/homer_navigation.launch b/homer_navigation/launch/homer_navigation.launch deleted file mode 100644 index db217818..00000000 --- a/homer_navigation/launch/homer_navigation.launch +++ /dev/null @@ -1,4 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_navigation)/config/homer_navigation.yaml"/> - <node ns="/homer_navigation" name="homer_navigation" pkg="homer_navigation" type="homer_navigation" output="screen"/> -</launch> diff --git a/homer_navigation/launch/homer_navigation_followme.launch b/homer_navigation/launch/homer_navigation_followme.launch deleted file mode 100644 index 419db5e8..00000000 --- a/homer_navigation/launch/homer_navigation_followme.launch +++ /dev/null @@ -1,4 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_navigation)/config/homer_navigation_followme.yaml"/> - <node ns="/homer_navigation" name="homer_navigation" pkg="homer_navigation" type="homer_navigation" output="screen"/> -</launch> diff --git a/homer_navigation/launch/homer_navigation_ros.launch b/homer_navigation/launch/homer_navigation_ros.launch deleted file mode 100644 index 04a131d5..00000000 --- a/homer_navigation/launch/homer_navigation_ros.launch +++ /dev/null @@ -1,6 +0,0 @@ -<launch> - <rosparam command="load" file="$(find homer_navigation)/config/homer_navigation.yaml"/> - <node ns="/homer_navigation" name="homer_navigation" pkg="homer_navigation" type="homer_navigation" output="screen"> - <remap from="/robot_platform/cmd_vel" to="/cmd_vel"/> - </node> -</launch> diff --git a/homer_navigation/package.xml b/homer_navigation/package.xml deleted file mode 100644 index 0c1c0444..00000000 --- a/homer_navigation/package.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0"?> -<package> - <name>homer_navigation</name> - <version>1.0.6</version> - <description>The homer_navigation package</description> - - <maintainer email="vseib@uni-koblenz.de">Viktor Seib</maintainer> - <maintainer email="niyawe@uni-koblenz.de">Niklas Yann Wettengel</maintainer> - <maintainer email="heuer@uni-koblenz.de">Gregor Heuer</maintainer> - <maintainer email="raphael@uni-koblenz.de">Raphael Memmesheimer</maintainer> - - <author email="mknauf@uni-koblenz.de">Malte Knauf</author> - <license>GPLv3</license> - - <buildtool_depend>catkin</buildtool_depend> - <build_depend>roscpp</build_depend> - <build_depend>roslib</build_depend> - <build_depend>homer_nav_libs</build_depend> - <build_depend>nav_msgs</build_depend> - <build_depend>sensor_msgs</build_depend> - <build_depend>homer_mapnav_msgs</build_depend> - <build_depend>tf</build_depend> - <build_depend>cmake_modules</build_depend> - <build_depend>eigen</build_depend> - <build_depend>robbie_architecture</build_depend> - - <run_depend>roscpp</run_depend> - <run_depend>roslib</run_depend> - <run_depend>homer_nav_libs</run_depend> - <run_depend>nav_msgs</run_depend> - <run_depend>sensor_msgs</run_depend> - <run_depend>homer_mapnav_msgs</run_depend> - <run_depend>tf</run_depend> - <!-- The export tag contains other, unspecified, tags --> - <export> - <!-- You can specify that this package is a metapackage here: --> - <!-- <metapackage/> --> - - <!-- Other tools can request additional information be placed here --> - - </export> -</package> diff --git a/homer_navigation/readme.pdf b/homer_navigation/readme.pdf deleted file mode 100644 index 808199ca0b0e7635cc36e1000a53c87196827351..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118724 zcma&MLzFIBu&tT4ZQJIbwszXKZ5umnd#7#Nwr$(aI#r`y>%PW~R>T_7|6<O$$Q4Az z>6sbWVaVr}hSy+NS&5j4?2W95000<9SyMZ67Yib0E^cn3|F2*e#Vu`IOr3}r#cd2- zOhrwN?M+N!`1xU+U7Sn}ZDBk%rZsHsH#v}gcJ%k{lL9l5cb^vQX+IiTG!&a|AZ)Nf zc#LccQcV<;f{s^jV<k2kvWlkXfIp2AMoB%pPTLRX&u#c*%xm+C_CI~zkFHWA&2^Z| zS(vr;rrVO~W+OFAoGFTO=_}Xs#!IZLIxVJk9*#QnvI=fC-t{M2*)kfHtOdAp=tajL z5*M4?ZNpjZHr|C#csv(h|6P~+isv17sYpTECa7%7^Hq;GYK~9Hn(Ppy!f0T&aHpqA zr=ASktoIQxTEQ;DX85$REZbRcw2vj#>n7E){Bs3uz6|TBz20c)#<nZ>=H;<Uzc$de z^1D*2++f&Y>#Vk|(sv5*^*9)qfGH`cx6sSXTPu~BX+tt0)M#q4=~0NJw4YbWporPt z%iYVQHNPbCY356l)}0Ycu%V05GcI+;T~ym)nXCBRr-oPClg@?1fBrIA8&BBy*;=a^ zbegShZ1Rih^+59vQGR?(yr-jlwB7a^Bja9sxgyvybV@J{`OLyFB*fc*2#ZaF?D2us zrdLuUxdyaAw5U<r#6YFXe0>|Oq=uZ9OTG?;BuL7}J1<yV0OQgK$?r?yxvpw!LrSEV z=>4--{35stb*-r5Z_C6{KV?xjq~Sr$fl$LJEhz=3eN2?~w|DsVt)dfE^cwO3Jp+$n zIfu9mI&-^%L^M>bO`vCy(K}GcpukPGhg`UX<PD)FP*-8n51Y4ZO&z+8#=UY8nahWd zsx#cXUV7%CH?NoyDjWN;ezG{t4P$yhn-FuF%w@Go5EjW9xnjUs#5vH%8xA<<v&hP< z!?k!ab5YfBu%Wf8>bgaQYZh8<lKef-z1D>k1X3x`%mfGOJKE7!Mw=%`(Fvlnkc#x7 z*x#okqR>CyQD=iIxRG$M6DedriZ{6T>lU!;+>W_U0|q2RBV54`wFfiq?6#X^6Mn(t zwq<e84G6c9ZYhCB6TkHwBqci{ooxe$%WWPU5s%%uL>+g{{bjZFUv4*JaTen7AVTSS z%qZ#KRoxDv5X8jyy*P$z$U@NLFqTAMB+`=gj^eFY#CObg2peH!Zz96cg=M`_&;b<N z<A3z-2dxCEq95x?ImVRGD^ctdXedw=ZaqF8paQLisg8v8AiG((@%r;%?ZrRLC%?q+ zmK_79r5hFvEL|?P7P_F>1d;1P$#OwO5_8#I2)>S2%rn0xstxc}4w#DTO^nG13gq@3 zoGBCdMy5*G2ku~sZnwr;F^5T_%x3?M7s#=^LXx=G+UU0`8D$Gk#3gK;$$QO3D-AI# zOlBTdEITL>6xY!>5(P|fEMArr@nWO<=shdX<@v!_?OT~j-cqrV;!#U@XO<D5G9$>N zQb<+ox!TC1?rhVYBuZ(@It}B~-5n`nt<^oH@|d}raxhp)l-Tsg^xN;Y;g%n)FQ*l( zAuqxrUs6&H-#v(JBOY35zvA)?^jHLQzdxa%N1t-bE>+2r%K<O}d^yT^v*YA&9>=V! z)gAjFR;9qk_gAYo8-AkmJ_Vs+M04l9I7}miJ*z3QnkCD!!n#xo3aEUbHe3!Lcz7MB zSC&3!L8k4wQnB|5@&O<VCJHNpDp0qQ7duNeg{kHw9A|o>XLQhdhD5+#hO@Mt>k!i% zvf#%&RD_BVlpY@bAI3alw90VN4qeUHe_vHh_CoJ~{9r*q1&U7ufO?P5Hp1^Wt$hUi z9JoA4?nVzOVI&tq`TOI{CEkQM_aNy9;!Y{w0{222as9>c_aT)5e))U$qG+;=_u&bs zn*GUN`arLiXKsj~t*ahj4qB|}l?xKUrTMadkN1f0JPvCAVR`rvdXPX62v8R|jIpr= zv7<;0ytJ|lU+CLt6fNSbyrw1(fJX4B_-+3!IFcP5h^v`#pq3dz%Wm-oOFq~Y#3m%E z7v{x{*52G7&~$FEUk0A{D`Uv?+s^B@aU0y-4J7TFo|K&d;)FokJscAoN!n!&qe}&9 zFC20wOt&0qpgSrx_F!vkY1ObZi~<@+b!F&D{Q68Q!VSKahkr)guK{IR`dEJH?(M60 z)=9`O8W@O*2-%h-L(=mLtpo|bQ>q6{m!dxygQ^^V^#-`w@YR`xmQxE~>I)qO{@9$O z3lKit1bQi%TI#XDzX*pk=v+cQ^Tj_@nH2bO!<>eeh)UXpy^zftaqdA#p-fmX&97)9 zT9z<>z!WCwlQOssV8(;>2-4nxt65(ve0nu(nK#X777Waj3{rqM{xOz<rLPE6^*Ap) z`koibgP4ZNHHyu>Y0}Uc7ho-LTfMXM*M!_J?S~^R$()?gzfJj$^g<~wWup}qCyomZ zAKkFCZu2~wMVBIm=bj3?VE$2543S=$&AbEAypvm)Ae7z6!RCO>8~`%SM<n{;pd}Y9 z5rs}+#X_S!F@GbOAX?SJ9PG*u506l954o<O+V~Z7RR1`6%acdG*|Yq<9&oO_kpK;4 zvT5-L$xNNNzdKEp)${jjlz&4!h7wd`F5X{;N)sP}eZUr2@ND;aKs@L7>4!13Gx`6i z`(O7Tv0>QQ|1ap~X8B*EyIVsu?vMk;FHgT94cx?FD%Hb!hb7$@l`KiT0~404k!cBo z-g+|;PAPZfZM8JAXo-L0d}rN2Zwe*O=)Q7OQ;AaZ;a(MEw6(RihF>8Attg&pt0pm< zxv=O@kwOSd!j{@N;raB<485&0XBKNF4)5pewLB^;S1rP<aw2WYR5_8@$iV$9+w7m& zvqRR%{-9l-<<!k}9fbtH8PSy#eT?eL?d96ZV>@lP$y!2N<$mc{xLW=riH4+TkSw}! z)Kv2j=nTnJ)Dgj042@pk9u}Ehb_jw(*AM+irhhc-(<A$$38}AxGd3KK@0e&{rGz-z z;1f-o+<Mt2MRWHRIu;};k|ugc5c03;)e|)w+tys*5!YH^HIg~K>89rwtjb#u9ad(Z zIH$Ghrp?>Q+tC*;tNlLsC+@oF5&j&yrZ%fw8lOR((YA8R*Bx!hJIY0Q*r(RkBdn?l zSdv~O_9alIY-6A0qIUY39e9~NgTZv$w+=^#Vu*eLpS%z15KM?0Lj_3htyq06?kDpg zR*S7>b^5{BI)fY23N6}?D5OBg%5xD^T>CV6(E-*tF@h%HJmIz0K1IERy)=g)_u7ap zh$Rb%BOR=4*ib}l<RIey5^Pv~bx$SWL^}Z^VG9VGy6yrY)GE=tE>$l)vblx)fGD0| zN{F@d*1nrmqW<>7Zyg?EdxLAwF6uqHV#yG?h<Kj?ZRnJq!BMAbgu9X2zus?feZ<YX z!`}uEkCfNyf+2~T$ac_rjyEW~L5IKQ-7USB;oxP?8qY1=IMVLD8tg<{8!B;k9R)CV zJ@&1GtC;CdiUHJ%q7DHXXV6-ik0jrmVMt&Mv#u_yJ@Dy#PU!~5M0Ob4KXWxgToem6 zI!3ZO;f%)W-zB*i{(Z&%+=M+VD<W6!?AvXJws7UoO>e{g+R++;&WGXNbAy0clN&zf ziOhOsLrZZq^)w?i{C3bs2SysMDwP;_z5EG|=v(GOH3|mE(|@^@nQa8(HduT(IP+XQ zjm(37OxufQ8J2~S5x2b7D-wFTH){VLgPCme{q3jBB4Odk5r?j22cfmI_Bm0(nU}wm z$!t+ggY&QyU-}-oEIMzI>sFBpu0cq|!R{vvi+IyLn!F`%qE@)nS4MQV_gdr^Yhd*p z;;lS^u^vIhh1l{yK0-sL*h#gb>LzzXTZCLivHmuWMJ4fXk|?^_{e^bzwuDRXVmTae z`B@@!oRMH4+b}DG$J5339@ikEO(0RD+=00(nibg9HvE1e|F~%VP3mZ(XkUR2U&W~4 zQdz}D(h({<_*e6B{j!9O@W7V-%6!MzYX8yNhc4BK^)dWhE1(xZD{N}#z4nOGq#!65 z<(NqA6|&-q6+RJj)Xu|fN8ut07xCC2e5N4{f*h@lkNZ0R-sl1A>`jQBz|D^fUH1^h zB8;3n`G!IlVU4;Fa}G!0lhTh*A6D9)N|Fl2WZ5+qys3pMIz)t#`qeB6h~`EV$n}9` zz&jp5J;wq=%@hOcKA1pw!mwr;^J%FHzqQqj2k-bP(1ug!>vZk)tT1`2$9;N42MtGv z4whi1heAK7H;NAp!3exBgYlN~mSsi}K|N8LDp8`5mG<1Q2lgEkVEVWC*>E|KDId?} z%34B!{`g>qDz37D^fI&*vkk++u0a?cTDPdy<F5pQ@}{d%CX0I$7<5>;go49QkoWoN zVc*`uKrvUc83JSCd#h{`Z1>N!YAG<H%|;eqJ!sM*LCthi)_IJ?P8ax-H@>&Yu%7<f z*Vtw&lAYdj1BBZpdiZESS2fmF<k091RWrif0_az;I4R#1#)rriij9{^bfRE0tOhsJ zo!*qGCT~)=HM@RGol&}oFf+!H(Q@1Q%);d!{=~;>+9a5yY8SA|P9<FYU_A3@k^N#< zf{gqjNsFHDgTEc-2_mLEvQ%0YL%#n{Kj{NAK0YKj=PSH{Wr5ic5?Ud!eAXI@It9ui zM=*Xtef^eKpxc2y&1zXjf)Kzp8S9G~q76@ocQDi4=NHyh^NWvMxSb`+mb(fQv7~%; zkX6eRWQ{sQfhxQ}8P>p`4RQVz&~df{#883;4dZPs+}84$V^7H7;h`sa_GzT%n2=Y` z-z2zH+OJ8|5Y|)}pbt+hE}e%_^_SPL&AEs0)f1%Wz7_$m^jAIK?uB?|)`)~X&}M_l zFGOdh-DyofSxMv{ha1CB9vbzcw@tRf3}3`TDEI8vVo$=x?N)#(0)<#z9vf_@QBnC6 z!;$CORR%C6W)+%QJUR!H^hZ2)q4yf@&*??3TZE1x$!O{^MGN|faMch+jC1Y}+GGv8 zaQlcr)zxKvT;K-tTS(R)af!EBa5^sUUxNxUf5`4pCu0oskhuo!%*vMY9Y7j2IxrP* zEJ)_`n(9|jDiC$6W1Rn6&OU@#B@QlJn=K;O9biRL&;={jh+;~a(}R8R%fz&H(7miJ z{_X>W<mnjv<+#5JyL1PF$uQ??7)lK<)shMG5AG`58j79;KhYWrK5G}EJMU@iGX&!i zSjDT!4EetCS)qjY&Th{K>Xv=a!~X<3JJbIJI|~~(+y7RR4{L7P9gZRU=GD%Tf=8eC zJT%zj+Klwu0jy=C;p!ZT=G0_JWD_754`X`xRdtuq#5OCTSu(mbrZ4OoIxm*WqlS$- zk)kTyjb1)WH{H_+RXWBF0gB@XZjJFHBklE3LnZYKZjPOLU!)z%N_4-TpO0;b9HxtM zG=JD---gpV&2BeTb$zH?#q>FzO%+wA8?|dQKWi8XXj-+>n92yZj(gs|A${(TAv0um zF=4@LQDNJeCWf@+W*WogbufF=J`00Zb@pyTBOYZRAS@fXqzplIz!1(?2S*VmVQo!Z zuwK~8Zkw19Wm3dCi=#VsmdSo)G;4LW)3&|6^wMG>Yl{0zPy9R!9?H(~ubza_3#g)W zxV1m)H3lZ~p%UlqR#U!#Uk2UpA(C+8Fy}UQw{{JBRV>+DwjT!803E1mfHXv^&3*I_ zCmGZ%-W;5_7AdeCyik8zf~blsX|CkxFfUk6*7n%QPyCDgov>;BJ6{iJpF8!weoFO* zOoJEf-?j$#QL&$=q<@tFO)}{bp5mn62=Urg-P4O2%l!_NIL1Tn+!CTLAVEvoZ+p9C zPGCcIn=NZ7x=Uv$G@`IlQIq<F=rZdNsntbm1pAD+6Db=MIc<aQ2a<6#P%1H?X1$@h zp>}9G=p-sUW~r#)1jmV#W>U*h4+nZ!B=7Tx?zhl_FJM+w?SA(Tr`dnyz{&w=Kvf*` z&VTzf7YBQ;9P>$QXG;rrt8>!`KD0N)C+FBFykKdZRG0JEIj~}F=zmLF_-8pt{<2zQ zaHP~XpJ&^~w&Y&UpE!~n4b7F2u()8r#gH5jVs$aGSxw{ONP*jYce}P&W_3WuY7{(J zt-4mq-Oq7eWB<npJA}*zia>p(zHoA)MvstbK~xfBhCpC0Tq~!et9Fd$ze(Bp2OAYw zH{Dh$G=+H@pFjQ9$dE!&o^vEHrD!!Qpn0dzP8fK)z{vOrKyoGqXo0XK+zSo?hA}0E zYW{Q=QF{j@IfPn)dhj{x_7^#v^<e%Tj5)86ft(UOKnO*ry8X8`o&@e7y}hN?At=b` z=(Pe~oP3DSng4khe2E~ib&n-$&97pgJb#KK7NgmHu%IHf)%*K<2<&&m;s`Tgf|Zox ze%^5wD5&N+{#Jt#PA_sT%2wp1Wq^|xVweu}<3NyVHOa1@3i1d|4r?ddvf!Fivyyn1 z$d#Z)$B{?X;<s_cF;m%Z?-&-5LT_knqLra4tSqd3LbTy%HI|wVVKQ++!(ow0eQ6Lo zY|dMk*nzHUrK^m#8-)UCdYcph^HQ6WQUMF^bN~S)25?37<}th_-lHW9I6P-PynF_Y z1p-#@)Y_u{BH2ET#B8dv1$ONM_?~Nx=EzW{CUMO0tU2)E>^O!$%4xc2V~ES#&XV3X z3a@p4e@8DW+{8MA7HxF>If7FhZbO+p=?r3eUnE2i5E`j+yqWfIn{gGPFU_PEE$L7Y zn4-DS^WlScrPaGj3nX%2%pmDwAwurajGCe~{}oXRXA=G#EDH5-{k^c9kt*!oY~H7% zr=ai~KHU5%wxI*BG(23Md%?n|GXy4K(&8n`A2m@WS6nqXXnVmNC6BIM^c}jT>Uc(m zig_GIpUS?BiUSO}m~}yS?BkU{bW2}oXsx_q<{dQctzXs(=1KM1UU=yP0Q{KOABY)F zI7!uiS>thtjWSMMLVKU9NjKj*4d4X<W=@j;h>n)M4;8Ke7uj3=Ohxnfb6f;(R)u0O z7#a_le4alF<@0X2PHtt(nJ1_DGR&sJT0FwE0TBBLUxP=7^h<Z@1FLs~&y{3Fi(nNZ zYVdn82Tb*dG2&o;?hWhh;Szb8d9007MiJpWfjrDA+Ih%t`~;ag;=^_QfdOkpqPqwP ze&kXCGP?d}-Q(nqe0J}oSt83NtYU-*l0Y5OXkF1w;5|o@PL06-JXHsR1t1XON4^cz zSHkz_H@$i#9+Td%Obc=y4?DZ>Ir;ehwf0&m=8THh<NP_qGjYx;EOa<C9>*{}Oz3ql z@nyS%p-D`!*1ijIZuzsgcH&ilu99rY!r3y7f~XrV65Xq!SvUAvtBJ-6Nnh}#Jmsje z*}4}A1XH$$jm9z0PrM@^eT7*DHNCVYVk%lG92+S=ArhOhN_a9HgB*pqXtftA78+?= zMh(QAtV8M<tdGggsp+F7A8h$9n#eRrt$;usUn(GuKl>9T1wNhTjlzuB7h&i^*~BgL za|qw|x1^3MaVl{agIymNh9$yC%E>D+PttkZLk4$&FWwUtu`9o7w_+I$h^5}M%%hzS z`w>S!lZ!!5Z>c|jIT12Eur*cZVavd8=ABA@`az8$BbJ+=;T{bXv?zV`Oo*K0PbhZ( z(K%(-9HPRHqyRo_y!%_@^_cK3C(e_IcI}7mWrwbEwR(Q!Mb)%2)kBje6>M$G1-N=d z2%MQ1jxPgq?St$UO(riOyoH9M@LeYkLNAwfy21bRiU}Ip9Oru@HMXnSh5q=CpYYmZ zyXrU8Sp`CNxBpyv#GF^kJuXFu$4y=kN*&B<EtY=YhoCQc;$W&yI5+HL9&;vLkmLl* zF8$@olBqVWj&_fd-+2E}Yez4|?y?aX%RMIUFOpeH4LCnTSS&?L4+CNhfmH_bY7eq) zitGWMu^1*hSzm#C(O-{q5#^0%SF~;6=_HnPm}<(g+cMEmRfFI8H!k%DOn$k{o&wae zV2Mg))m{g7!vh`p<*Dgf*GsqE-uXM7ugh}kOTT6G&(eyjRta~WP52Nn*mU_56zI9# zQwVmHGw8$oyGY;Rh&8CR3?Sn0I>JklKy)V(Zle8wFQ?1pBgqiih~A+Yu7N-BKOaBX zZ)h~gDquqTb6};*)|^jkj>5>F@GXYhXUJ}5G#MuK2GPDwm-~VUu=bpNKLWf1H#dJM z$8XLEuFEmI5S^$dEXKt4+swKMB4gJOa~1bLJEbn)1z;K$gvGEw9)4{P-^SaYFAB;( zTgn+K3qhCiBeV*bn3v2aeQ5(s78Z?ln?1y!h|0Z_a*FyDs^z`LET7zK1&=JafSMsG z@$qjmfh-ZxOCHJKi6<3nE8S%AEM1N%to*_p)a}~wz_OpVM>uT<56-O{r2g~3@b#>) zEAR9}aGc2k5CyZeB}oC)&G{9BoXjF=&S%0S0e>lCYA1W#(J704B{BNKUx!{j-_%36 zN(c-1p3PQBObKWwdH7qB2mK8km~5v8Ez2seexZZE2r~oP7HA0}M{BV7<y^A!&amQS z@(On|{4TlKV<lHX;tQTZoVf5G41F7(W?OH6;LY^=|1UNVJKO)f2AP>TIsUiT;If8{ z{T2sO&!_rX8F-h@eX&HWkTE7W99nE3UdOO-vqi>pBn?^h_0g((n24vTDJU=Sg&hM5 zH(uhuTihAA6j9e?(NoIttM8u+6IY6cG6ON1g|iEa1L;QLbE;)*R3!;@)hCHA41ngB z=kw+wAU#>05;|21>u#cQvxRwkB;~b*0dliL^*4@r`J}^DWYtbR#x<*?n-iC@hq^Yr z#XG#RcE*E8H<=t{MV5qsx*9ugZK;m~b7h_UPZWyUkx;^Ab}_cafO<fvUOjbdi8h^B z!iag4&ge0|jpTPE1k0RfQ@+H48U13@&c<aZ)q(b*<nh)MnMMS_udb%y8UG~){|}~2 z##viEXt|nM|Dl~tcsIjlZ+^n)H4qA0)~s!6q7-t^jXmheQ(aB+y`1M}0s30a#7)?A zdHO>u8N;2b#Sh^;=M@iUG2(kujbGq!DWaTHiAPT<GZR^gc-Y$*(hDt)<SX3!Om0Co zmhd@aPJ1<<40l8FwdRC)s*5mPffxHj9}0sx#RZ8eO^ON0I#3i!D7NAmxi3?o7h>C@ z77e&hAY@zQ&`5{k@0N?H>4Yv~c3~VGSxukQFZvopSb6gw7Z8Oj!FiijGLcI}?zkEB zMJaxqt@u`*+aVD#x$so8qi)c@x&NR#?@6Dk{HOwl)IU>Kz-3VV*m~GG<xS~SsWUho z2>|OmIOQjL5Gc53UlAH$*Yn1)BorEu1U==_>Vuaums1yxpf){0thr_h7<FkRvi$T; z$heUDC9q;p1&bfK@JexL9Dpq{Xb}W?!s+vHMGyN?=-xxg^^_Q3n?b6;>+(>|9Co2S z11~5<eQs=djnr_-@1AW>Ncf_Cnz*`#)ccwOPR-KOse|}>!!vaYhc6a$??f=xmA@)A zEN6z)^1?2C<)}7I*$|EG%@t#s3@{BZ?a)kkyifhQXC9)9bOzCh-gtJMoArnot5{n= zJJ<i2LzvX#DfSz-wsR7Q6$CuUH1eAK4gNg>hDmr)$S(OwNP_o)7-?bCv2%};qwcjF z(p`TQ^YUU3k%^z*u@VaJ?bVAlY-TFK$;l1@DzJ+<$`vM4EaS?lfi^diERL^6CpV>r z2;^uQ;H9CVC7%D*YJaQxo=|XK&hN|KNRIZPkMJTd6?i-ZM~0m2%AQ0GB!zkR-h<73 z0nlaJ@B;AxXj_ynYN9A4MUpJSd!RtBNR-eC()pN$D{0|^DnMqL;7(H@o?jj~bM;|C z>K0=_EY0q6cY)RH))}UxB{7JTzOz58kB&&Ix7<zkA}{V?ocC(t_=HLVC_7|J<`sJa zmL5q8Rp<Amz^UQ9{!@ODM3Cur9d2t|S=X=ya0jr5Vi<oxgtZ7J%A@Y}22l%6F|&xe zZ6JHqdjS!-W9%}c2lamCfJ)gnQ)Xh=+IHWzQ7|gT$%)jS8@!KY31`TH#V*%u5sUB| zm+#iToG;Zxkf9(65>y~*4p4PLdY(^H(Sbq#XsDWCjZ%kdB%`iDe|Xc?xcA^4%pV+Q zto{hvVYH%W@>#AV9#Wzu)?!3;%3qMaS8c5Ssd_p7XA;f)|3=YV|0kDbA!7Nj*#FP? z-}?V)iC9?Kn3?~ViFK2gsY3Q<1INwH%-)S%|MqrH|2ChXgS&eg5pkP{gF9s#>K61} zLicUEd7kp?t-A8mT@!z$x_d9Xs)$fw(FBpri2+EmL!G;+fuYF>_}F+Q*BbU_BNJ-` z*IFj926jfq`aTtvXinfrjT*v>(MXM;9#C2(x#0ZL^WZ#o-^A1us0464*am2hK(ZMS zDq{d(Zdqe`5_t?HpW_FXio30iB^|5Nr!4RVL+wQ{6A@DpQi9Q(7FK3efO!oI>qqqC zkbVFvo|&WB@y?;X9t3MM3)lqf7#kP{fq+n$7N|LxuMf<^(#9IWfeEq<xEbi8;((?C zND5udm0T5PB(AT*E;bfn=66s`MO98Wk${MzDxU%Y$Z8IhY*}^rr>he9THsB44is&P z|H=Qs2kXZ%4O1OeZBY%y-0;I00tmJb|Ln@>ney7-@!yvL#2aTbqPnv=WM?l5P#L|h zF1}|*IsgE`qTkZd!N$*~$HKS$Jt#G^JO;UQaA*Pc@!<ir4fIDJnclhjmtB+E*9-d9 zjuMcaLOr(w{x&K#uy0?yEkP}i&3{z$D|7V^sm9-E<Hr`k0T|?$G^V(IQoqMZTG|PS z*O=B@J-@rY`#ij$vc574w(pE_eUxx6`oca)FrX}}@i7nY;a7?K*FMu<5!3OFD<ii$ zF0X#ne>c6pJ1go{!0It?l*6^oz23>u^_`al$-vGO_G@tGcs56K{g*rmQ!PFfNnO=A z{?h{B4dEFccd^FW;nneD`c0WzmyX96kd=YjH!z4`@MEFm=*_AK$=ivz!r<UPL234^ zNU08K&RFt$VTJ1riRhj8o0_S;o|W-i-jR_-n$*#ql7y?Eb>(j(AnNd&stKeEJOz}G z3Up>^HU31ote^8BG4&wvr3fNGC;=%E&|Y5+J2yLl_jV6_dT4Zo0M^FS3H<HzQ~o9o zHaY;#)X3ucZSfE%6!=No(bU}z8gOcV51Hg&{&V_K{)?lO83)boT-W*xk`6q*pN@v7 zBaj*R@jDy+t<C_=sjUre%uDp_kMY!79erJ8)BUq}(<{ps=wGJvOE{y(fTETw$VyJD zt~}XW`O&JgvHbS$JoK90CXkTxAx-jo7H{2;?P_$P{-d!G2#)S5`?vV>OiUTqJ3k6G z;L)CQPXhiY>Q-X^w+@_XT$;wJqI~XKz4ObI%+CJ8z|7Ph*x+~%42zc+*SnwD{|Sf| z60$G+_+QF&K(0SKbim*Fo&M)R@V&E>3rHq+hp<oQgsmwcieiDnUS!+=sb_y=M9hHk zx7`TbK9dLgAy5OBZ~dWxDG&pYA5g!c`Zq`uNG8o6P$!`Dsvlqhkj?*IMO!{OP2Pzt zei7di#`X#CNE;pn_9RTw{0092C0z>aje2hV_y!?v_HyJ#l?Oixv^Dz7IsU@_oZ3=- zYl`^GVL$fPp8CH$>T4`7ulGZgS(?7w+kAxo?W(VAOetk}9F3^+857X^{gD3^KvDSe z?)crOCpp+VAMBf%hBh$xHkcY1pL!Nbh?%|>@R9q~OYx66l_30v{asfEBAP?BfN5<w zGnl}%$yq_u+Go^b(}kAmAM|)Zzf4M%1sRe)ae?HI)%Zc6R;c5uBPWV#SQGjaslF>f zKG&lXMS`{Xa&2zy^t@D^(J)t2-`gd?pV)S%kqhz9OCj~kNzfFNdb(a#ufPra(?(5O z7#CU4_ewOm^xr3SnCk=nGf#?2ZG&w$(852H++ys(b&P3e?EkDef6ororRQ&GQihE- zd5=)HnKC9cYgvei`c_=AaE5Ay>AC{5`!P70j+Qi_-9ITC1VY=abuR?0*4SNInGt;R z?fPH|2}`a-Mp_m@>_q^Xn*_C8w`=c&Vu9o{n}V<``}*N?z<!!v8I_3K7yPmYA)yt` zkMa!z>H*Q!prxybLul<Gz`FIW)>CZ8)zK1YZrA|aMXL&Toyz<r^pR3-t;+~h(I!Ot z6Ow8FnnjS2))sos!-ebvYXdOQIf^w1M_VE4(x)R@)QP3v$EOp3b-dOp{oWGgYb1(r zPMh}pCx8`Xv!b!yfK3F+K8E5bXDPGqP*~8a{06TK#dHk+mI4zJ?~+pbhtdvbBd-94 zq^`}kdFoh&1K(SDm;P8!4AKI|ABd}d#4*i#_(pj^qT&NLaS`SbOV`-vkgZKkJe7f+ zcdx4yWdmSHeB@gW>;L34>-nD;i6|7OuZY`Ap4N#C0yLI9dZF22&QiHB<_-FrldrW& z6n9=-ZbKqSpq<uucA%Y{4uEpSzPQJY=h-aaBnB}^o|(DEL#5Ve;9{_Lmx!G7aspJq z&FISEpW4y(db-pA1-JQjvT`LvYN%6SLi8zuGh6y@Ex%Yzg|j?UX^ilflEY3ONy0m4 z)qYzhF$9}GVZzPD)t)3<{_D<+^gi*3<P)ddhou)#zy+K_A4^u4Q0W^Y77V^I+Qf31 zhcl?uQ_5@%d5o|$ND!+h>3TZ<D(4pzv!Ec0-M(^KKDA<M;Xn#jkGH0<R62}Dmn6#T zUzPtx_m&!$iE_*i&<`aqFk6oCHhqLnOWt|6f5sm&b%n%UJU<H)ZCtvUSu?vZ2>V3j zvUn2kl`AY__W-jFnBN$bbqn1ey>)-iw}_{*VxS8v>%z(2R1R^IJRGjyY40>aY0Tr< z%U<r|>N_aKyhN+aHu=tY{*pYVA$)+1nJE$zTOcMiAh5gINLn2fHlsqQ=WVhc*s409 z0@yAjy-3k)+ZEh)2o;$TE0NnT@9l7mCFw3qm?T%4s^_cwnKJibEwyO!b`Fa3sWOP1 zsztB4zvz0IVd25>XlV;>mrWLAGhQB`<r0Br8Iy9f5F%elg&|FR-(gL2(rJ$v5+ym2 zDGpmgo>bpbg?fHPMb1j}cO@!pZ6)uaOD<iam8mBLVsS~zVl8-~)8SVYO5Z3bymg&p zC_7e88^U_Gy<2rjtmt;|v-j-yUZE=d;MQ2`a!<q}><Y2JXs8$6LqUVxx8X^~vVrOS zaEXtPR6S&i;sviJET4}pM&W?9{)Fz0$P5$z4%=ok@nd_1poVsfOKhCq3~i72=|jqX zADP<GiA2qF&N|ld^W@WB{Y|hADSbH+?R2FwcuC9bI_<}$i+FDbqazrIMTcXHFwxA6 zzp%1S?A^}<M~UI_OusIYw4x;SNmq8(hL~l$C238QQ-zTj#qKyYnfT|sz2ffJbVn5> zMXgnTH^%+$P&YFUW){qYex7(qinDtD$AQYRgWRm<@GtC|p0(GJ-Vf6XICTH4*FQ~k zOY>gEEUNh#c_+h-VOkGzc%J5Cz0=xh)?3YdU4zs=7xEpe9JfZ{0-pzTERn~~NMKrJ z;eRo`=R(IYkX5<%!?h3B*pZ=2aCNE}q^>Vc8ZX*(57^rY1Hhnj6@LZELaAE;B4E(7 z+al-BL&^qNHgOCD_5H3T+Dpqc$GE%aX~mc;eD}<6GysIjfOgi7x1_AhQi=`M#pF}N znHslEHc1-S9BQhryj>KMR&KcPG23?^GINPRnvax_xjdXL%g=EY>4M$KomXx;0uk~H z*49fOi1|w9NWe@&tQ9MxV`#TZV#=qc>87e53?6>hQhKy#H2UU9Eei))ROCd_RGy_5 z@Hd4UhrMUzI0g4}6tZP<rAq1PmQhz7we8Dd%vSL^D#rEpcPE0hcCO>=lc*%qn#vO6 z*tyzIRS(g5G6XKO^3h9++|x2&D-J!rJVJT4j>*tQ`b=v|)JSv;hDawod^qM5S9+}E zp~yy5{W|fY-J|GVuxu)qdTC|sH`D7^KSoWS*}SUI$ZU^~WrW->QF-E^FBz3MWZ?-L z<sEFLM&C?w4dU2F`+n~`7$ulGZDredyc*jtse#B2DUxZGMnw3ga)Ud_blW10)Ac3w zYV~JYiW=?*W&&33eKJw|tm>@JP|6FK(u-1p$QDUzn`$0Z5@)S~9ES(7KdOKDgvzeA z`#6%^R*?>3qy3u>m?$8^;zcBaacdK9z-niLslu?qByBbJi~T<{+VC2WP$66^jMI~X zyHYEb-3P|E)>m_%F4**<SWJ5#ZqVuunU9wE=?39)bi7W!2lsxALXsLmNzWKIHh2WJ zkgH_>qyWdoWW*(V8tO*w-d-!#GdzHE3KupfHk_^#%YyO3u<8Wb`k`oVr0Hm&+visb zeqNjHzYoY68imlc%)C}|#U9!q_I<{*<P91GzXzngwFnAjDu;M72~_NZ@0+i8fl<N) zo2dHGx-tsG8r4l)S7~VX+xgDXP6OK_wbHq8b+dvjV>*uNy^Riq)0w#yT_B~NNP0aK z_a#L|l}MlS%w#1FfB4=qzb9dPNM-u2$|mdUnkf|+fmkd&70`M4dK9mHk2lg|Y=@lL zbj)6W?V!KgS(NW@rnd>KE$w||EWy!uh-!X5ty_SKKWjiFf^0^;ZRKwPs#&!fobb28 zSnS#n&=VY7FdQ;p$@~NjV)Zdi?x=wY*pFMnvixp+4@&5*c5!I?rx-vNI11RXpo?>I zW%F#HdP}q0QWAv9Q&lux<&e+%xmDlIz0frFRLxHpEj`(sq-N?BW^NU`y;{4^+q#e> zl&PtE^xcLNJsGp(2EdPo^~}m-eh<7b)Uh!A9Zp-LoG+|!)S<0D+GPnu7uxosCTu)L zX<y2N<b*#%^QqZd50uL<uv=xXDp%&@EpK3hj7SJFkthRXO=+!U*Z0LMgZeogTE&${ zvK#L<ftZu@f4qZ^H4-W6xo|CL_J(i4RrAZ0@5s`KsRBdQ)WSQ`lBWxTj9t3Z3mG)p zBGL3el%@}tLjC6+DiGrO7nTu~I(cd59#6HVeHgd*U+^9xzOHL$ZTgf>Wiy(8*%R_k zySY|_@~EYzY%+4)_=m37mQ!YYSz>gA<-Kx}@B9*cm@><7uL~P8s%)^VcX(wS8V{6R z4nQx@&dPv6M;Y?c4jS-MqJ21u&(5*k{;iuLa-h<7$T2oe&+e3FJu7*K4ji17yV{Rr zIDX22=Kc4*M@F(owq-n?Cn0%`-8p$zv`5xGs7*nVqcF==MxE!Aj!%|<H7CGy4_*zd zN!Z4@c;kVG;LjF^PCNl;T%g|Rk<og#cShH0sA7i?Z&<B>@@;i!1KJm>-yiX5FoH$h zP45NE3sX&k&p&DPvBpS!G@n>7s_d_Igr!Eyj$EEZrGM=4Lqe#=5MfH1(4oz))WX&Q zk8Y5LhAIKxw0#!ze2*uw-Y|-UF}~*XsFmfswK<>2>&@j+8LDo5OdofN*&w~Pa?5^8 z!T9)W+bGSRW721O`?@E^!K@McLTj4D5Toj$#3b28LJU7JtdqfAR}$%gNe_E_?iNX- zW<E*v$+B!5hDU*lqt$tu>8km;uq4AX4c(hfW&t0ycOsfs@W@l=24}O9PuZ;aH*$=* zGDf7Ty`{=9XQ6QHcj|f{>=>-fYAOjN^n*Oi7)?k6kOL71?W5ImJovAw2rSS?+wJz0 z&B<Z$5d29lqe#yhYDG$_jE$~OzZ4`?O6@3iq2m?OpA(U_JXO&|Mlhao%xEU5bYWT> z+SG`#6QfN&ku^^CYP;Q|U}+2Yi=WbNFYBVT+=y7))M4aOu2QgC(+LAt0`>vDOqbEh z+(Dk@w~l&1BFGP*^=NP?%N_4g2DKdQjatR`06Y{mPvjHmKE|P~BqM)g8x&~FS^N%} zWKs6TuM8K4m&KZh%pwFkQFmwH8<h>&gjP;=;xTih&u!+b>Q#G;#R~;=gqm1tb*MZ= z8>rom)HqN3#<jg3`w*B5TQq02gWU8<q53)RPVhAtckwt{w^m<GpT+P2NyBEe2CPWp zhMk^)y!9g(8H?rw4PGV!&#q<<{)h5Z8$~t6Tufp3rI6f_4HKXF#Pw*{4ae-`n9~DC z+C&wZX!01Bk^ppc6d?k_II{zM(BStgYyeTD!=Y>bJA=kDn>&8z5F`w4Xz@z2I-*F{ zjIelzNeVdQUg^+YvM(saiF}asa>lP9oxf%npYxS+JGbPN!wPcoBNG*0JqT-7-WUu+ zm74)vK6$fb+}4tv&zT-mgn2k7vi0Vi&N754rM$|(`%p;#_n$oe;sC|90qt=vlQ*L; zlxe;V>O-ws;=Re_S^U2=XS6543B!Y71XP`94za*Fk@2cV8R_+;UWh;7)_}S$4lC?) z$OAW9dh?t_(zBrE=W*9EJEo*?M(WR#K$$z>n#j%2=2Jx{5t_6}0g2N)$Ge6I{S8_L zB;?S*8D2Y8tco7FrRS)Q^b3jw#cG$SLVY}eJTqwU3anqcB`w_`9IWug6U}nIWa)8C zl>Tv-v)hiRC#XbK^d`OI<>+I_Uf%Y7z`A`J8vVFNOaZ4|Q;W13wXv>-G@40RNl$QQ z{GzXyLnFj$aFOD7Q4C5o!mI6Clo-L?Fq#SxhMFWH&0?P!3e_6@UvAscqT>;ONTecL z#m<^LqD!-a)Wgw{BfR6QDm%UWrl;=5Ofzq>dMVM@7S~6P3J=_9xw0?e<Gy?DR{_I! z93|BzRdo8i0&BpMYv<R}v0JMs-14lhc!;iT%^jmn;Of}Vy-;zI&=sAx5BKg33t?NI zh8lwc#XrC3XYJ4oFQRJti0)KpBDqFY5s%{*y=HWDwxV~zggsr`YTZ$3m*DLaN~&sp zwi%So9;=soExJ}W#1QBdp501MPM*dNbftC9eqj;ck_AP;i4x%qNRG)sXS4q`UIFS1 zPs+TKEJbfQJ8gGW`qPd7{gj)rXV;<FEh1R)8cLJ>Fr(1?UJAi4nf5s6NgV7})1dkj ze|664+Fk>sn2S5s{h@%{#)G@FrO7C-q|T21$NdiVRQYcQZH>zSNtnXe9DY$UPw47+ zr31%mw6huxEp6aP+lS^_{jGT!@31}TxQL;l2uVeltmGkx*$7vyXd5-_9XsmJ)8;~| zS%;}Pm5*JDnI=+HQLKmYH*ku5=SbgfbY41J#@a(sO$JZzVdKqPSP-3AQ9yNrmYR>y z)Fe%<MP{oMldp9Z3xX>;$FMHQ6~b|iZNEoQhy$XjgFU0YItjiw`J-nH`f450E>2QK zRW{;xm7i0Qg{jK!+^TfvN7GBrAaNRl`6v8M+MY}iGK(zJh!e!2=+7!)#xvF5w-ib8 ze9&v6Ax?falYI4~hi#rGz3N@TtZZna6RA}qT8<5~=>#11)xGPxkp3^r91H6Y2Kj#X zSuMX?HEG4T0tZvN<bV6U7sa$R<~h{{0OsgIW2*b!-yOnUw3*Tu3l60U=S_aEAT;is z(PW5wm?hAFCX1(uCzdwnv+ZHy3%v&j{hFvZD-L6kshys`UgKVC(@JWV=LIJcen#4D zSwb*R7S}$PBS}&4cOf`hLa`L1Si=oY(_#V+F?x}mF6OBms0SGtxRtmpjajH;$8}wL z0g=aHf2~^R)2NWs+=iYPl7BvU>;BM}Oq6aHckRk8<Uxt!$^v+vv4-ctjiNcf&tw~A zJmfg50-Noe_KEHsR;)V7@mWgPDtgXf2M0ZB$1^Kk5kH(dnP-nFbN^V<3Y?_I{!?=k z4wF6&U)5d4utShm^;U;4%Ct#)DauKQqSUNIZox=eaq*ICDk{c}T6LzSr>A}2bTdL| zb%gETFd`3St+&X0pyZ!1U*y2hv)98}A-=Rk_9Tr9{Xq+T@1v(-z}el;f!;gJPZ^I< zd9IA(9njE5?v3G_RA=(?%~fK@BFBRnvC)*!xIcHHM5?ldBOLpr$<x`;{W;NUeHSv^ zrmOBSRHQ_=SR7Utq*!mRN-_YX>-0`^S&fm|T({KJW^2nMHncreDZM|qz$(*P*{63Z z<dI$qQ7F)QA)`OKR}3!k6F3IA9D@KjLWA(-nxr!`tBZZ@E5h_0O&w+COl~9M)K1c6 zOcD6p-8eVqID4~sC{UDTrcI2PNZ33dtd8YVz>*xWQ<|qL4X#p49MU#SFXu4hkSxxp zLtCm)caG<cgegMO8D6+&3)5jE6s6WeSt?**6uEH4;O{J<Cy4M=a-E$=)?{<d^WGHq z;2*L5>ylzsenn5j(2uQuMI!<J$jJDjf*9V^zjNm#8&`COs*FNhKAF}zU&}>&C(2L} z)R!Ip_iM?14wP^2B~(7CGW5|qcvJG%K(luF3@-BjW@v62{Yq^e;~Ce@=SBth5qi!p z)jhAc8x5>yX~@$+YMqDZEgtmfnBu|a9QI-Z=!MmKQkr9~mwH?jU`Z4MgXC>Ir6?z7 zD&YhiWE6cWnt)525gxr%veFE>i9z9Y3Tf^FoJnY^m=MnikX`jxDD_dq{>2ta)b%)| z>iC`NZpD8yPe-fF*$cKVRSe50Sg~cMs#oz91s@ZWX9(>Yw{Bb}&%OYE)=|86>J=Ae zd(QG?d`)^`d;pVzJs`HfiPoxWcpJr-wxYQKgFGO>JwHm&vq;PfH=1G0lxn#VIBb2Q z%!j@guf|-yYS7=WRdrxsGY^7#n*1<mtbRgHr0zHva(f$ARLC~Vf=Iiw9dOnVxASR? z>TU&lr7F<v%r_D9v`T++2QCU(i904>x`PA84#bAfY1EYg2rN(vEShSi!yO$D3^NwZ zKs==YjfvX=r`2OE4Q|YlPym^1ylwhHznI11C0N@%UUftiZRGf=l@nO`Bm>J9a4Isp zKBQ>dPT@Mrvpc^Ux#^~}8ybcP&!H|r$_StJy6Zt+y!FDF5kkQD3tQ5!gYKy*Uw*jm zHX1;a3}z7D>;qb4@;wu1+hf-hsbAH594ppTV@4sTJUjAZcLKDI*YSCb1>9RH<7B!D zJ9#1mF_~q{+vhoDv4$s;XyFyL*Okm5ZfMf#*w>*F^Xa<S-(wMlKB*WLYSEEtaicv3 z(!!Y9GR~TMUI-H$Zukt+DGU@w(=Wv_`J7ofb{qiW$tr{dol(#0<flk&x48`p>93b= zv`u6(pRDDhMFXO>p-@QdS-OLtwvLP}@u0rLi}+QmZ}N7VLC|woo`=wKrOI07fx$Zq z1N*2Z#x&De=20?aRn<58+lCExgWOc>lHjzE&wA9>D4_U)8;YaqzqsI@wUMySjz&1U zp^<apmNa0RRP_)rbSj{PUWj~}ek+z*reN0Bn!eZDiInowbI;n*SmYM7btQw>YgF;r z3Zh5d0P0u+b-jI%47QTeBYSNg3V*{cm%PY{B)=v<>=!{^#0$V7KqfZ^yP9_BLueS= ze5i(mhRvLiiL4Me_co=XGvpy$<V&o5>Yu7j|LP~*JF^jIMww1v8u)wM9Ew{QJah4s z`u!Y%$rrMMk_rdx!G5C|-l`cz!@<qCq8-DzQ;3(0@y}V9?-7pp&e=n8p|KHx^qPqn zrfLr)l1xm%tl-uv@lM2o;w$c9liQf*S{0lLJqoYl3|7f4DP?bv>yGh{+tn0QaaL4O zf?;R9mKi@Kqwco!yHt`dU@%-|gOlQZkWw*)h>}+1tKez*`J$dsgx|gznU}0~r$911 zuMDK|e6R~)XOI_CbC!Z0%jL>jaaGR|+K`rnuz<_QmfgTPN@uf{lAXqfn#p|+s`Dny z1eX~RDEkjDN!Mi+Rj;tQ7aYi0k7KQ)62g52F$;C#w!jySd7MjV$!y`nT+Zx|6BKLo z*n(S!T3~2B`Bcz*u{v`T?!GphDA?Ka;eO1PaHl1S9SGgntVE0-u$7t=ofiQ_!*yC3 z7TcR9ouF5jv|c9=H`3&l<jVb)+qOliPgE4dxpm5Z96H#E58U~AR-=8LgRqBDS$Tel zxMtOXfNh0$6;o8Rzd5*%E$ke(16@69Zcb+kidpllYy>U-p3Xfz%v^I%%nSHcaYzp< z&^j@A_zJ;1?bRB<qjx5lh{v$c7PYXLd%Zbu6*eSVf*VB@<QNVCJ=BbK{*a&mhd31y z)JKX785xXE)XtapY&b?DR8@{BVT8rkQ@g^Zx(hStx!I2)=uh}@t?*WZx<F>UaKCOB zu8Vt1VroIaSr%P8q+_tSpuZj8oJWTy5>yn6cVrM}TrRWN_LO91wVG@_w(Y0v{==BR z+Hwfey>zKdeHnN!B8CyVg+$C<4!|b*NGV+4NDXSnx|Q2~MJ@~9XeE7bTsHRO#7{Y4 z-opT7I&~5&o8Wayvu>Aj&`<r}E4Up}?$zRjRam^A>Quq*z}6>N&Q9x(e!(=b+brwU z4_PivQ1aTYUzIpL-EcEL+354^mc9^6%sEDM&f#9+b&rw4QTE55X9QT){b*C=c9j^L zvjgm~fDSE_*PZ2?$j2AMLfh`Q%owYft{7uj_zRwvgXJ|qK89yrFa|`MK=`8~<Hb+n z@oEj@s~7CL6k+c3QnDI(1wwdV6kbPrYs^+?X^a*7pqDQq!qY;~V@1qR1Yi2$2rCY^ z<*N!{NKREmKvYji#ErEMqUk1P1~p&4-ecv&?cWgPV{p(ruL&q>j0=!B3aTnCEX?qk z0D6WKUiPsc{We?sZo=PR{zRnByx~y?l!Bemu~q5T?}W0oZT?>T)Rva;1QH`C^?KL8 z#KZ)>>7j+re`g%*C7Zv@JdT|3ybXoHG9FEqD+4<DC=O4{$GH~567s70$iX>Zb7Kl) zfMS-sQ5C{BmSn_>r_sQT`R0wDs>OPm8}W8U?N=F{pj5g2qJ8Sj`74*u#@TH!dH4_{ zmUr3Al@!<DQa80$<8wPmj&n-|i%pQ4L)@~|glSJALys-#(`8bK@0AJ7?<aDnZv2Aj zu9?ArOD<$ettK25S37Z35kJwWo=Z&LUm48Bvgg>io#Wm2HQ{3`(GtgiG^LMGh-;~- znT83usStel+8@hvGV~01%JnN=!Vpff$o)#aD}NWX+*k?qdW}d!W7o4tqy^1-KTA3m zP{2k}QMLt$rEd;;6CXT}waN6Ew$LuUUnk}}z9*b_VpfratB%%x(!_hRMD7ca!|5c@ z7z(R0WGS6O?{^)_N&gsqFoej{ckPsAqbC_A>J@sT*&DSykB?4xfP>oJvhGGC-XxR; z#im4<kZ~;E86GU9*`y0|#yaY2t7@4_FI%2XcBbEKa-lexAGl_MC3>Vp$Q8a8FT`pw zJ|eCQ(p6*2W2N+^j)XEU#V^|5+J1jPNj9(Y(*4tS?a_?q%q9)(HO`$C&(s>2fh(X_ zYnp1Dykffb3w+Ur#W<-r;9|+ZlVQ#EKkmZ<i7V`<^yTL|^<83nHxzfu>4QF|8i9z| z(qc7r0~Ka;_w#q+5TFu9t`Lg*Qkvnf8>~^rVL}M=o9$AI%fenn)jfC5MDba=ryaO? zWcsCBQ2Z5^V$cYiWyD5XkTM!cS&0e&nvk!4;(o0xCHMVAgbq5Y!9deoP8-<{i}kjJ zl4&f;Yxa(Wyh{2YBoP!Y_8NQ<i+on&m{;fzT7i!$2XA~GFL@8n(U_^lnEc$kY+CrY z$L^B30^)4pzVTk+%LjmbqY~+kl|^KrCZPaD)%{ndx;M<?)rBFw$~ZZF=pD!ipikT2 z5I{~TGl44M%o$gCSPClV4d;g*-op8&={qSuhOxIc-(Tq{rS_seUqRP-z=(ulQ*<H! z4N4$PYD2oD^0*!dh{#!iD^;2kYloHU64~e^$@y`^r}bUa6a9@&mGw9JU8t8^eVefJ z7i^d=?%eyO{eKv{hhR~3ph3XLwvBsi+qP}nwr$(CZQHhOTl4<KET(1_lU1@#RZ{8h ze4R(l)Bek9YjK8J2G*|dk9-xS4w7M{VHtNuPj71^n|vrm{&)Vj1<inF%25k==i;1@ z`zQYR0Z`Ybpe58LkU#u!_4L@Feu<RUG*lgO)Ct>0`eh<&I-MG)D@JHiM9z}?H`dpb zAf8>BN!Gfr>Vsm2CcNe2(BH|cp<yg+&e|Y?-QAoc=det>6hYt0u)VyvxOgnx<t>6@ zsjdvnpQ814hAjlf`+Pnc5Ht$I252?;HARf4$wlFF#HHmOEbE_e%azw&VV;f*w525Y zjfb|yjn)k*#~mfau1eT~u$D&rEOq(>JQ#du4CbgAM8E1A$)o#0?RYfU_$q17(~SLE z#hLdalojv9tg4qWlX9MPVGg}OmoB|yL?S;%vj-kZn@Vc^+#sVjg*FE}V#h8=WDIK_ zUSk2OBC$O-ZO4mDV_PXYIB`uxz4aRAyGjIP)^3>&_XpwlW=uw}L-RKngAPDdM`vG% zH4}^Ce`z`MDbdA%nkvIIk9iok{U~%JrS6hhAF;uBFd6$p*J<CE>PpZIGhmVP5Q|Yw zbs-hre(^{{BEEZwypHhM6v_lyz0vjO?G~1<y(@VHYk3bt_HLCkFKMj&Lr+;a6+FCC zLVl;oZwJep+Q%Kn98Bt{XSIC3Y5k0Zkh`Z9Z-n_)jXTZf?toJLbxX*5r>hjo*V7q| zQjt!BK+e%o>Upp{lv?FWTdTN{vp~ZMA=1%{G80gpTvDL!Q@S}eR%(maB-7#!gwW1@ zQ-)Ie!fz3gUMWxHo#7LG1Fe;YV_>F0QI5U_j5GPr`pkN=N9xiF;?Wruy7zu|WAq*G z2nZI`M`w&JiNbm)g_V*wu|~-C(5ksL8uFYqCsm11d1pTIe65w}$k*+paZ10?t_wAO zAG_mQ!h+>D&CuKHND(>00Cn!LQfqQ)zu_L6{OR7+jiGLqN01Ts&CSU7UDEaUdZDU2 zvmNlV4=2?^u1EWSWunZB{%a{ZXQ_aW3tEYG)_2g_MXl>4d$u6XMlh>J`qNbiUG+5Y zk!b@h5Wj=JX0>)awWZbl^E<v77C}Q7E$xZ5i!yV{N%%?+0)vm}V6pF4w_!E0;x{pm zWNG^va+(^~5%Wrb$HAEIIfi^)YF2z#6JD6qN(I2U*uMKnqLkhO1<=}LIqI@22O+a} z$6X$lDpxF<2zqVjy(wTd&G|iE^~z5O-5W+ZYGC+_1tG_lKReqvFH0S7^4d*7mjQgk zTzx|PIhO6`H|C~1Q9CUzd3Uj(JDd7UgbXTX%sx{nRdFFhmjko`1d%1P_?irG!-!ip zu}3wu>hQ}qtGE)*i>z=!dsTq*xzMp}!pyrl6Q4doaF(<m`Ve|ag2q=?YHublii1}f zeO`>59|s8p^2X-8=unt^6>E(yrTx5X<zvvUn{bQu>(;jKTLG%slBU*V3Q8Bjy02fk zt<dJ9b-~&$k#m!4d`h*q`FoxVhoBQ4o^6Kz#<yrQF}Qx`AUL?={(A%}B-1Frd3`3^ zS15Z^fNW7=o0gzkq#S^@SSRCE>N?SYPh7nmwPI_+l7OV^o2$HTqqD0XP}82+%$6wc z3<6yCp3#nG<HzKMSiE?`Of@qZ2fJ<^9b5|%$2xvAOTIeT9h1QDXF#TDZn)|*HcRnJ zK<I*v5jH|foJ+W=k~{dN2<)z`F1?v;mf@+MW%vL-raFfU(juEmd9WoL*y<3w^E2W_ zNu>cEUCe+VSr?*nY_M8OIxPE8FUH{~!in1RJE2Juk&ECLdZVjByy?*>wk@T7Ze+bB z&M@NVg`%)i2@}{;(&)LSX|H&d#&QNAzSyh#Y$d6}P7{fxmYt=r&vgx0T{0MSie^BG zt(u$HI6vTE0q-!wbPFW#4m@?u?rFjBdnROJc_fmDsjxAU7jGo@2a15pZQ{LqVs9!} zw6v&j_sUh?3c<Mg{dasb_go(FGd~Hgm`%hcNBU{;qz{LH2X3A4W)o1+fef;5ps0@7 zk#NAGLRq`IT<B#_Nruv4!b8BQK9aSB)5-}0S<JxpB5$_SR9u5cO0hv63^i<5*L33g zu^={u2uh(EGNWw@y3Resj8r`#%xK#w@{;Z>&h@Lz2`gc(9WW(Ezv^6OLH<5M6bZVO zwxS(%-R4yC`@EfeLmn<mer;(hWOig$_Lg=9NeNoXoE;3Urq0TU=j_Db@#K9doe$FH z`YXK22&-u}Ee0dF)?smFa1OMqYOg=sRI2vxAM7{QE^J#!H4KK=R(F|PAyLlUfj(|# z?STqWGusGELZKtlUhcecor}%TfxanSC<TcFQ;SL<W(R*rsVG=zPzCQ4(orsk`p?)p z_lB41jfU<$O5}A}<fGnMxSFDxFa^_tCb*ntlc89|2gWSa&rR-MSOW=BE^K<>WH3L$ zUmXoR=aZV+066ZMFy{tWR8AR&e8*GAr;o2J+t>~&4CizkfPi!QtwMTmY@tENx=J|h zPhtE*t(^OxE6zOedc6Htrc|x^G8KHYz7&@a=hC`<PLoNq0Y2`LG-+L(`qGO=t-1!G z)k}iS>*zZ<A4m?rBkmX7(AbG-zdds(GvA<Nqw+KXERE=SGP_E)Uk$}Xr4}sI0>4P| z5Y@D-N<}4b!uV%z;3if}e<k~N=CkEhBBwVLhh@74pRCeD=xf<A7^<57)d!l4sJN%> z?+M~>toj=X?Y(?Qn`$;Gy4^rBmdkWOrtP^z1Ob->g*#`O4x`ig;NvB2Rz-SS0sl?O zw~nH%zB1Bw$Xlnvj$U_df*RcG8^=lgxV$&?<X#x1t6Wf<f1dF}I?vr-LObPoTiX{^ z)R>rjdOB!<8#)l^CD4Gu-7mu0VN0OM{gg2jr9W%fq`S#gnDfB)pzR^d#8JCn%)fSI z1}lypEO5euw^Sz;R<Mv_cyJc*Daf@z(wHSu$y5QvF0RJ#a8g8>j(4>UXZKROAHODB zOET?U8R>2FxHJ)wxtb6b>uaabvH<im;cy6SR|0P@IPUf>xIqes?5N0AGhN8m*M07{ z=fm=PWon5@xmm?;iuQL37Fz0%bctYd(kMpwH6hL?`d<{bB!gc3W&dHr%RNZFx0>gH z8>7wX;+=_zbq_2X#OkYYurpuqR`l{B%23hWri%r55=X2F_3J#tC93Q;%H@7;6(QYD z8*f>Y=_I4c{c$Cmm-uNWI3>Z(s20)c3C0H$;Ie6xWh-fq>DZO<Dnt%ehx4|Iji54# zA9v4LBkS&A4O%<gG>{#zsdwC$R^MZte7P=5;gWv8Ss%|?{VgorF_S=X1vA2O^MzGX z8ue%Q5b*;gb`m&Iy~z;bxh*-ll#E#QZ0V-HgRVXa4}Y&phJ1P7KVbtjV+)1fb}o=A zc-O##v&zQVYC)B@@&0ESu;T%or;5!=;|q5`!!d(hAUzeDbr1m4Y_Pbc*Q3M3?Pb-x zu7))nxAE(+`M<F4ne5|?j-RPiwuO~@$W_^+=E(PQ_O4lYC7^d2eX{j(yd`XfE-9vL z70Wl|Yy~I1`*OwuB94}H87R3yz+&K8Ywg?wk5-4P$BvwrKZxQ^h9~q|$7RPym~2mY zm{HBBerEar-8eND;k?5pjTBQK5W*4%+~}mO>necHRHgmFTbc@5WR+<ZRK_ZQn#Hmu z6APcz>A!u+Jn<MARkK5;exW8M$eZ~|lVX^?yY={K=BHY*vn+o&K$n0$&+Ddq07M$* z9$8UL05{eyk#8iptv)O=?Z^8}`Nrn(>Pa*+1sUN>&6kOs^3G&aeuTlU5%a7QwNr-} z$8)%gkV^n98vGJyLUya}id;k%@{0IqaG_K?>o<G-f!FZH=+HaU-J-oI{-(cZ)j3cY z;I9aZf4ME17XG(pQtmMmB~{Ld{up}oxn)VmoF_(0B@oD2^1NuH?tBIF)pIAA8U(B- zc%6^6&d8~DkjB>u+?lH*aeFWobaTR<r>UmGj_Ln~T?2|QsTiC~S;^cFA{P;R{Lf^M zoUR`Ns033o#q|^wG%K>$6gUvz1GU%&*W+KC8>vuP<L5Je%sB%^m*fylidyF$VR;6s zb3F9cfRFVe({?yb!JwjLIVR;AM8s7|yAdo*eSqydNdp<jtU-~?V|SoMz86+IE9({8 zTs<AG^OwB*P!3{Gq7tkJ(F_^pxp}-~y~{uuJUQ%B`dgPJdFXPBva=%{h1qWrRUH&l zGbqOkrVNUseibR5XHx%?1yr6k+ozbqBBo$=8%nMHmmhrvM<6+!gps!uhZKis$601> zsHv16Y+Rh|^S>#E^VAFe!p{JvCszpW9D`Divb%w5yba8XG-~_u40z^>WXq+_H(Gjc zp({5v)O-RX1DzW%jdBu4TRz||DmG_=Clb{Zcp;5vY{A)oWUG5u*nxHF)86?(AVxx+ zgQXP+E2h^fjN|HZ{`0YpwX6>rw3Yjel^*Cy2oIpA9CN(d1gmzumI772e}tPp*@x*K zfBYjj+B0B}&tH9aMr?{UwoTVxpIRuP!lR!$sH4i|Bu3CwN3Y6Ib!IbQ07}2L9064^ zZ|K?`nrV@9ET>AjgX2Psu^=kFe0=|1KYH7>UYz;!iyeUa#7Q*nxSgj$#>y!14{#u& zI{uN-8bdOrB+0ZD%)JZd^0>HE*xGgUq>>nKod6D3H?0@H(&rbRbcG&tAu(<@b@*i2 z*}qv~NOMdq>h+pjM({U++3*Ptv2HzP0}Np?+=-S60r8j78AXCLEbl$Zk&&w5)H2Tq z)V4SE3UcctOJI}f#9m)J2vq&sliU_@fPK&lbN6avf(BBVyZmR|?J>iw$mHoI*ekce zf#HOw`DBLO`Nkt~G_l*Ow?=!iwgI8o>w?t2L8$g7aEiVeEixn;yE%GDvR4;0_#X_n zsUgk7@4eNx$TlvgeU~>UC}$8{Dpv26@k7a$atSxG67w&xq6@YP#BvwFMhEhMc3s+B zO6Jyy{o)R0MJ!t<tAc75zl^w^#LF|L8TUH4YlPb;q_Onr`s04FCwSsv6(#|EKgoSF zgm+=kg!U4Gwsz``<FUm!cVYn7Nb=};cC|C(F8%Nr?x6(Z@TvRDz`Y~DtwDz%v)Fsv z6Y-HsI)=F~I6c}1WbrlF@fCdvLNtxjM_e-)9P%jTt=CKrI6S>aUp5dvrr&cWmzK4G zaYWbdC}fW16^)HRUZ)2DY3IRE5RI`}31$%P<rJN=mpD7Z!oM@TQC1)oP*Ino?)aiv z1~Or*>D@ri-zD!ChZ+BR@hls>{4INEZKlCJ$fPxAkSVBJh3Qb%Lp&Y7whu{$NOK9! z;k>UL!%-kP(l9}8s3quVc^-#zlf0YlFw5h}LB-+A`u-?WfQtJr7RjEt6lSKBvt)U; zc3f2sX=Lm}<JcZT#@ns0;ii@#EC`KIo0c$}&O{xzY>ZuI+vAfP2fIz-)U(r7y&zV9 z4W*7rA}bnR`#rT45}fP2wd}HFF-C`<N)CEs{Y$)vDVc$DJQuUyTcYO7eI+>2_upQJ z<yq7qSk}tDxP2>kNl$hz+CIivS-SwL!x=1$#B?VRbpAQtl8*}tke;vv0i;+p#w-_? zR7@KV!ojIV7G64a?%<!r{=OsF&(A&Cc-<3d6&B7!r@Lv8PIe;5EvZcAaB0DpjjlR^ z#EF~w>?DO^)gzqR!kfrL(Gmu7(L1DzmMhQ%gd{ZUbk=Kc6Xh6I0G`YVqF9={k5I)| zShyQ#+GV%9;N<8N$a78oO!^0>;sGVE^g%dC8C>&$BYG-lTO8qGA*M$e2ZZ;FfPcW! z3U|2Ss_f!PtnWPPNAm_D;(ZUmC-K1HSCkV^@klbkHH@x0se!G?;Tw7#%s(P!c~N5l z=TX##WVq~M*D3RntMVu#i1~mkTlJ82Pnb7GPNPR$kIlAEH3dFEU2mVN-H_f%nPO$} zlnu5@A=Kv`(aL;o_cFu6jdb06YixIUILUkthce)cs*c1A)`XUF)G85o_^9UF*NTv& zBG>&kR%+eHc4_}fbzuO@T!N#mca)p}ZFpOp7*oJ^4CH?eo+MZ#E)Z2?IKktt-*&$? z5`*B#EDPJ+uodrgWAv()^uo~@tEPwKhm7`vd|Pl`Jq@+r+5q`!3CkW5xyHer=^Ldw zRzotSsM>HtKG}StEI_vs3OOpKspdD11U(_3IScxY?^IJq9<?PVAH(^dkvyZOwA;OR z*V|C_J}MM3Sj%Z>7S_Wb)wXC(k*r-|nQxKcS}EQt0+ce8;?%;|NSO^#a=q}4`4Ue% zl}}$-MJ431=LsaY4FSG^sY|hhgrLTQWg#x$m2X}FID<JUlsz&Xn}@odExOI2j{n9w zNyxo}*1{rW-Vt-kxX#9Y+i*~L7j}z7O)3M&?XML~6LH!uW&!tD<%T9MGUR-e+sv&} zmCv|i)&qKfr2FC*oSwf*#fY`)|9g^iSVP|k0C=LKwPf#`WcCX4Ll@;+;p3`NG;yyO z&E`-6j@bs5WULrUyo2W0F~)y-q$&(AR`x+j58paKJS)SBUWT&062ggN4fz~Sp{F=I zG=!(<qk`_oX+^q=gj1#UiR0;4l7FAZ*!3lyc?Rx_QFWY{3QdJUqJ8<u?;q30Q7nns zKQ@-4o@y)2WwkOd)=r6beUqQ}L!-2%1Mj`CknNQYK9R%aQef*l&=%dkGoBG<je3bT zM}occ<&tl+DwFw(DcO>(?byj+U;X@$h9KhWE#}NK8`@NPhQo3ko)eJK<~s{7_u*i8 zlpZ89;Kvo#ecyNH-L*#J_;kLVKJSJ*z8T#sAJt56S@JbX0o(DmwB7hV8kr_gtqg`7 z#s5W)3sDconS_W}GxyC}>mf6$vi^MCkb8eWU5%^<Mm3R+Lb)iwKbtFdWQN$l;@6DZ zj<FYy*|~D1I5VBRO?N{daNu>hs<p~Ps(lz~P7Ieh6fz@2(uMLu{NoG>ffxm2fQJ&} za5+&-QYA@jdz(=Wqv3V)p1^aNF69(9>#GW$BrZt<w2y2x0C5S<<I%{{9BlwT6i>wl zW_RNgQv?;{A7xI1+%?_ee$Bw{Y<_Oi3CDU&CkHbhMU*h(^tOg+2)D~n9W_nx=a?l5 z6`}m8@PIo^3ixuH>}5*I3*k%R;08}>`{_MGESn`9WTBs*IA4r@vB*kS<0`G05?W%o zg0gsZ*{rbvjFqEOYpd$!g}qc9NR@{xZJJ%FMvv5W^p$`$eC@v(vWzuxvL1jq#`3b> zFbb3&3Z8|-V9-#vl&PM;P=rIqtd_h+iJsfxfvY8acIm{F$<K=!+PUatu#Qs{!&h{u zpf_+T9Uc~Z|7lNO3D?Um{2_h|Uav!q^ye)W_7^P8v`yH}T3g?dJ{=NGNFdIEi&TK) zKw87a9ebBSxoG+{%sy}wAYowJD0P$9m_vizas98FFxiD!k0X*dMqbAbg{H*LoP`L2 z6rcO=%e|-*9Mjpw>7a5^hlA|EVHdI=i~_0dagdPg9UK^ekZIa$>lD0D)R$+vG85Gu z+C0sCKotmSFh{=2y%xta&Ik!GrO5UL`lB%iO@8*n1ZgD0KQ`o!lP7@#(W{PiK}{iP zYK`}VD$j~s?2?HK6v(Z+T}m2AJ8Ss<bpfaN!9&_U9NTpQ7xCgmMP@!er66B)GXz+j z7U6q9EmSd^VMS%|>efrN8^ATyA)G9cYS3lhPUTsop*tRu(t_M|;qr3U<qI~XovKIn zY(M8S4ILPi#eTaH25qQpFFw?#p)KN;T)>zH`R+dxE0~s$*a&)fZ9UifO;RUT0&y$z zMs`B!RaO@96)xeQmn7O#Q#2L&dy30s=p$hU3liTMWm_+!m(gwF+afPv_1tUnj1xRk z&_g{~mfkOxATQ*PV>_8Z^x`6Lt=1V!zfUa#Y$LZ64dEIx<)1dN+xzk~ELdg00`wZQ zSuNk3a>1Z+q<pSIBg#YsNR^G?CN0O9m+~G*E*OUs8m-8a#Xl0G=FhB_;*foVQzU6M z4i%ucEx5ZgHQ4*rM>SZ(G5^iIog0Cx%Q?#V)ob(xfvJSh`5n5nBa@xR6`CiOK}HPn zgV#F-N#dEKgA^C!^Lk<|`r@fLj-pO>{h8;ZL>3uv!eeoPjd?W}`l@{O(#JTw>!3xx zKBh`jx>2_MtkXnh$=_Z%yH`R|4^MR7&D+<xS|h_`@g@b;_*M&c;J?=8Nt837$u7oS z?Yx}9S_e+hE;}qq3SF*8*!PU|I~tjEilL7L6`Sd+=Z6qL5FzieoJB#PT{%g{CqUc> z1G$2Z21ry1Whg>rzV1t9Sx3tY1I5vFthKye><?x6-RdIdyoNq;%%^B0sCF_ORX!Kb zkZug9E4iYqibUciJ2}jow^N~gFLkOrR3uxvyvRo@OQ&(R(h!%_Z{AzTguk={J9+4^ z6<|i?W3a<;pZ`9*P=ja-x={_lB_ZK(Y)B<B32{J&+e!A`c7i3ZdqBNFx99)|?yF4R z1-GJG=M9&v>3hdsXTHe1b8?6xcFz(8iIYz)<6{FcsW%h+YtQJbS{P(KIW($@R%D*f z#n(h-KGmNc;3Dhwwb-;7&RJOSDfT_3+NO~NOlsDxLL8T<5~{tGTX2#yFU>)}(9Vf4 z(j5{>1W!N-(&tD76T8D(oYi_e?X#*Z;hyebzNDzjP`SYFSv+%rO|b2xBYDM|qe%8u z#{C$KDlk8Z1H2JwKT78p9so^HAY}<StR92Wdk@rt@?GU;x5nofkf(mi-kTip$cSH4 zCjRfU-Kvr4l@&ffkVW*1-*>SJe<v;+!#z$uM3>r5$=13@v-Vp*S&)4IO!wK+FP?T^ zp1RogEW?~>A*6uoaGGc3fo*cAwJ&Ul>`(bq)+S$8w(<Ta^n_0!{u9&LlgB5|1t|1i zJvr@E=hZi~-EQjG%K&%VwE%cr;8MTlKHkm8ly?UtSdLq;f$Wl*0S#C%zZwz4dhj?- zO2~os9(xy9klfIk82bw)XN^o^Z`WOtT`&h0=xI31!^|Z`fQ1Ood7a$+!xc5OTBptq za+=@<%j4R?7(5>+k*{8sQ)Eo=exakbp=P|UD>AR#b!Xw1@;KrQ@S*w7guIA}y-5M_ zWkX~=D68KxZjCRWSZiw%)jv2wx128u-`^F8ww%)vxxWKm*c$Uy()H{klsPix6Pt+U zuFw9^=>bYJOq&i#f(99I!>P9K$8`c8grbA0fF1J~(PS-2Ore#JB457fn(t1q6QXM1 zMP}`nJ12w&JFvDT2g|Z__u}1ES+*xYn{*gM#iy0X(9`RAyw*DTqi4|}2R<Mkn#$Z< zo$Py7BuOqjPv?K-5fjKVq}6rG3p+b@;CHC?X>dah;l46s;frM~av#g3O)?8&5_JmI z_s{no+VGL&H+dc+SW7kn8bz@ESi4FmNF`eMK{9Ov2A^lW&&z+Bp9dEcomg%tI4Yl$ zvMztBKK(dKy-aEa<x+|wxXyD?KCpPCvzBcIbgY@pO2TOY1@$^(sgb0e)*yGR&8PbO zYXZ42WPQ%T-UY?CEt$Lm!*F3hO7%(4A_duW^_V}SB$n?yLua<It{YjWl-dJoto36p zBKgEohZ9Jaq;nj+#H5A{MC=wyoLBaQQ|{2fWTs+I7{^s{O^8X`3P(&?-Ek`$GRE{Z zFfe^7f>gRCiU%9ph<xS=Er6foGxA|HwB}jcb@dzSKw(V8;yvJDPBbEtOnLb-%nrRi zgUU+O6=y8o@#U+{F#0iYjLQB&>{@xLCEhTS>juTSS>kr=zwZYl?HUD^Zs3L<@-14+ z=jyH@UjITU5{8#>Ry<Y=23N>DK9gn=norwt*x7pKr${AB7gd?ReK~T}EkP;LY#pVe zk+i)%=+e#D0$|wYk)^Zc_9nL0XFQb_iPphBhhU8Rz6ri}c&MPL(<RpUT16Z51Ia{r z`5yK<$d-34{M&v(Dq_RZ*0bk^og%)T)W$D0_p>^kAP-M0sg^;*0?7(8!lRB@n8OK! z(ugMT^wY<U{ZGPLzY`RpdK+?86~%AmZ{+0~Gw)#?V(eUiXo>$(qh$7^`ehG%=a4K{ z5E(<3pad`&m}<a&rR>GWQvtgH;z=FRle3ZNQ5z22`8HyZne+iEJw&J0xq^W7zUidJ z)~8A-)pG5%SQlZ}S$4KAuWjaXaUb&BoPdq&p+{ezGo`LRihg8OKO48T-Qs7c_F-Wq z7V6_L(zrp(>xXY`{KZqXgq+XL!3J?+AtH_%lp-}jWl@W(S}R24m*GHf8*p4-YiK8I z#9x-T=r1wZ_SV`dVhgIeaFcr{TW%HO2h7Cw>Bes%!12*Z4t@!P(t=0STFp44`dsmm zG_6I@d*9!LE$jpzna@E?VivnwPTja1Q#|;yMSD0J8}=Vatc;s7?ma#E@2npHFnU8P z`p&r0y-twTg*1)+e(e?Sf>JswP=jt)e?wIh-1W6=pM$h@D*Y$B5e_l>zVsz<O|(=% zF8VG}Rf<01ypN9BTSHsjOUZb~lf)IgKuyvU-B`6hly?)3I9{r)Yw!M{qhVc~_|L&? zAw<~neo#BJI`4CU-n{{NegJx|IqBjf<0}Z_6Z^>q#sV;t$EFPkso792`H3Fl1NzYJ z_jcTaV-8Q-2!bDvUhk5d(tE9zBW9zledEuZ@^6qp83t5jBys3ZLLTK(SjA~{s0$L$ zn2fR_q=aGxUt)V^;O=mrvHxgqf<r{uT|`4{Gjb<TE2#_Ni*^r^aGq;6g-0}+8Fb2L z`x!-BcT1ZeH5c)Nz~IPtN+`~qnSo2OqW(1cmioq5*8vKt!Ra*;-T2mNZ8O%bf3e6e zwpfnM7er=oG-yDxn4B*QtFl#{!KnfqKIV{ghoY<w<}q38=INW*(0QT6%5W>w1qI@$ zHa|<*i_&GdlpdiJw%W^FHIKe1#rmo3npQ;rBeF9-i)uHqk9sW9FX9yAwJ}-(Q1hbB zD0$X_0rGeatXa089Pqh+ak{XA;v{7C|70fR<KicZwYbfi{SF9R>4_SRQRt!Z61-O? zu?e4+THX$Bx&0;d+HYo6=fZ+sgqNf`AQD^$_@|d$q<2MN*z`9(=`Nm2?G1rWtVGI4 zl|7u4Rk<vX*zBkRGRm-UH?L^p{y4exUqx{Ou9Aem@z%}qpvatSR2A^HJu;wr5?{C) zu1Z|fX>;{khg&^AL7Jthn+Teyv|W#YIB*rQ-Sn5V_K7KXb2w)r!BY;Pa6>FzZ8Hv6 zwEfq}vf-DwDN0!jkixpbQAD5vntYZIS1R0*%ft4RbS2L8Uj6~frSCyyhdLj%S2u@M zuZgV`P5VS9!8<wpJiB90*s+a!J3@pKTJ?Q4+>)l7eh5a6{(fCSyTj3Yrmsz4Fu<0V zu&930-s{L1gix;R<$>)DDOtW_<(us(pn5rnePbg8=D05yxXuuz{R2#Q)jFzUZ2Lrt z);2eS9}9KWZudtaU7j@W(9>wjk0=I=LI&Dki8lr0<0=0~>K;+k-c!k5V&p7__DLm< zKixFbZy0h=TqWpkY;pL)jq?iXD?GlXvUhXd#a>`Q?^?j_!NBsWLcc;mh|lL1>@w$G z!$!L|lM&i(<pEWPyR}EEYSqW?a!l*|pIsSGO3FCt6B7|uMP7~*7FWS)xN5DNo`D$g z#xyn6pauPBD&85NJl>(O>_e%e<RcK>S+yQQ?I`n>rtEN@>igIT9e`q~39WVOb`c4o zVSQ;F<CO6-0$oL5tUM2$n*M=sh3m6aRidFY*_urbs;GFBFKAVzNVN7@S`nGK&h0Nl zMBa4bPn5zhp>7yUN+^n;wg#^zh&ChWmSY#hwRz(Y1%7&e%g)mdp|PB4oyO*>|Eh$D z7p=?AB5(thq~?3*M0QNV>cZVJx5(dCI$gdBJcnVD)OTxl-45Y=1<)gop1d*l8}INR z4IX*~6>$ZJ%t_A(Iw&s8LQ!V*mW)_+NlrX2qk=}$;Jp7K5jkIv$m1hh!EB{@=UU#` zExGg6GU<^Q&4|LdZv$z0Bw3bIzJXpa7({_rA<Y!c4$j#zXW5_i7<dGy^pcb$ZX{|; z;{oVYw}u~Gc1o5-a;WnsGM`(L9`U6utJgfVD5`L~p7E!R0euk77{;M#%Bj4GV2@UR z7jO6B*@!I$jFXG?Ol`Rcss9%4##Cdjf~dywN>g&OM`a~pRx@h-Xx@6jAVK-|m>XPM zyBHu>!+wMG`|MHxZ>{;N?uf802!e<$?_Ns!BYG@yqP@nFuD0b5dx|0RK%Q%}q}W`e z*xY$F9o@4{V~3(xPoTk5-iggp^bl>}Vek|IHY<XIlhE+)ys2|`Wxzg<Z5!ju1M5>( zKx>WGCM(&~7-m?A7F?PDN=Jqr!Q;d_VNb~T)=?0W6N?>1XWWZkY~C|V-8-k(??>-- zi0lMXRgZAJG{#;eTlPOp21ka_(3@OgzgP@S<qYczOi9{S{>MXP31PKiMnXvj$LB8E zMB*|P8Mn!$zsTqJ87?w!^6XF<^?ODntKaa-tSb{qwvbaMqh@^Mek6Jcd6ypS_dVPc z6w*%F<_s!LMRvC$gZL_Y$qnd{KkkmDVd&x4qM3Whtp(w!^r^YvqwJ#w0dh-?<WUHf zv@Cw=re~P|7Te)9cFCMfNX&xFPv`uyqfaMX(iw!H|F-uvug6qfjsoFVl2u{VA`x4_ z2TJxyGM>SbuUcb7Br4Ipng3aD@D!Yp<IcP*(OR50a4mpB-JzcsXMCTB{csP&YJq&o zU%7R`n6WmRr`4Q4wRr0HpRMN^c|k)~I4d6sNBPQ2qxe1=q2d8B;+sW$bmKs%`hJII z#@O)NlXO6RXXOXyh7hWj5<y10Zo*Q~@8Q&is{Wkpk_7NJq@3#~TbEtWO?}&XZ3f8% z9X$Xt?lHt*+sQm!7EkVk<4OjB3P>6nm5|OAceLCLq)>p|z6lQipX8h83^oJ8-WlRW zI82ej<D5Xh%kUm%{(ViP=u7utC(`h0Y>T3>F1A3^%rLSgJ?xI0NV^(s_VqwXO6L^r zINafUf-#7LlQ3whB-W=iv2xkhxpVDZdZ7zNGYYGI)t3Wc6n>cs0zu?NM!AD4D`<AF zYDeR5An6dD^ec;Cb@fz6xEg$(MM#l6npQI7wu?ctYyLFLevij<ft>0u4#p`F)mVCo zFx_e3@atHK&Vq-=BqkVr_20}XX9oy<V)Vn$FZFm)_w4pfTqRfXGJ_HtX!Q^nV~I@M z+JYb)pI&1B<i2xmT4Q7J-K)PFGTzXIrUjp01>kwAC(7%y&UPj);kNO2IFVyJib(H{ z^i)Dwp)md)NmqfbhF#UG#TobQ^AYRz$9*vWZT}IA0p`MSk4bE9%cxN5f~+$BCdK0d zlh0hCiz_3{Oh~=kCKHyu_P+bixuBcvg!vcWb8s{}%!jx}<z5lXf9XZlw9i5~mo+;$ zhSMVjBMEQ73?xbZ;6jPz@(y027t8U9Q=UZ3^;i?$Hdw|USi{tWDv~^FjQOCVh(0Bp z73jB?FM!7wcX6S}dlUR@R(b1PB5oNNvS^RVXEG5v6{$=vP1U$N$fF{Ihu~P?+beRv zX-`LU<l`5nj9>CaSl%WLS;uz>J|0Chofwdt6f%N!dOQ;S4c`lZAg7AOeoCXmV|?Be zF<w+EXvrPiG+}`9L1RL(<yOV=hq99ve{%Hq2nO8?YBTK#6rKybH+PSGpPXWu{xC#$ zB_>OhL(;5`&U-^7U<d!_I$K%IK3ApXgM>*gJws06o}j~P5ku%<Iq0fUc*j}lw&ay{ zTPzUF4YkZhzjVUA!1i34`EczDRmI%m9Ipf>Pk)~Gqp1_Rx+5gh!6|(>8l&!ggg~gx z#f<RtTqv|Yqey{#R0qgSASgW);Vj;+fNM{jD;?H8W+COzipGTM?vFNcxxYLuP7WCR z;7(avSogXu3(6KJ);m9Ixh(@e&+`eTuOb0yw3JUF?_z&Uwbmr9?MejPN~<$ac%@}F zpqxVqT2R^SOeEEa+LXMzd4>^)KjJi_6u60Hr_>|WRD#*2cZ-z4fMuD?muh`{71&s> zr)G$fR=Cxh5p%VB9RWl-!Kn<D6}Ab9XsNJM4|%}*QYp6fn;Mxt{-K~Ij)5P!UOM|< z)dtQAIQO~;YV%g&aH%FI*Rd=@v<jd|oy6Y?@{y3;#C<+9_s*Oz1vT<Oz}EE};DeqD ztcMF<ZL+lfb{37kr#Jyauk|m+Q!4+<iST5!@Y5Qu_jZqBlG!CW`VGdqZQ3!?dEaM7 z!5Ws4riyrxj@)t3Lp{;_frWkwg{vu)I104_;3+!TyKpS~kdM5`&8nTmRzg=@Vlm|K z=<nVrm{qKR6cN`JVs*TrLaZRut863I$G>MaLE70~v&3f~i%Tp|zqb$0o)o7Da>=|Y z-l)W<{9I+x#wde-vVFvVKJG658+-5Iv2K`zbEu#BdrH7P&*N!oJ)yA59%X=Chw|Ry zjMqI4Vk2^0YjA2Y3+?;!Q(so=n8578e;5-OZz*;GjsdTjPydRH)YGCCIhej>cPrN! z&y)JI!xW|oH8)u{XHxPwXtoN%8s+p|o^nPG_6&J()>~?K;S31~_vdzz>T(w$MRq)` zt<d?7#5LEw2AvYu3IGqCl(FM}BJ;xQ_^HI`h@<VTp9&c>nAxqnIv@yzIm<Eh!5L@T zx^?C+>Nn}bSE&&;IagWWdKka;(c6HZUc6D+g2G`w;}Gf~%qA*kPBD=YNn>V|Q4oL; zMUhiKUFcWbV#hhke>NLsLLmAWz^Ksg2#yo`DUoBI*QY_S4tTctm)tkFKy77G8&1+U zq}4JlJk||3q+A>s(3uGu=vjEHb0!n-2ES<Msrv{gO2Sz~q9;|RwSk_@0a8q`4_Q_? zkcO%>Dc>6Kr;TyVtQUxTB!2kKRG{f(D)no+j>|!lyQG#BczPLy9z^z3+|sco_It<J zj8&nJPT8Q+*LIB#W}0VCXKTuR(4M*+UUoVld+62L!WpyV^{Hx2tcyFKpUxWQp9t#i zxr>>cxKoQS5Alru3q5+ej;u?7pVll-l(=VD)}?r*a--&ME;dMYrY8d__0o|`!_eJu z&0uJ=o}1ecrH`^;BmC1wxPQs?5RMVPpw+a%H^GC3R1K6|=Mp8B14Mn8Tl7Mp<!n^A z%3D>wv)8)cH=|sY?LwJ&$jh}^Vrq*`I9>y5LsWNZcb&9v7+bH9d-$`v6A(K2>}Zt~ z%Mi#6!FuDybU&@R6f9()LzHhCrc*RC^t%(-FcQw!y_FU^tR*&aaP-v%7KM4zb%k0o zdcDWaJgTZ_p&AX9Bl<*0@I`x|25UgzK31PSq^bcW#rO_jHoGSatsjJ0MM#(oSg%Kn zm9N-q$FHIzdE~%QNzA4e`IoYqJ|?jj8qUL@QvGE3;+W&8@>bD3>N@5@Tn(OOf2qdl zUr56`9~WO?GG^}zF;CX~#d{vL$BwfQz>x~`n;7Xj#Onm_l;+-H9@4(fkm!J)#s_<0 zCBpP_(U!<iS31cB+9Q=pSXyx6^L;k5cX{)Z4(hWfD1~E&;%S><e*O|vH3#_a_0%&7 zc1?=fail8?hPROpzmWsi-@RpWIoEmS?h%fLT#kiqbWG?aHz2k8htcGT!a*%eLAlK8 zvmNSiEq*LEE{WJb!$fHRZrJ<+cgj*c{#Mi)YL_%=jL%0s!51qAQg{5dpEb$Iqucgg zprfzuH@3)*$!a?kLEhKrbgolym)pTCmIs1)r>wWE{Lc#bc=yX5k?QQ3kgol(qSGm~ zX%xV4#padm1Z>{gk|J|uXg{LfONz;gt(oP|NXx%_xH*Ax2;3@^CsfBDLzR)yHF1*< zWS(8Z=o$2tm5)KL&A|Bh9AOhMVJ&7@1IA8L(l*4Dgfs-hwx+95ieDI5ETL@;fF*6% z87j4cEKc4gS7lXY`l{>JUQ1-*+GPH6CR+^uuHY{;*s7qRvG2(8;|OsHr+I;Rq`Vc7 z#1ID;fw0jDHrCF7F{BJRAJo}U4|p`x|384ILNUrGE{yncv*D8F;?cO;$+*O>CTCsq z@Mz|sc<z%6kSP5POt__t&4vgiel*Bptr9UMx+7|GY*2$IiV^*glz<R@u9xR<bn6Sc zQLBOb^<IYFxN~>rA4Gy4f>svSuXzkN;ZXm-mn&haXM3?f3@g%F+-b@Z2<!w+1oXN) zLJ~~~BHFK&l{a~-A5f_K%?Avw%q|HF*24u3xQi|iB?BSlgJq%(p97ASjckm*RJMky zW5a)~Ypg7s!~1f(=Mty|B4yoo_wLQogn!(K3WU<+57i<V4inU9r7P4H5?0>V4_46~ zxWMvsGBTRBrkw{?Wv((YA%S~~0PM2;9uwI-IW%_dkbpM5(-wItkP~c-ybUsbI&w4? z!leN&rK$?TBo{Ut_UpLfk0xETFh#Q5O1MN@L%^CTW_gM={T`nIx=Iv;$|%*ypITit zXu^ZxgeMI*npJ1hmWCObHoAgQa;2=LMW{5Fq7IlvZSOoivXb%aMuw`Fo$sBW44d!| z6W5LjLs^eX2z`lP&%^!WNjSv_N_EqMfa<KG{Bw-YNhYGkvd{!UswZaee?7YSm@v&q z4NQ-hNTe}+!jSC(^~_U5fsvTCN$3KcqD1n%<0vox&apS|sUux`ylWut-$xC3nzqqT zIyt~eyue-Yc4QT@$I-aaz#k&mbFD&#In2_I41+AAR7Gv`G%l^D038oA8eUnrOW|8Q z;qT;<d{2#63DLq63Cl^Z395yH%je!_=fF!++!ci8KQ<re!w<SOjNyP;1x0}_C0Q3@ z&uQ@&F@qOXHmgt<mEh$;?u}~fIgR9Rn5Oq|hi8=QsK}loVpz7SJG4sUT4^+My?3ER z!}ciTWp32df-WGe*pH;+*-!tODyq8m0VC<pe%0(dBP0)E#4@Kq7sgu&>KzA@L8x>) zIWF{9$bkgjd2$A7`4D6h+Y}V)qp_TE7(~v!qNK4>_p@4Pa$!$@-&CmiHK#uLwTK)> zrw8!~Z1OL-DuGVHU`2P$xw}iKja08GtC|yJit;`h{64DdiqjrltTR@CaDX|}__gQ@ zI1%IRkBye|>ehVoO`3zRna_PTPo-MvtP9y-^$cCTTM(Z>U4Ng3*~+@XtVP|UCo7E0 z9gZmoz17dBoHSM2KMdep<>p=}GV4F!B995zt0aBK^(qzEAO`A!p?jUnQEMtjrj)dv zP8QGPv*C)+nOw)GnfNIjsE9V4*z4J}-7&yJAGF8%zwg!04qIY~7B|ML2jiv_u6?L1 z1xh!#2)dtdn~xb(Hdy66xPoGJdAlpn*fEz&<+R}>s_PI>ppiZ229aSqr%$bV_UxmM z5>}1GvR~&xyTed~L+TAJr}rmlwT-Uuud0aUUpp+L<xXp6K4`PzOXp7oZQN%HuqdQ- zEM$8a7|C}5P&i9F@QfW(u;vh}xN7~a6Xn1)c?N;#mWC3FqM8{8P^_zjJ{+X&KqlAZ z?0!@facr*7SXJzak+ss1@2?jW=pTBlszawiDKAsWSdJDGMonC{Y2RB@ape1pADlEn z{pj^dU@{}jxRn4M`Gq&&Cld-=Qu-=l1~U|L=Y=sH_p%c;JylmgIwDQ}teXnRuH5es zZqS)TpNjFpnE1J>l)}yt4+B;ene=a0lN0%}pw{hRj`O><^*ieSoBtrS(6Y>G63^?i zhX{0YkcvE?jHWswg{d=@3y*DVIeedqBWx}`{jMrfeTgnkBBV>Y2~oxCev_H6gr*13 z#sAuyx8M`8T@1;p$w*ocBJq5S+0~aZGj#FHF0+t$*k#70Rjwm6Kyws!z3?mv?m5Az zv9Nx&%GM=CxUNq4we^u+{-TSjdzLdwD_xZJ@CG^c-PL3L7Jhjb-`J$j9W<Sfsa&1g zuQ;33LHN)(YJtUl89UOyB#2gnXFT9_DTB1&p<yb>eyYRXO#r-e=W@}|(T2rO^W%gg zjBFFYnL?g;#lc@Gg3fbtC$r^K{8q&?Dw|a$)7f-%MT0xGqHp)-gG8$BSgi&-XOG}a zf|7UsjN!zY)D>`jOU70@BvH~WU_O_qSwPl3AnCSdcjWb5)+XA};OSJm%QfM1Yj#J& zL4BlTD-%mCUOe$*IB_pKmgUJkpq_}q1Vh<*lI82i#jJa_jhv?BjGB$T{ZkG^Nl{un zjAi9vYAVz5%DVkiXKh-Ho+J(k_1*9N5ZNzpn(yR6OU9|;?TLw>b%a=l>Vs~x0{qt* z;ITz9-P6-j%9vI^OBnr54dv7-EzL|8>-#Wm#LJo~CX1V?DQj0P5uu_}Cvf6OD@eff z%nG&*O3UV_{~Z4c?N6cei!<Z}0<jf=3i;4^u@e5Qt8Q(r6Up*<x3R|&IG`UX3m2{^ z8pEPDnws*ho3<0HfF=Hp>z2@~QnVO`KYS4r8w!B!aJ86={lcZxQQ+=iv!OBWQz-&7 z2Om+cHRKhIAj@nR6&u{0`r^L~(c%^C8B2k2mK-I=p@5BkO}Pug^5QprYvfXO4pf}5 zY!Kw4*!1^L8%WUz%JL~tbBtP459@X2JXTzSUsdch7m}D@X{AL;inOk`Z@>TKaZ#|H z+ph~j_>Zv(DYH1`uTcjQGI<x51U@h;Dww6^;E~<xc?${sBUOpVQV7Z=RD}#C;w7A; zRn+>9qHt)WS9G;wHQ260SGvT$CPYnlP!fgM%W+R^|C@0t6Zl(`E}o-88R}+lL%MYR z)fU~qI0_(+s7UcJmiTeX7u&5ESFGiHw(UhWHs&FcZiHM<$II3<??*v1TL8I9avVkt z+-UWOAd~3v!S!8|T_OKhPY#XC<ZZBz^D<7y4`ps!7{Dz|q{T`8tRt?T&qN8r4HigQ zelyXIcy6HDVS@)vAYe^zE!Y^|C7J$EN^YwY%laKYdMc>Tl8y+po<`afxMekkp#N1) zltKT4vYa8JmEqV*d_So&{WWXo6Wg=(`WopWyZhvWQKM8i*Gan`l9{<eBCb&T$&W1F zJ&Uw_M`dG6<rv3E#IIQlRd+kTu3>$<u@$(Obv*36UO!Ux2J&3Sa@)&EGs?_%_S)YA z-Sjlv&<ARU8w}LQf&rLiaEwat#~^kXV~ld(TM~!PT7EdSs2XGjK3J*@YBao34Qi?* zCo%f(0^Y`)oSqWZP|1kC*&A$dVhh*3GkBR!K-2_#(r}(dP;|~f!8NTETpQ|ZOE16C zcSay+z&d1Mwl@622BQl=w)HN`mh7B1!f2f}Lx<_WC>u~K$i`sZ$LY0?dD4yWv?NTH zNMWUHh@mQh`>cR?eGvhIrMFAn%L6X(j~mu}GFWI=@H!~HL*g0Eg@P!gXk3}Q9uD=_ z5!{}~8VO<NQ#~E3C*>9lX+ErDGm5Ta`~N|G|KFV}83-8Z8QK0f=>0#`Hwzon|6cx| z)HfSD)Bi8^?O~#<J=MxGz|$@zM9|*V)djvbTHpYQ^gnY@xBmv@t?Ye1KF3>+*KE(x z&yQ$aYKP@SwMvua-7P7Zf^q>eBOoT=h(N2Xv-ETHHh>0)NqkHJ4Kh;>{rDzGzx3Sr zIFy_$?I8fOb0fe;Bo-%N2Oy5@DFCQZ*&9DN022`rIyVPDkU6xoJ3ccYMhEb*ziepb ztt&q%K*@m~KjQJZu$l4sJ1<N#OH)0lVozAO|MfO5_4IVk@3DSC(O1%iTr)in|K|KU z)bXXc2_Stl3!wPY)B^CaK<%9<Gyussnm!0KTQe)DzcgTFKOF!IDuW5Ce{f@9W+4>n zkC!2;85dXl(4Re`f`Up?K4>`9L{%i9|79}(Bn#>aUtJ~tmfNpsGl0j++XJ7=F799O zR73?-g(YPq1H*R)us`HJkh6XByV7f4yN|CK*n8HdS9t~S_-P#wfTR-{8J8^>n3|fJ zCzF{NnP+?uW>3zG-na4$4Gv%}0XS9vR~PU+*1MWfwvEj0)`c<Lw^|^d6i|E%J=i8E z&>u)d&@YSm)9&P3zFXH)Uqlbv;Dwy*m0t%iPC)-3xsmPpyIOU1VIg(@==|U+q`8&3 z)%WeW@%iyJ1pWKe>n}*A{C5-q0>R<+{(V{K_8%O_ch~fvB05;lob=e{(A4}(pW5{N z>c+zrpXXEF5-ZpSrzSfm$1fETg1)5z?0?qx!(67u`mae6a$*`1x{^Xkk`H<=O%Bd^ z4_E86tgWn{$KM1QG36BOzVUyQw8MYW`kn}-sntKA#s&|w8;HL$pF*@dA4edLcBb#N z${K5d+E%<j8<v)O7KWcC7i2RoFcvLnFSGpQ^S}4rto^^%48R<KXn=ekfOAvp+556( zJ;@Iv(@!H`yMVN?|AM{xmgYAQ&yDn;y?p~->{y)ufU<D2{B&`CaNlHsW`_Xj>KI%- zQQtmA{eLMsldC8o`=4naITL?yKXZ>tzbz6KyKd!><Exvv`asMfX7S)0Jy8LVe{*<W zb()8>tE-Qpto)OI*5`g+n49YAU4LbJejWccER-+#<_o038KK$sCyhjt9X<WKyzIMH zlnuQrL~mqi0_&|C*CTD=`x^h$slN-09m!*Y<{uj#c-1qy(`0UK1m)xeTHpA?0_uI+ z?|biM`-Rs62&#<lZZD^v@tZiIBV*7qijN4X!Sv6F!PP(C*FT4wd#?pFWo7jTU+PMh z@wfGh0O{wqgLd?U2VCdi@&J?;fV=lYOAJEnC-@zErW*#*kN?DO0K_o<6}<)k+wdcr zePbW#L%iY|^CO~#0|+|U3y1F4|F#<*e#bL^gdYdd2lxf<MW+7(_nx!*g@2bFKg5qm z?$`f;f7cy9wHtrd9e>5Y??E`nkH_rSe`7QD$;<9x8i#zRtN6WnmF@q}1<&z6>La}R z;>N9k#r+$Izu=kU8`|T^{<|Iade$?mE@Jo(4^J}n%nO_1+yCO${tNu003YEy+t=I5 zez5cTo&!Ckt3EsiXaurUPw&>l`8)V$c7CjXP&)J8E0(c)a~JpbQ~ZSwI{wG2`-@0J z4deKfZ{(xr!)Yo@3xJFbKE@@223PkN&hopa@w4`EPka0~;s+-QfN&1R9IB@afcf;U zMalw#<`s1!lfs|iw2+r-@Zgsa8=x(lV>vX2II~L%3U&O&`cdpN3qB#~c;!j<zKP~b z_%_z;t78{Sm)FgpfV9o<occ5>hK7taqgbZ)B$cG~NO3_>!kIWbx$-^0nY4<uBnTpp z&4YGedG(Du!2J;FnIc}PwD`ybKG~ulTY)$<fHh+S30jBiXHoeRw6tXxU2Z>wS736f z5wy);tzco^bt{V^Gk7J(kQbgdMVIv1O`FBdMSAbU7v-s@pXuy|&Y;bVaBh^kMxJQV zKQ3cUT5d{1*W%;wJNneFiC>;VVns5i062%}6Hhv`bru;=`~z0JunkId^26JPDG7E{ zhA>^jU4Q7<P|eV%=u)T@6ZzM3FYRNIq&N-t*YP0!B4dVT+mEaL_n2~x&M`VV7S*rB zZ?bJRC*>z(CYz9z!>B8PJrzVAejXjJ_U+)pAR{GVC4IH`q(~82%16m9{^cO&M$ENQ z9{O?~F50)0$g?;3xfPa&nVI}mAA>v+(&39|f`4PIgYTMCq{st9$QNVEF=meW-Xl+k zKkqW_GGHUwyd?}CDL;#Vt7wIwyGO$oL_!55pyYW2GU5x}9W5hE?6tK1fIK@GetPgM zYvcO#UxVs{fZo)7)>@MO)=+m0Q%dvdyQl5-&{v0cdC~u_d}jW_;N|3~Y2PLRa5Kvg zl9zZIw*`ALIE9%=-0RFo(V*lGU0y`a$G}wV=bJq(kc%qU{{=@txW80Xf9mHGGUY)e zk7rZhnw`(v;`%nTi==0$qDh^1b5@knRs^DAd+Iug@H4|$70ZjGjp2-r6i$ZDqju^u z!Ad0m1<832>v0v>6>`jLZd!gLgW=&adzBcO1UXch<@f0)MiBQ5*#xm^hRsIlLax=y zb}i<5F_9SE$}BX<_gMT3Ewd~TJy9A~5<FLr1O@I;-htuGaL}S3VV0^XRQt;lEtf+s zSDpr1Ht1Ku-H_Fx{m!TF`_qZ$0<_x+L&yRNV#zEebh3reIy7HoWGAA2iY&lT2C~f) zG6=}6@ggs>pVf=)QH`Kx#(kAnaIJ^qjLdt<%7IC$&s}@MmLVcuv(vi#%vr@0cFbHg zhgIW|067%W{mhtWc~#?zZ>}xp{gPrLJSm|TdAVo0f^?4NnVJ0aXozRm`fjdzCAVUa z{zL)h0U~h7p<cb#Sjh!en1XPqZRkhE)LY&uELSyT?JQRYFNwo!&rNRO8U&vuk`+7s zO<VylFFprrmQt%;6EnwPelRB<_D=csb!!DHWTjw1Lr}H29qz~01bLL1Q~`MN?jA{M zgz>j!L+-9V5FgaH`WtV$wcqvD?AWil2QN^{$SKwc0s`k1e7z>nNcFx4%ED>M`kzj+ zhl8}H)RwC61gDXjZV)=586-?&&PoWO`ZbBpx*L_1Iv+GZ1nK=<dn8=c3`qKcS)utx zwZYtG+)2iiTbC=jG(MxQ9P8v92lWbiSRy-M;)kBs5vgLuj?Nz4*8NbB5KQDVg`osV zBXBzEwF?yA6JdO6vEnq%Ego+zsEZy=MV=RL^&H|O==!yu6|tUZB`Y%ma6iQj_%(8! zh>R@tz6h$+%=7+6WuvDl`U-rAPeX9WId<^c&5qdguxHnfVnSikywhd;k%!X_Wp&3n z4ro<h0+F8am-T_1KMLwsCVr0e$%h*c-MqFkFA3M5**vsgoiPeMg|)04zLXti72GPS zD(n7P-stw-(SRkDyepCi@xYwyBXaoBTU@3Lo-xo=y41o2|7*HOLOWGeS{wqB-&Jo` zT355YdSApS>C)whwK30rq^9c$UoZ;4FylaWSltui`j0trb`&~^(&%P}d{U8k{@Md? z>)wd7R=TDRSGPDTyT>j1>g^aF7wg=X-bXc^mX)i~yT)9s=Qs%{Ra$>c;Wpyc&#OBj z6Vq|qp|}(2Ehf(=5`D{qA=pBjIiH?7l8BZC+&#gMzeBq*IVnpLH%7d^)M&Abm2<hz z+>~Gskd4%82PE>^oPDM~(>)?}yT+&25LhxzTn+{k6=0sU&>k>Yv=cY6(E4r;PBOsd z&Hg&?Mlm(fr!x`5x&?U9LGj$%xBDP7&Ic#tfn(~Cr2XJ{(@_lmepjS7Dv~;h?x5v< z5nZlO1taiFc(PJB`l{o3LwzE3wlvV9FovYsnq@pbV_<gxqh>n$4DH+5Pm!Rtnl0q( zN3MXgAuBQ#^M{c*ORKnbhxoX&fwyyr^wsaYh<R0{+{P^^2sL%~(#>isFuhKfNzs<$ z(NTEc)!GFqxSInXkPS$7FeoZ+(MY8f4Rv!NGURKk!-LvLmLSB=s!ZaJ{8P++(HrAZ z>7&R$+ILf7ZyZ&HsXDGH<&l;*GPDQ9*WTh0WxM<cxlQBK)SZ=p$;?rc7KeR}7cBWd z#E^w`(y2A5fe+)>bu^>$Wd*thX@l(s@e>AwzH&D(KL#+*LXB=>SmRA-f*&)YJPQ2& zC<`)ar#uCH&q`R7XDC}%L~^z1H2cEYv;8%dz<JpXRL|gnnT>5&X&#<pOK#|F6&1_9 zBjeZhvWHnxtm^`s7H$*XDQV1@@XY0k)(M87K&kwzpMF}6RWLem6SUCA1!kvF&EK}S zba;XiPI8~e5P`JiTZr~K@?PgxiKU1Y-<7=AKzTD)QzjMJR58PNPsO2Y`|ub_D2`DU zl1YohSM45r;rbh*s6grd=cyzwri*d$$(cK(r@89JO-Q1<(E7@>c+hWl18+98(|h<n zp6WSgVhtq<sY~!JjIiGs1tZ?8RR{*#*5%l+){+x>Zx*_Gewq6c0*JtGE^38Nbxg|Z zLp4Y2yV3cxW($58wURAL8$o#ACnnZ%u2)Q~I4LNp`qEri)R%h2QZM4v<1=U4!i!+_ z{nD~B5#-rF2yS15?)iK_waGs~IGR$qOOYztH93<AjfD7C&Fn@b$5V)qV4z!|W7dCn z@pT(AGjHa6{~N=z)Js!cC!V%iNUDA3)36O-5<vcoM52FaekX;aibZ`+WeK+w`E>GN z#pdKwXwXX^o{5)x-k!CLRzr>00gN(>6sew7WaF39vqNm2pt=$a`~FA83&3gZ4(!K) zrP>5lIz4gua$J>8gCZh~b7n@Lo7MZTxbC7`KQA2v!8#vzcFj79TldLB0n0n|*kWjY z@<j7}NW6lvd^w7JaTZy~=AU_o!wj8bNni;HoUhY6YbD15cu(IjLi%}6whCjki@|_7 z#fnkp>^tMkJc0LJD0U9IR|zW>PPXjF{P6qBqOkdT`c`PM_&yfaIy`gy^j=?w`{j^+ zPFL>I3XADtkGed)HJVs{?XapCkYd~Eg+DOm=nWaoMPrA7^Ieec!|5k{%}Eum+|OkS z{~6rRNA1+O&==RLEIkn*1aqr)_v1?#t1?5#e&g{(&kB0cRD)%9Z{d|`;10g&QupHF zN}-Q*h3*#TVIH=k=5?SbAD?-GU4y*wL&MusTT*+~opO85&vt0d*RQQTZj#kp>K;?d z#O;GKn4iDTy?PFm$*?$~m@dWP=TyttO%_l2C%h;>Fr>W>zp)zScinqPdX*hdVv)E1 z24C%ira4TUf@jmhIA~YcS*j5}yOSWt_C2%SmRkRrUzTO5vI6*6Z`1d^HSfHD4J?g2 zbWm&PLBwv9676s!-S+Yla|lN??%8^y0Y7`d`7uY&^p(T+Q@kviCiRbS9YN{hsqYVk z9G~v@?iDXr(yhw!^Y-MraFD0qFIu#yJ<?9K<(>wYQn7aJBq~;i8&r*pv981<G;zqG z>HRwu7xkNF6IO>LCVR_d*%QCU<B)fh8g`zipm7A*+xA1qni&Xk*{>NMuTHftt>R(Y zW{?>H(2B8x;OjgzopmPWR|7+7qCR|ZXdb0?d3_dh`C;rIZF#4(e1GN~9Rp2&MjaRl zCNJdWYrMPT;hw6|1Qs6`n;d;od)aL+k!F0B&h*?xJU)-V;Pg>uolLC%;@)d4Rjhh` z{FYyM-&z;Kg)TjLr3KGJz^tqcjyfG;M<3PEc)v1yT9I;IF!(lwg$>x?tn)gq<z@M_ z!{$K|%^EIwYvL*6g_1+XajZ$29I(#t>vzdE17gUuIzde!=k$zp@%5LIx433?>4pN< zkF~Pjq{uitYOTskbcU`zlhT_0sKes^TuFP9$(FXfcSJvQmlJJTPe6x|mun=lGUh+v z8gy>iO@s@c+|N7;HzNCyeXr_6IG|MINtQ$>0hqD42=Jn`*=%$LGe>giOG)*veM(mj z>UELcQeRCQ2<NGZ_}uh>EiTF<w&PRcdyCJ8bC@TuZ@Idz2isP=JUd=Qb?M@+RMr<F zLVQ!b0mpbFyi|TFb|<_R8f+txh%36eRC~gGAVaWC>?t(-<59nY+Fi8=giTRE{>x4{ zb37*y2E*hW<~*Sv9T>c!|5;@K_PlpVteSz#x&Qbn5%}!@rmV`FnBu4nu?mrh3D~x4 zHWxIJ`m8AcW+G>nmWBOxCVC?jtE`J#gzshA>8c#N0cHJIR@4<#*VWcjvUSDt{W4or z5GyAJT>w{=D#6%_IE4|s?{}-lfRQ#{t*}*a)F&H_RR%4^+HXrc*EvJ*`~G`opKlqY zrLswVg5z2?0?&dyF#6X9zF7k}cGWt;5<Uxx?9UIOJ@69v(Lb90(ECsr^yMX~KQ^qU zdcy>g7&*%I9sxswV4O%$#Y>S@G*E@>3#FF`%*Mf28LVml2uXGKz1Z$j#Cp{GiyfjO z`NNy#W&28sN*t3ZoQnpMN5!0Th};pwb>YR(iw|Z}L2OhyZ$ErgILDZ+?s#%o@Y4y? zU(<s0qT=aHQM{}aBZ3yn9}u0jn-VTQU&bLd4u8T%N)d4QIz9$*`9XPT8WB<%vzN7` zq_Gx@QB;ww%>|d2o8P`L<j0=5_=N7sPvNR9<}&eu61iC>nu$oShVtlB15Y>2oz@%0 zU`J*Nk&Z;Ot22{+emMLj)sT6kFLRm_o`e+ARObv`1mrPQifmJPHXj|QVNdf{qbwG! zd0K_e85#$cP7U(vB@v^=ey4<HzY*H{c%_L|mITdMYQ*t0oI(XAzcN!1+@b!Ejy$ck z${2EzCx=flJ7`4MO4V}KihP*U6ZWKg$a;=q@eH3*`UqXfX1cq5VTkMAenZ;!y{?`R z4}NC?4NCB+L2>uIrA>67``a1?=P9j23mx430F=Wf-ZC4$Q39>yX<9vWLFMvt4|sl_ zoFYchtdu1T4oqT|9zn=Mr*qhx*fA+~ax0Xjln3@KUYyA8cYErJp34)6ozqT@DX~Y7 zgmo>6A0rp>&?{Iu?N$mC?KsG&wge0H!C`f0n<p{R8v-!f3!gJX3q?v2!cfnGV%!Xg zkQqu|E_3*~2Az#RcEz%N#96J3q9$OEl(a^aC-gmgLvq11JD**12KEW1c|o<cAkqHx zSiBGnzhD`Izbop7)A=AMu#%BfcF8NSYrVHbcVm+??1(N_3lyz@DlTRFuBA9Pu`6~m z_&`oH?$O|6KGk?BhSpkJIk{lw#;$NrgKC4Qym#cEVJ3~|=SxXFKLZBdpde-b%lV8% z=b6m;V`D7;g)?1p$9g*j$C1||W((_&Nnv#=xIIC!K(OkfuRBD*#*2gMQE+wiJys{D zDx=NmrB`(>3KS*|2z}gX1FIha$%Br+sFj~^a-QaBR0UC)`JvLr5#=46slv={)x$6Y ziprX3=?STaN`zrsV7ApRRyqmjdL_%?_g%l4Wil9L=bguV{)v~Y2jV?!u+ZiO5X*Qj zc)}*G*GQuodpwsctF2r}j+lpcJSIilrW&iQ77ETs98UOtxSeHHeH=%t9|&39$#855 zPlpq@wgwB|*E4ng!FsjpK;!|Yj4_Ltxlq@P%4mo*dN%2TnbpNasJve%ujTeYG0LW; zwhA`7sS_JAmm{C@%ZP!zynupe(qtAfJGq4{yRXQkJYWNOkFTD4*wRl~eJ4-NYXA9o zoWp@weJakKQ_c69U52&a^z!uy4`Mkp6;4&mO~+V(6l3ZZlR^4~PWWKMRFF&5Gpvil zis(Yjl$&Ei?Vcj(@;R6&u-^*SWv)^L>~kz6fx>-b=v{p|qCDqvN2?T=11bbe)-0*7 zrb?nasR2IT?(Grs^$B2^aw0fXYjn2{W<-~KJZ0FgA<utSRnSK>U0tUl|9kY2-DCL? z%LK-SOj-&giOB#<^P6#7gJ4FQ<o1|PF?N$cf(}>*Bwf#vH!bp1Hg9Ixm{_w>p)1p% z<#3=|y}T_q3SUH`GaeF$hQ_kijtQ4SkDe_O_<%o*b<xu#J;Uj}#;ezjKF-1RSfXdb z6=Cbda#bKQs29U%!V5PsatSYQ@!(C>9Cl6<7RO9*SO{P~(Nd4Op?=7ttVU*~Y9|~o z5hiO&C@r6rqxMkIFMQ;i@pi7OUEzq1Wi<JwC;U}kw^jX>c;t@Wq#KXG0zb>r@6?F} zYFw%j{ijP~Si#3o%MlU|(+{Hc@R9NMkM^zw#|CM}xzrmPa@7QdvxwG&)m`l=@S~iT zbp{(jBNp^0)NtHJtQE|9lxq(0fp*GMI}!L`lL=cvXyfPc&6ot^pp-JrRT$i1M|;*- zT#H<X2s;+wuJ03WQ;<jN9fn7;3@#6AT?L7*=33l`MfVzpwLOu5qwiQlVduYhGT0Br zw*&gny^XWs1(HxiE~ao_Xbxs^>rS>81q#a^>RvPFYhwy#HekNK@JM>1BZX@|?6<-5 zS(20(s0y&!HBk{aEV{pe<;m=G>X{(yjNg|jat3ZBeuA1F$GLyiFZ>uKxox1}>fF{{ zGd>cb49OU`ItK9!4^F2jf0IyHKc9`?aI~^9eW0ne<Z3P#JNm<K3f4-vA^YMPu3eH; z4;5Olh`<w*&`ti%zQKYmM}9jDX=oj?O2mW(cQ>rxpK}0*ACBov8NAW}%pH+{5MKMT z&xj`(vuU<&g*D7}0jj`e@rKdMs(ZTUd%lFu@#~Dz1-oAw(oKB%8XMT$Ti)1YV;)lo z6qv{+`LvMzV=ThigE+P3Cw-r=rw3jQl<RUY|0xP)dE6Ocu^eO=46JK?Sho-0hgcAw zk;K4bt@CW|U(3MNXO8u(o%L^F3P2ah6B^cIR6h*V23%x;#p<FaZ}`R`X|*Qj!4g$0 z^EtHTgl%%k_b!?6ww$R`H3id%bA5P%aNhUoAE|SpI$gJH@F9Zyd1q6pFHh5y%<OJc zR-{ac)(k%I@Nfx#4{%}5bM#aJOgRE@#VO~Xj;(KPKB|Z}G<2^JF0E?Qu(fz_nPX0j z<@kyZo54*!7#*rn3G2DnlgjZl&SLp4s;CNkW3fl#|0ZS94<+}&;&0Y|k&acD-PnL` z<Ub4HNYpzcVie3Qa{OieOXIjT&N;$Es?l5;D8sSNyWG2<bd27YQ*ue%PYU%QS!jw{ z|Ed>c9cls1D=(voh>Yg}6aLyi3^#dBc^pv3Kt^U!Q?nWn>GW~e{FMM_{}at%a*o5J zQ4AJ|*$$+r@oN$L?+(+L#`OIJnM1L4Vn_ad4CCqx?9{}=?$(p1LmtY-r0R5=Dwg^I zD(S-8X1?Q*pL|Y<#Zr^3H=J(wi?-S@qCdK6iIe1o+p0BjvN`D8Q-5ci82x(UG*`P- zOT?2fzP_F|<N0a4%XbSb6?<mqLu`YVN;1;7==WeiY-bzRBEWFs=&ty5lHQTR!8oAZ zIMH?K8|1;{YPy~a2Z0r1rOw+8mTmbACeEUtl=}ua7QK(}-dL!HE>0%${MDeucIjQI zx-44K=wVp(<3wB>%<l{$dngV0PNsGRc#FFxMJAyu+`IddyM!ws@`hnKMqxh`*9_W$ zYA$Bk1_3DvY(CASUUd_02$UF`3@{HZnl``ewnTxbdkl5d$Pxu>(eMUrlYQuG7;7+0 zhK-(-9}ikR@J?G|nU$e((})&T(YYx|UBkp0_&LCGC=c2<o+-sU_$%|=t86<6oBXUm z9?!=_qQ+1uJ$|&*PT*s%`P@1Dj20fqz6lXt-$jN5$3aWu=?@j>ltKl460U0%kLopc zF`8j?Pp)lfnCp_@lwKyP4!bE#w|$eV%zW);=Cnnv$fPs%D4E(+_<$yjm{)i3vAV|> z|1HbePrL!ro`))le%WcB=77m=DxaRy(`9vFDn=OzlQoV&Iv)4n4IQ>wPcG7FBF~fE zSi#xHYK7M!)0_r2{F{(Tus(?KX(XKM84(_+3oBxi9EB3E=Z@IbU=C%R2|0~aI-vl` zV6^~>fLORQ<&HfD#y#z5>M^$UpaZ1CvsW)4-WEflYE%WJZX~Wvd$;hJGca|uDU>xO zo38bMfL|PuR)V_Tj29X8$$1|i%|2Be3@pkARNh*BOk{kMTu{&G?=~&(XHhcYH?u_3 zsSrM*>!tH?uxE2Ib)o+Rk(tG^Zbc|c{oD4a?l>B)oG<fwkj`g@v&Ign!PXG$6$#Cc zKCtdb-Jut0<XFXRcF^w{L)5<{_6(u?lc_r+B$+3og^+xBmEmVz`zOL~Ru`V|t*D}Y z2iKXnEV3M)-9ZI6PWf-MDPt0?<T?~v(5W~#;55o{V1yP$YgFKYx#c#e7O5POlX6p* z*L)h4jO?Uh$Gg{AxHQzXv)v02=WG-gYQ@g+KTFFnQ^<}Zq1Gj%t*%_Ie`S8VSr5E= z+M9)v5;OWpn~e`@L>~1b32vAeXljicL5P35HZ$y|{UE)w<h^@dBShB5!8aX3nJ!$w zdYh<t$c)IvVH4c~U{NjEvIUqevB&=2iew4~C*%6?Ym?I=q~+M@g-0aEZ3vW_B+Q9< z`$!AdqQ&ajko)p&B4HA~L(K|@=%U0hS8x&FH(4p3mWF9Xgjqlcdk|T38d!jI5y`pr zq=Jlgky?WCV><08>>XPndFozgAo2Z|NytchUPMbgT-dOEMpAG6q@E_Rl$=V)o!(1i zR|EGS8ELP$iDH`ml-=f&Ph$JK5)jW{7b04+({6SmCPG5SQyW9dre3uefI%&mFoCrb zArKh2Xjai)=e=LToO1Xv7_3T5;Tat_rya%9Rh+m}{4dza<qTY@k<Uha;691ten`~T z$NLm}ETuRbBT0R9RVlb+&|&z<EKMysf>VvSmT|^hY;(=rze|Cb^-8duyS^OiUY#Pa zGkE(kwG5fRJ<ExG?$N+$+%yeM`a8?BkmK1<ATgLQ9=0=hZ2pKkzX?R0>edZke@}L7 z0^i71$yRvRP`n_d2}y#RziB{pvRF@ci`by1_udO`;zP+n%p34Y<vtu_oTXTee^1>< zp}%&_E`uB~QMk9PjmVS9G33HvRSULsF0q&iurH`>6<|eJwEp>kF(@JWn|mW_GfXyY zJ;?@V=+5Gz_@*D)d!xt4gLf0LOW!(Y=_|o^6{KKJ9V`{UCOP|iAd%cJ$|BOm8Wb(3 zk6-!_JKI^zc(n^6X}~dk7I<AcagAf^Ip)l-;|g({!TXjWbFFge_zME<1dj;@@8PlN zD)+P&eZLk`I8I=FH2yd}G^-?`Th!3`!2nqr)zO-%XEAn(U#wA&g=6%9Lm`;RCh&n4 z{!<5&G7R{@Cd-7zzNGOccq(y<!I@f7iII4~xgHc{t;t=pmQ#-T5|21TS33$@HQ8fc z^3e-KD5f=9=H*f)79lcn!uH!^I+TG}Hhb26jP2b<om8YtVW)i?-)0*kr>G=+=%xJQ zhOR=iFR(fg<)BD0YQA}sSoRb6iawY=&I`9j=)ezw%v?h%@I`m9Zo&-Zdt{6e6gXfF z^tq#easi*XuX~wQuCPjEzsaS~($%W{LCsmU3`E`pSYZ%CllbEND3QX=CGsFuag*4i zT=V$I*tCyKyl9XAF6}no_F%=U18A0!Ddee!hrFrX$fdj@0pkC-H>Vj1g;?fl#smx~ z|H8Gc#2<Fv2Ki{*9w@2te#lC@JgP;BtF&A7&0*QETYhAXS&DOF-I>;gO<7crA_O0R zA^BEWlTp#p-s{2rR4rtzfaHH-PV$_FD5EOzX%S?oAHx32`0=-Hv=A5xqb<spj9mf5 z92!l8tdAx0NYm1z&5`%71-BwC9+#hpr+uOq&Ry`eW|a_YcfBuE^0xPqq^tcnk%R6J z7rFdUrzU(fIVs><!&E%0qqogq#y7WW(rB9dZtQ`$xjgZ$v-XA!{yQ*gh{S5&tPN-D z8meB*R+a75vF%kTI7a$j=a)Z2|11sA&~5x3zOWYFjf}>Dkrnn6f*77bK5~*Qd&Ejm zkdrqfQCkZ7f|XzL7_)G$T=RpxA$hvN*GaD3%j_}zq~}?w2ca;_4}0#oqBV(uAvY+5 z&Nd&*d!Vv&twzJ)LPxA4@#61RHS^ElwP*>9xNS@^uN2OxLe1fvO^O8ht65@*6JndN z20!CnFW+uCL<xpP_JLlTn=BGls$)^xTBU5-F;wA+`R8(?{*Q0MJlRabHow*B!0~Zt za$}`)*5oR8M<i(E6ZemPF<Cv9x5Th5NPDdhhT!Ttn^X?b?`iFnT{a}{ipp)avc|mn z7cyx*fZw`oy0w4CawdIY4514BjB`a|(5D&iqzv`?DIQE)&*M|LHb*654HCG<vSGA$ zK0phhS41r_IfB4U&~lbTWL5&+*4idVo*Q56uwv9NK@2?DLxOoATsT6lt?!%->@@W^ zcC;Chi?uL~s@+`)C*zrBK6jHF<^Y8sUG2h_y5%7v4QoD^S?eYHkPCQDj%g`=-H&}% zX(Xvd=RTJMcN&dz)JytH@KpgRuo@cryZ|NT7x_Dpj?6BvNyXF~j@;9$LM;a$8d1UA z=Bg|(lLDq1nKQVwxihdr=2#L%Sb}^USLwRA$lX@4p>CQl;ALX6kNa}Wr~GvdxkU`D z5|N%18Ip%~9U^27+zEmXBDNa_*N97%zm<<#2B1NUm$4bTP<w)Ca=70o<>|YO09JFV z#=Q3`x>L#wQIMMAv4ncFqW8_t?#iM2G6YE|mQ?vRX9L^-LaE2v%1ilxPMe8E-f&lR zvGXShL{(nRWrGg+PxJ+p<<Vy?CU*Ur<Ac`nQOk~kTtW3=isx5#;a6{`1MxF9sx!1* z!dw1rJu+Obx5Zg4K9}1<l$(%RIyNiA5{eB_Dkm`r3t;l4PzUI}12nKIocQYagqQgz z+xg0w>4V4Jv5=(ZEj|dA4|SG09VltQyFCpe_oUMMe2Mm34W|7%Q=bjt%!p{I<{5L> zybP*0%d$0xIser9_WoE-Xy{?HnZb(R=JvOF?jyx|1n}q4<{vZ++&FLgwyMDRi2V;M z0Q9FC!bs_YZ<U6$O}Qfz2&Tc~?NDaM-qV+uGJS$+sYzp{83luelEG1o6_A5RWmZUX z^mn;hxD=AgsGVYro2`I>Nge9Rx?)EN_$)@jVUp`6I<pEr7f)45p78w{{azFqwAh>n zHtaS^y9`c~5iV(-mNkn*C&Vuq2GYCYD&c~!`ZnyTGlYHA6|uP9C#A~b!i}Eap_oqx zRRdtlt(~#JSUzH4uMl@dUg1<Rt6r<)TsFZ>@s-FQ>9X;z&*)X$GZ_^oSp<`en2Pez z+k<P;qY&hUDWUD8_iu|ho4Z|J#?;igODHd%>!!sk%iWuo=dcS}h(IJrrs^&0HSO#` zy-Sjp;-X?c|3ch1D{uTIj$q6Jtme!5c<+H{$X2A3j}>c=<^fYl{>VA{2N8I#Q%nsz zS-Wm<k9^@_RZ(TV!}N%8B!kN6q057!4AxyLtp}bQ1G$ic#ok;c0;KiE<l^6=pxJ1j z=m&!-vMw+~MH9MCr$>e>tEN8mBfX-AHSYZ-+mq!`VKUBjZYuKCCPW_cDT|uLstRi} zX0d_biv=0fXb8Ox-E$E5__P}?>ZWH9{t&X61k7Q!R8z~E5~AN{fwL(de#;}QD(kJz za`AM7tx&{yMDI9{JIiYOW^Kca2I--s^(M<k4H<w7ZJgrESt#6ZCI1x{Xj?RUd z6~_3((TEaMb;|^was8>yAULrWS`llj>kE3Pe%3n<Yj(PSeL8;2L_dO#E<(D)xRTG{ zLcR|)$NWZCC>)9Ds{CB~8Vgv5wdaZA)^?fF#fLL_{OmCAL0Wn1pm5U9kZqFb{96E% z5Mf3T`yyw3K?AkkeY4@C_+Fyg`_0S#bK@|j7{be(%|<YoG;CVM_^~Ajy@-k&@`^By z_6H3l-te9pmP8zLLc$E>o-ICOQk8h<c?)cerpURR;g|1JuyI|rn#V{lm2kVCT!`$- zZs1$KS&7{{DtWknd{X_`U24(d@*U-tW7=ljOVMWBSl~gciA8(If&6t%`fIpgNeDez z1Zd-o7A4|$)t$JyEqnzMlENWsB5n&foWHAAFFDI}wJIlmUfEhF+EH-yO#$4;YENS9 zxmI$jA%bD;0TZl7;rb}F!Pp71=|kD@&D+<Cl|1r>Gp4Q}s3ekt0IrKd`HpCej-Bsq zH37Xp@cS=6a12y_5d^m>jEH#foL6@d&Hcar{x=^3<ax=3?8q!-XAK#z&P+>~EYVU= zNgIeJ2C~HamEdp$eB553=76yzQMf+xpG9ZuRPXI9F7!=eT0}N7wAoGZC^nGA+=|HD z*9Cgx?x?jZYq=(8eskNX0X5YRCv7-U3+a|1ZZ$b+uybjhQ?|^1#d>~Hntkf3-ip=R za*_SGRwdQ=NlG>Pe(t(Ub7J)A{tCHY1S_W0w<Z${Lx0kXV)PsOb<|Div<*YgXZ45M z+cA09yVjp<bZfTU{M$iq6pfCs#PcW-*-;~mp#*oRxtaAIR`3NizNh)%f_`?Y=D*C0 z;q2Q!{4~Kf{YfsDnJS4kt)=}y`N)&Ila~N4VYyntmyy&!g-x@}2vxq9aW{+?{C-=H z_zP@%ZZ?`6UVtHIDU>-*`suVSfZ_+ow)abXl+E@16}2Lwig4zya6VQi#+;^DHJC5w zsjr)5%SuF*qFW>usM<H#zK%GQi1rmiB=A4-MTH}#)YjOR@d)RDoF61OLY;%j&x{EM zL%e*KR`u|I>K91Ra>pFuK>8{}bSx!N)62xS*F3}6(c_HMT>3tCo&B_b^p;>w%KR*2 zvpI2f(=J3{8aI(|d-Hu7(iSgk|KgEiBs}?xO#qbR_Y?~v^t>dpRjJ@e-59$5Z%Kv= zu^%4V7}21(f1eBu<$-Wl<=0=&Ox0ig(Ho^r>lBRm5ZT5ead>AhVUt`%@M$`b{oUf# zf<?S!-mE_>F^lgZo~7j)D|31B^=o|`PoMx|yM<}=vfS8kK=FHLEfvtN*+!8@P6i1V zQ#aw<c~XV!pjI(4mK6sxe(}o--Q2>(tSH|>=E|F___;QuP&r+y8fqS{;HGKF)N#F; z7b)BgFDrD>xm%)T*kcbGg5ue4Y>Rtp`r0+ELy6NeS~9vs6<VF#PxiuOGC}@3CkqY2 z;5Wa=PUus89IfhM2+8;Ln-KY}*G^V`v87M;ob5`QYuYDqh5-}Peh5QD(yt#zk&H}| z$OO|R)awfOKCYX<a{m~IkK#o>wzWxxkotiC5IO^DJWpjob?6a(9@?4r%gbg;^S&PM zj^A(=nw5i<{D?=81EOb$xXG5$hKcBKamcU`Ni^pZA|D8Cx?Dw5t<&2Kp&Sjni9wB) zyy+WfMj&rP^gc7G%8ZFoOL32;@D|b@O-H(7rE&E}R@}FD9y(U^-+i4j_HuuYa__|q zf=1$aFbM&x-!SS{B?jEYFGgNu4phcsQa~C}=eH!XdRQEaIs>rV<30qM!i;D`P0JYs zQkODN7Z*2P3aCJ;FXTOUnJre|vC@sPb<~^$R%lhvOnkZ~VKpfsyY+n38TAi{V^DVE z9NzvFoPlk{@VpjpmJkB@int2ArODP1<?o}pO?W^E)d`VEkaV#M5D7;SqEE-K@d}i4 zD}WcQ$?E=^jZ|-1a~i*{$vQ!Q(?pQ|o9xJ{t!Ha&1MNY%Gq<-w+Hc!7)*T^RkMd{z zRO>GuRqY4sPtVfN@yvMj3^6xsFyo@mzKFCioY)FKp&9P3hZqfe*}x>806W3olw`gn zy<Cx-f1zdk7M&KxAur{8#FsTo_XvL|o-*w>Vnja}gfaS|dTB&0rL8<(re33$SRLV4 zB8zBGHjdLtH=yYU<tZ3y!*&MKA+|THMnvE@irSpK2N?bSGR|SO+1_er6PufFDQS0a zpmGew+ov?)vT}CVU$pK~2g=x0SeJpm!AP0eB&tQX#<ArOVu&y2CInexV{b|rxl)*r z?O|FJFQt(u0EE{55yenBCo!KvcYO~&Xzr#45;fMfX{2~gmh2hyBefYdcp_2?GhcKf z6s@HMs*|=BNA!RPaXQ2mLa7neBXLdpf$Es1*)wM<^WUE;M!(b$JSEK1$P@y!b#TMx zDXR=(Hv|-$?d6Fk-2-_u6{lf~z>f%2HE$=LTU?+zFz-NitFDm-%sXVPE=^A2!WLx( zodHio+p#P^`D1SfIbz*rz*f*~Bz89uO6+#0Ru##rvQ<eK=|vfrD&3R$lpOuSFex}# zE8Xa!-I-vdZ6*t*%8VV~LPKf=KWZRVHJaTVvCt7AotpEgseVAMtUxqqJJ9JDEtDYe zi7yF{VuP#c6B)-~-$u!7Nqrcb?+;Ur+DGRQYcH-uyy}ldOsf7O;|->S;(g#&joi~u zHatzCQi<y781q?3>o>nDLMiYGBqy7qBTPVJdr<3z9X1!^w71Vyj}#?;luk<c)m{m5 z<7Nz*5#?^-`*HF8nWVy3PHE{w#FW!Cuz0h&Lom0@Fo|b&p-qapsNi1)IwwxxS26Zj zFeOS82nM!IE=t8?5_btIwz(Fw=kdB~n9{Ql(9>QTZPD7P5O4A%vZ#Rpju)_SUtomG zj(v;Q<idg`>q__qz+mA|1>kcOX0$C#!L^(H3vi#$M3Z;(#|_(8^nrBjjdi=(>rGDM z)fzBd)j7H7pXueKTbCvzi!w9!!^L`Oi0iX#@hsg41G5K=pIXaPO3Iz$Rmb}f+rL3@ z&7p;>?z3viisbR<rgu;`hfgu;F0(CN-k!4_up~8!&8SxW?sjv8T=<$_b!&hPm5iFz zdqN*m5xFZ60prDrG>h+t>_s)Qj!XuZFP1hu=|S_uqOEny+xJ$v0X%avo$+h3>Y@zi zPv0S<&|d-K2jXXx0VQ~w&I4fDn#~El8BdE7BmP4E<FQ2YH3&p0jH&H?B-QN8=0si5 zofxumZwMSx8`n#{F$FIhpK$Kxp$;FFiSatXMf=g4+_^56H<<dUjXL41e64=%@e+tS zWg;wwn!HWT%241HzGWWd_F1awHC17qPghWX_|&Zya46L#?x+1dcV&2=HM677MiM<W zY8XtrCI==(!V6ansygaMMNdo!4{mGsd5(eT%nZhSQ)Sj<+8>``M}Y74Gj;4y)YmVL z_Xvq)k4aCzjRiu4JSjoVp*1tJg|K+_U}6UWK1)hbf%ELaNv#m!m*0A@+@4!?h~&@> z22t}r9=s}suexjTyo{N-#iK3;b7ZN7f2!%p{QJ)Yvce%jVgEEl842ney^*0oxNSe9 zZckYBF}$Qbz{IZz*I`z>0J|@_bDQCX^R$D6c_X!vMK~!0*-riF?TaQ!FUgSm)FyqA zmx5!rd}%gVLSN$!4lA)GN~yrG5?^014-I`C8*n!_q-zZp3T7w-WTZc0-)pyAeDZ3T z6$6L_)OnU0ux?_sOk3R<9u#8ZJ`7HUAt^f1s>YpkVQ7T>0NU%ahm<wD&Ke)nU9FV1 z%Z{fC?prR(lN5T#Bh0;~X=<ye*uGp+_xWeAy7|nJNeVpL&>aQsa}?U(Fc?`1@Q!^l z0uH#kITU#jSmM|(a|6V_oG|Vb=*y;|Y5zn;%VLWWSaq(ZSOvQ9OG#I9^YUxfOatLm ziKN9hRPkY>)E2E60@sdkUz(LWtq#!W+>dq=ZbzExjNQ0)8A)je#we9tUdW3IR24Ir zTp7%f7g;~gHs5B=&6jUGxB8XvKMf(Wa?>mcz^VlkoCs%Lnk|u%o$G0&d{h2n7RM*6 z9U@@tJELSsm-yhgsFA2kSnR-xm&hKm!8Z}fz~~R)ZFcwuM}C7=hAcu$-2MF&?P{GB zc1HDmwFL%U)f8sA@q{@)f}Lk|O@QGTkQ8sG!bM;`$35LYlJck|9Rl7cCh~Z_m0Suq zxSse!vHIkSgd&?A&BChYDE%OP_vB>?T3}WAg0QYC)tk|$EOyb%L?muMXOSy2nAD5r z4E`U#&qkF%9ch$?wn5IXf_HVaH@}wVIuy$j2OyPVX?LSY-?@{P(`NPrQu&VQ-Ojih zRW1)S83IgTqsC+y=Qe6jh`yXg&oz>V-##qZpEt{PIX9(^na4!=^w1tWKKme==3<-d zt%K|1FejUaVaFwQ&0!VQT&*BiY8UwU3<g&hb&cDy>MmXsdsU-{PAjZ0oqyolWOgJl zM+f?j3oaV9+hP>Jl!AJFW@vj4E{v&<onN+RWOl(TQeF<eHk@pSSIGi}p?p2wAb%dJ z7jRi^r3Kuv#h0`QO(iYnuaNPBz{z$kn|l*cAnEy3o|TAYjea-_U)GP%C1EL~qeuEM z;mYD7>hN&@%sP=2reRt|`vM4-Df){e<mwB$Oq8Bq&hXaw8ItKc0Aa;jB4zHt$EO2d zxRF||9!Gc=f|9eu%9V9|+oDcJGcea6jH1O7mlWmn)7FX`->sI@SMIT<NIm7X?Pb(Z zY>60e%Pg{raPt<vS+y{%Be{jqUK&CyX7&iU@)mN{3-iJotrLe2t>b4Z&sc<9L<Ykj z3pxl6=q7a5&Ifl;c@t26`9T_5C2b$|?DMdek!Sgr9W0<oPr*^(D3{WBeaVdmPZgON zMBgD#M#R<)2c(GjogZ~CAibgA)O23<%tbinS>)%zU-)J0+vV8;scIow&;=cn#RsHX zx9a+R^LXOT!4~e@KaRb9_a>Ms$Otao8G2)Q%(#i0D5<psk#|X%m-yg`w-s+zz&3Y2 zxh;wgmp)G=<j@N0tK%;}^{KDSyg~Z<_6M5SAPObu-Z87sb1+yI?IrY%7^2R{-ry*d zHc91~Sw>*%iXITpY`rp@%7!R0hM3+8e{+r@(2jm&CloEha1}dP+h$iVjx}&aBQEF4 zgB<m0S+yfubR%fnDz~WMcl86@wISxk%A86JbiqixEFM@}coyfq($7<Jn&%LIEx0a$ zHiMbj7)~PL)L=@8p$mF)s-`S)#z0z}E`%R1E+s_pNefE&^|>UxiT!q&5hI8|szk|Q zaXq}6T<UjxMY-FUm)DC0>>b3lDE$^aZWiJ*OFr&l%wc~yqriimB0KN6XY0kmpeF1v zwo(rS@2P6(`S29!w@=ZMoU?a$YHkmp6Y}n|+ISoRrp52}c)L2XCfb<ggJ{q*{;E7y zq}TISnD%KDoo$L3XJXJ4z3FrxNOaCt_E5i6N}*cJwuq$9eXdMj?p1NvENq6i^bbEL zqGS}jK~w<J-Q}x%>rqbWPy_qU+)!Gip-<__DXfN$d+My=B`L#wU;T?}ugqtSjW)55 zh$ZI^6h};*syGwyHFSPrEF(~>r-<9gM9_*o-_~pDa;WLp1Lp;7_FQW}6Tx0EGFtst zEY)HtB6dgr^RjWmE><9K!x7nH5pW3m`YNO~@+jUhqqPudeo!|syBX)YIPPF>M%T`_ zqF+K?d}gsw?6lBA(ih9)5qC>{qU-v)oEVnN$wVSa<4SSHaDI*Zebb%d&B{25zXuw3 zBw;)%=@=@Aat^78J&gKvrK<DSd=sC$s%r<Vvh;CF;f@@SGD>d>Q9hzji@b4SP@QGj zdV*{{JOUi^t0xM9f<ZFR+a0=~@e?bR_9WtXK)~>PN0)YR1kx+6<IgCMaFl`1-i3FL zXZozax@Qm!QZeb*Cv(jm8eAilo3oz{pxy+Nrg8JrgaqcdDZ@STGzsg|R!+Nu+Sw6! z6mLh4!{)A!2n^#kii5#=364`AsJBaWij}k7w>I(CF@=A@qHpPNK)qkQ6z0Qe7VL<m z2?8FZ)&lb}?6PQTus30ziFD=qGBGC-;{dc}dlE~lC?y<zh;EI-%yokH>tP=$;=&a; z17oT4t09pNzyz5{6x?f%(<RmL+vyr3N41SG8_$FV9JG;3K42G9igfLlS%2aACRM~w z*Gi*9vT+&tqYR^eigxLV|5PWQ^h<<m3`lEAGEO3rU*o8WgX1*$rttn0t*P!Qjok_* zg=BxT4Ds11t5k^@>au7uQcSa>T!l}^N@W^x-tnkSCacys*%>?%T0bSJEZFGrDm_+| z-|7c}t}sUlx>%K6#bvAqBy$vhn!fMEEDT!IH)STN8c_qE%&+1pe0@}<d>y4Fq~gcB z#Xl;NbW`$QiZxk~wPmye0^#xrz-Ns;^&TYyp2P6^h484!CuJxszT5tcpTud+j?tR8 zUXh_8970wYr|KWwZk<g>$Pq<li9|^-C4}?Zh5i_IUqVW*HVWEfo@QY}DRD6L^Q83s z7Hs7Y!iJ84-+q9#`3kHFyE)qDB%Gy%7tVTIZ%ITc;8o4r*2P91{7pgFekE6n3~O)Y zQSCpXE>~)<a0DvgV-GR>wdwB}ch~QFaQx^f7eic&!-c6Ac$xW_<>IG2X)02ukO4WV zJPz?1Yne#0D!}YxHj_4VZ#mbZl${n}#EGtTyE?5}{(HH<im-~WZ%v@8s-JOUIzQf| zp<<BsL$-FA>2w3-U1E>Bfp*YI7>=bg*M~0jkc9#5!hsUJZ%j-<oeRo8+0_YuaD4>q zD@U4L!-|;goUO+`yAs6!Zt9QJ<%CGD)3=Zq!*FBDnZ9fMBx4UEaxcABM2X|T@?Z?M zPQw<KVs#doBI=|_K4!}+YA)A|-*TUw$y@l<RK$I#5IJ@_HU8-I!mE%UDB<8t@1n1v zc8R<5EBVUoM{i?Rsx{%H<ZU2HU0cD(6vu2)I^HT9Zsw<#mJ$*<?-0o>pYFhji5wlj zMk`cZSjwjfw?wx*FV(RTeZjjHXyLQLv|-z6hv(vDHwObayWtbnLF5E=l(s6kU`CDt zB~M{qmy1sfF2hq@_u*xuQe$ueMXAZ~A#wek_QoMOl`xo}dE&o<f;{&EeVwz;d?ye` zBM2!Zj%IKJJ@s&O*<qO=w+s543Ij6GGx|0amRww&ROd*vre&)Aog5n!2b>NBbEXCM zTre(1S`}1bAeX$Eg-Y?^_ZUJ#KS?qDMwwq`{E|TEaF{|oclq@TlluuDI^2weA%Ctl zR|F(HvT|;2Vio9`Nnn4dfEcYe$@&}ZsND~B{kxXqaFw#+Zid_=$ao*S1i?P570WU> z^Z20K%@c5f@*;!Z=a45kL%&fg*4?>9^dYN?I?p{#&Xj?ao!Uc~%07|S1|N7hZ_@SU zL|M(rd}R>EJ6YN9le@7<zx8i1V1Su;{u2D@%L1>c;Vc%iBZ%t0Kk;Kcb0r~$J+qFE z)}E%bFD-(=n9Vgc#O+$jHCJi_D;haDL$3!+krnYF-SotGp&0x_$$6-Sc`CcPx=#pA z1bVePGP~wfX=;ms;msmUn3>xT9{u5L?crMo<s}aR`*WbNzMlO>>Z{pfCxrxGvh#B{ zF0Qd;<A)yn?}N;!w6=56!Wbyuk)aFbW4v#$dQW=u>)jgXFE`l|t*xK20h<7yJ)u%M z<owsICg-!s=1SuGr5z^Dni$fws|r^!v_rV(7sGJ4Cj69eAQhvieYC3@!$gUr&<Jj= zZ_o)w=v^$P>XWx({e<c^NxcYB>$$kJAC54Hh5{>AyXzp33y#_uQUVq@UaEDM40GB5 zQt&BZ|7pSp=N;%FOzLLzlrgQO<2^^>7=z7)R9-#z!&WJ7Z?Kx{e3ZzPAF9;vjn?dt zm*XVONYHtbE8t)uIfIKF>x#i@I^{)e8jeNwRa4JFHxUD*7hvVAfE(a;giXWbec^~M z@L`QgJdM`7%aym`W!-b{$BW}aqG>}wvfJ$Vw=MKG!w4Fct-x}vUd%S+ZXM}u_L80k z-^IcYDigS+yt`pd=>g4E^*709>kJ^8h>n2Ww{|qxy{pXKwk(IhlVd&!Pe_*X^3-fu z8Ouy{Rxy~3zC!&ye=*Zt;0;s#c7wXIjEyAm@4R2MUE!2g${-~_Cc(&xTNs39edJqk zGUlie2No`MY8W``pT(d6M%Rk_i_Si*px3X6<-HZ-j_K*bx^Sb4b#)z-gbd&A_;$&_ zS8zWt{;;RnX|$a+{XER2h#kqAfRGz)C9J>ePXVje=IAipl`qJ^jKJBKWLNPi85I7L zfN*%X2ZPx_eatg%J3|;d=TR-{;!;wlGTO*%c+k~!IJ_DyIAgZjmY3!Rm(X2ejXT~* zcKZ+&*$zH@0)WH#d9InH&yg~H7HJu}9#vLP(L2C0j$jn3Ae?bhCI)J|<+V+Tpwy=H zC;jlvqT2zdG)0AF#K!hWin7U<dMHqs?3iVfyD42Z9Yg;&nr;#qM8QSF)g6N%t9!dN zd=vk`&jyiK-Ig1}`>l6u8%raCUxof(0B9SR<jbN3tP4{5MrcNJyz3kRYkWqXleo<B zJWW3?bbn>lx`czZMj12Qo~E8(C^()vI$(UdaeOG`CcQ<eA;i|uxfOH2<?Dj^*b&S! ziipVtlF~;00xT~96r%h*7h=I4V~#2*V<AZm;L9H1CPNX{UG~N{1etIIavY2w$xfde znX{7TQKg$dBy?vbo2~F+zh7|Vx(wISB7a^vh%_;AYDWk>@2VQKu5P>!tIjKHSb+-7 zJG<t2c`%ZB096@|{GeXO!{ESG2`BC7i6FpB1J$91w43}YJcbXr>J(nFjEyXlu&G`E zl?{$C1lV{^QxkD8SGtHZ2bCX0(x!_5AUaEWTPhu6$_10&hsd&jPR)AEz%*~5oa{On z@nn6nGo2;5#V*NvKYf{RLL86_>$AkdLtW_q5N-=C{ruQS8hC><Oea)jINk}gcB%m* z!jc2gKzn$G&_N>8o-|s=cF7$a=~VRdS<dB8WX#CeIIF#p4ii|M_3OpmAjU6w;9wF) z|LXrrX57jJv@e@>FZhsKsvB({SCEjRFuGPn1OKyP_()im85`+!;@R+qAOx5d-5Bi8 zc`k&awU9IO8+{4D^Sp&Dp&(=fN^+2O{qfSt`}+TQ)_cZiEUsL7UuNvTyag$RVZw7p znF@^}?NiYcU)M$lS}l5gM~&>kt~A=pl?h)?7eOcG1!~zDECWDdWt`b9b;GIyAQ9z# z`3|X_Xt=XT4vVqNHFC;)DlP3UU#e`OPZm_H&+L!<5_E|61nF|JTJJr4I+sHD#nP`Y z_>1HXQ{<i2Z9F<+p|lcEDyM3}`{+`)nLe2QG2D}D;*A7h&m3i|d@kf7h`krvm^J`d z3${RD7}ph-gaC&jbBkPz9r4f7Z*uRaw;|5(NvVHBlas7Vsq(bA=~?K9e3KZLKEmjQ z8l!XW7J~BAp+na5JlQbX>#-_uvV0J0&`!^nQx4>1f>+lS1f(CFoOYN>0CLb$SvGaF z&bVeHLS{q`9l%e2xog72Ry=)x!1QLecv0QcV2g?!@H#=b6u8~!4MwiC@d^By%k`{m zIa4hMiDfjcd&(m^eIfnKNcky-^%3zE&ksllyTq=fh!;q}qVf5lJk5X~)#Q?6*7^^1 zADV1#xL1<Jk{~l32_b{bg@{kw+X{eD5)x3q(|OPC5#;g8aE3Dt(PbY-M9)#$sE~rR zk%zOaXNgT$87?%&1683<<oi2o<v16SwXFTR2VVw$y{s*#ZhMK76^?Q+3Mm*+`BV<W z1QZNT6=_nPLo+s&9pvtx;uP5B0(*TP3?isHp`S3TCG#k?f^2SEu$$Yb@Zvm=UQ%$- zIkXAY1Ry#>V!Y?X@`d@mVM+krXeC!6iJ_Aftvl~-&GvYRccTzMaKa-O0YIlwZG-A) zId&sS)Z3h0?>HR<R?HwgG>z9h9XiPMmV<3^;w^kK-D)L~9`8QlQtdCSBOaoF){Cvl zEZ~?*Cb(K@-9?aRR6D_1^EQ8saYyYUgf1++Cm^RFX#U%rnGxcp1amywG@(osvxxG8 z?I&RsQH4=S78PXG@*bi2F-{k(ace$#!P!E{cBg6LTe#K`c~UXs{+s3p6>naJYjsZ< zg?Q-~D=~iWa}z%S-rxB(O(jDJJA$Zeu^;{sY{qZvoPT=buC;P*Q3e)4D|=()A*?Kf zF#Q!gfQ?%vQZUdBOk(kfS~O+0OTMyq9iEM)#Ec{OFQXDNznu*E#h21A^^u~BeKcK| zF3?iI&(LNqF^36zTIjQRS2W>&?1d865^Pzh4^?^2q{;?s-xrt73W1M?ex`+YWEnAP zEpI(UUj-|D;ZYotPp4}<t05sD;ih8Vb;ol15i&Z^Wgr@PLxoIXDfQ_M%{5tK6@-zf z{fg4Z^l;>jA`zY-$)%T(28F4<<jbgN(^9R$3RX#EFmpxQ)ll@)s9)<K2jHJTi*K+% zjy|6W=a|S^{iQP*7>u1mkS<IYq}#S{+qP}nwr$<EZQHhO+qZ4o#@q94{)k!3VwNYW z&Z1Tok&*diOT(XL&KmJm&d?>^d7y&d>xuG(e?eL&+%kkH=^o?U;2n^Kc@|j!HUwbH zgN+XA*)41#EjcJm<BfDtZ>@h-ne3V14kf-(oQ76Y+PD`_`sCj~ZZ^|`qC0US@YC*` z`_O%WjjhA|bc9Dyz8*9FD#Ne<srrAGrv{MVeHgd&F~!r~8>p4PIrOTjoJeAdP!B6h zlmBFJW|4OOYTi4HV0%nMR*4ZDY^WcQNjZ)~h(v%NDu;|u74A#^2(}J@p(3eS2G5Nv zj-lU7&+PHof3%t`u8M;hxhh#D7N%9A&sky3^_JCZ>SxP$(J4F<NGGK2yqq<B&(ikS z5m|<tTy51jdB)b;K0xe!Ac`S)Q{a@ZSE`J45NiU#+C|h~rxSykeG8Ft5yhN%nqet; zgQQ-Dkc>0p;HY8EFvc?I_YQ1DfQD9Be|GPjIPfORZq10#fY_q!;dNEK?;65;*~iJ3 z>eGHOEE9L^oq38Sw6HMdlGz#vWs(nhwUDXtzb&bRG_1f{PZ#ofc-lEYW8>+LkDq#4 zP>$jDdTe=!8GVzaPqR#!L@^{$N1tkAbX|8v2WwmGAaaiwn5^KbwSt&_#55$fE0xBI zqEt$Co}N$7Dy!(HMq6c}^|0o@wz4fgK1Stlz2csN5$*B|*AIeHre$k$7a@vVWpp+% zJ5w=l9^`BYqN<)D;4eFe?5yesQC@OIETc3JfIAraFtEoCeKj%i8w{qFw?4a~%ap17 z8?q&qR!6wdbXE=fj?C5KQX!SgH^$Y1pZvfuv+Sjyz;xlDrWif(lzy!G#E)}JSYZy! zDoE)~Qo^T{52+JF2N+ivQl}?F5sR|PwTMg4+q7TVjY;lkp@$a42VyFGM<0%&Ofk7Q zL%`HDR{8oGX`OGNAU*Vr-cKRn!C*{Tmei+V^o6tYp>{uX&1M!_FA|6oQ5Ft5iFTt+ z808Wo%<TWul&uu@vGoR-OZbPjW+~F~S=42DwHkir-BzYDF!zGPu)0M{**4IY*+Ghr zOwAG476apCVEoCZBjWN9V5Z-1;l%-M2v0z(==%|{yq6aT$e{I!NHDS8{kh>SfDIe< zy;J+`#V5G?6KE!+nxW;&E}FOhA*v%AU=fp}J(p1*x~1Q9>h`0`gxe?{sDY^nG)IJm z?AQ%HLtAeg3`eVYw=64vuj`_tTEX*zHM_zA^P3Cl>$*O^z4TUZMd+@3i;i_E5U-n! zTWQuFCe*?<>gL6e(24bQU0K~x=TnQ|t3V!zs;~#PdS2oyn{;h7%1W3y<eOZco0Crw zC^kRY=cU3BgN!mS9a0mbJv)MHTO+xL+UWL`p3^ENyO>(I1uFJ0h_+KkSSjQt$<SW( zjkhF?KWdJT5CdE7Pe+8~fzo0Ws2eew))N!h88q#0SftEJE0(YjNN!OtjyVw0jDsJ# zdJHS*T71+D#u`1kDjO!jTe;x#Hbn;+k+tX91Y9{064KHDoX#)Xd)YTPhu#qQZ2V8) z1#CZ~Mn38#M6p$7S-=c^Hy&C3(WP6+8PjsF_VQJ<nsu74&-Sf;fgw7!i6LS8E02Yy zDrVizzg%n)-M?K)^VT{@;?|$4#!K#4`Mx!$u=EA==2w4uq*x1y$+T!Mb<}FjIyTG& zt;5Oz0jy(5e12vM0Sv(j&q*%BgcpTAMU2%U3!t9NHH1+5o6xH7bHt964+!iXnBi&~ zrC*g#Ohux=wIm(5J`x7og^wpwW}NF-BGQr<!O)FUl7|JpJH~`zRU*Oq!8Sg=I5rN4 z?{l1$=4uTtV-QzpV@#T{hxvE&pozMTV?sh;Nq@dUBDsFoVEsx>H>k}<cGuI)FwGIZ z@;y#OL;;H>z&G`MQ3CnlsD$f+jr}_z{i0$ma=+jGLV*<yFfvQJTtu@p73|P}U$X0? z%1iwU(A{Ux!kzJcIF00BEY^EBP*1QLAFYQZGZxG)^52I1<rw42p;NP>d7r-Wi=Y(P zjnu7P6Xcod32fkc&<hq97l(HfN@Al5LyKBJ_d!}y-zp`<cjWpH7xOVRnmJLIWD=;t z1#}G0i8F-&Ko>xlZG)S(_~lmP9GIh=&NOX-u2PA`Ds^es<^<wxYO}ZbltOCr3k8{o z(JXnowv3Gk9r|uaKX60Qzs!25?3<`0Gb;&*t4!UT?U6Y$-#t#(^tKH~+~0SrN6L0( z?min~;d6Z#1+8e~K=v7MhxgQXvsKXM327s&%aUs6oR>h}AlYy9$%SZ|p6gLEKCRF3 zv74ziqq_?}m7S;%E@c=bd13nXdD7K8`hCma0;U>CdrUQaU16f*1$k~XUt!jgUtf2j zXvcuGd+KuFvHG80w}U|b`xv$_-N#oyA+Eu7v+u{K()XLBTIQF<`ne4?LORlP+{W>> zl!f~8q!mc|X20#vCrvnP9{HQ=Ch(k*jCNp@M9h%QIy~*XeQ09%KHB!9M<pJIGDWJ6 zXKAKjpB~e39*4Krr2L!r?|$j3T}BK?%+l$1$$nFnJRU-SZqP*a<^^(3d$JPp!Amye z2KE&@liV5rJCvk%ZCWn7%44Zsn^d^4u^UG+{BaL3G}T;Y#&>K>{>V98-n-8ro9w_r zkv?2YmEe1>27&)4D_cE}U%JJ%CFlDhSnywfWR$cm^21)>Qt1vw590!oO(aZFvHx2C z_X)+NH-`9u)S?YZ<6C982mC9}4Si`BIDK@r*6P!SD*Jwv&_xUZ3vcF6%i4{qoaZS3 z8t61ga>s0}lCgBn56ziQ3)mW+*Lf}$mLURj<~UP@T0v9ZojpmAwO`0S-gdoQ>P)~* z{jW(JiQ%A1m@b%tCQ`dIfJ0f3;tLD%@Tya{U$%V~x8Z?y*yO*;QAk@FIk@umyrqwc zh(d3iK%F#ehM*;{+_QD~$uLX>!nrTn1<{CAt`(9LRMS7yrTihA+HwcqRF)hLXAlCv zfR0fdjW_-IGm_|COPWAvaM&h;t2tbu^52dh`p&W9{ieCAzh-E4H*APvSMIjbd-VNS z4{Gx&{<)t}n(6RcSEaE|q0(J8)eSmeCE_gMkD4?_AUXN1a3?YsT^sF+!4W&jHthxl zTARFoY<vO1zKr*Ui1$@tc2st=x_Qw^mOCA<<^eA_;`_FF`5)Pnz2&JXUteeHpaq4P zgF?9<R7-jFq6wwIZtOgJVc$4SY)!S*qqh!A(cC#!0s1eZ5}$53Db61>d)mIO8@#S8 z^oot!Ez@RT-$h38JA0M>Hj!A}d~G4}!5-9e^o99sRV^&IeAdKNwYHJMGspU95^Y5r zFY_O^GV~&x$uO6NXMVM+u#8q}t?n<RR$|l<#td2v#4#|w8#8Ms5QEtcv3iN0g!5^~ z>t6mp`Ob+~l;{z4Z~lcui(~TKHl<XfR*_ZUorW#)q*Z$`1jq5Xf6;V^t}3JrK#><< z{9hHA6t(LnF~KpGV@Q1n2j&yE1ibyidvgU1=&Ab6Aza1&({e4$$TITW@JYs0pYoc8 zE+oZkGD_Fux_%I>*~R-fdCaMityL;^`}cg*sL`UqSjY#-NS2-Z%F-f=@a*di@mB(2 zS<Z3tvd%A75g>{WtO^TgFb__Oi2%Kt4yZUz!SErN^ge3?I%J`xygm)v91_@HiQDoP zl!a5?B{dzEA2TAjN&Wq{c&f@oAK1Ww=-PE%Y@lnO{zH*>qsi5(KfYw6U@yf0%y_+| zUl9py#MOYE0-G>SvQJfFIsx^a#1iP20U(d^*84F^wUR%$mXLnOkjgE{@L-CeB$-0e z;L_Sj%_eVQfl2@)5Q?%Sdm@s)a0Tx<eguXA%~VTGQ-<q*FcIVPb~8!RG*d&c7&Loz z0ht;5Z3CdR4>adF1)$ELzWBHvG1Xk}k!2yz(7hJ4{MO_xZ&J4&fPl4qR}ZlYf^9PJ zGnf4&9ZUXvlx;Y=+|;*oqJVY_=ICz~+Iez_n585C5+`0WV|eKIJAjAzO|Q?swdqK4 z>oR>%K;nH=dX~m9Z3}d#rn(c0#ddBuUIbq^?&M1!86pZJ#choh-brZ7C}roC-Q|Rv z^kH6|_Jljez>uZduy`kj)A8#rdu1Qj+Wj6+KlSzNQ~mWvh&FTHVYO7mP)%_+_*c(} zIob4rOB~zg`YFufa5b-{^@C;pnU9YL-3}MRv-t|FEd-RXqIHdhh2r+@LguNRa3o`e zr1YBQFM8ZZVI^cpwcjRGx2;(fcnzced)a+I^rp;l&M;Hw2(2sJUwU>!sgl~5RZA%@ zlw#q2KfM%a%C)TH0Tv-wqbZ#^qR5Fo0jZcG#gLAt_eUeipovhFLFWX}B?^Ag%t0A% zHJa^fjx#YKRpUpM*aDy86Jr0${I1LtnswXb7KfLy?CL3><X>4|QS350$pB0%75ufk z<`K@j#>Vk>$ALglWn150kXX;y7Y^>RDA=gj5#g%G8@z;{59-NBMYlO$cXk^c%9<^C z4`brnAxeC?(zgs;2n2odz9@!8hz?j&;8w^^`pmtzEo$p;kB7C_dFwacr@7xXwaCQ7 zFn%_zYS;`ig2X?q3#iyZLT*le+N%e{fh7|`%@f}6_y~l#_XtQ#n2D~=Od~Lyq4$*Q zFu{|ErxPF@g$};$(y#07CBS>+8*Sikn<Bcp5jT&^J+Wj&$md&PzeF8!g#E#2b)&w| z{m&`@!_P@vL|hY@2}Xg4WP)+RV7FL2?c)To1S`KV6bW08pnl}3iH$v)3z($ChpnBt zhK~GbJP3-ofPV&JE>Ks4bnXJZW}v{>U8G(xPvH1>73di%gGu_F)2A~P>9bAW7b*9r zr!&HMNa3tc&TTo+0fO%|A)f7$Iu{eRzrdK>sP|K_LK-L-`CF-*qE{F4i?Vv9PPFy@ zjL;yudw&peBsi_~Z-n=$J>)tdHpWtKu0{XugjrAmRgd2|N4bAH9Rae4*OJ9jdoy#m znKns0zI9&B2hP6K6K{<A<S65wH>*{UN5#_onF#2lyYys9Q`yW?U3wH1yf<q7re=1> zFq4jr?{pSD*CdBg<phY0)OvEU+26AF-|v|{Lzc(Iz0fl%+;6bj^w;Of%zGkAGJJlx zrUd)s`+!}$g8Y2DQoVJ6#RLq{K}la&qi?%j`gAxYxBtr-V<q)!yQwKPxR;R3=Af<x z&A*t8_wJzruyvoM@9aH$H+=%$=GOWkX+6U6NiXQp#Fl_cTGv>jvi7E8G!w*&6@zoe z3mnV_rd)dSY<0fIxL2uTO`NmtVej8hv(5Ig@T}N#RF>+3yJTbfRmy)n*`s4|o(>(C zD1SJ61LJQ0a|cb@YWQR2w@2X7{XKkGVfc#iK{($d`YzZ8<xg%9EE^?J5t(k7#+U>( zcj_{q7ml+pwiVla+`cx@iSI<)pX}(^^o)L1+Wviy9}vk=N@{jj2n0qNkv5DOnVS#h z>A^dddAtx3snZA=4TYYeH<o`Q!qHr-{ZlByf#L!^&B{+=X@#jl*<-FOo$CbmhQ;p; z+U~2`JZ`S0-OohYOfaDK2GZLT6URW#n$WkZQX<&b{L}7An0x729$?u)c^o&DfYq3i zIvI?MJ+Kl1$1_&!0yf-cOOnM{Jg(|f%Th!^o80q{^u<Mep%$_0QNz#eSY2Xq5@z?l zBWA1rdqHwPk^HCdJrMD1iO&ma9BPqG>jgr6q??Qn`cHpD0#*jVb2qqyC8r{7OGB|P z%kkq8A`3?hPV6MBs+Zcdc3VK{TJu|?1LjIOI{xlD?(vk~fN^Oo@C!SOTu1&Fm97p} zNJQPqdU(qPK?3P?dCEzIf-*U9RUYuEB$z+qn(FWIXWwz;Ku)^xHl+uNfc?Cdui_$~ zdeSlReh#yPP$tC}Q`Vt5eQC5G8d%Te+r~~a3v&MIm4@fI+g(##!zuerh7os_G~Wgh z?Qdo{ll9ydV!gB}*O$fBQ+6Fc$*K0Y9XP|^j_)96Q0Hvn|4Q^!O-u9`6ex{#9&Zm5 zMCy>K9@+6yVCV*1(=O&q^i)zM`v16k^$w4EVq1|SJw(S7G=}Itj2qw6+*M2bU?l_P zUp<+AIWO1XILVW=tHTZxHS*5&__rIa7~(P7?ntYf)YS^{2@zuCcOtH9H%azZVWCJV ztdoDJ8RB)LvBWJp4o=Yk-11Dt)Lw2`QiJCBwk693>3}!|r#P4*po<#sBd0M`tPnvM z)hgidKgj-t^`INcMrLlSRDz8fj29Mu!%~F2?yhg+a9`CR5ZFW$a_4{Zah#jtodc)a zgBZo}=A?$*Wf_}_>J|yF&~vxFcqo9B&R>xCKIZ6VMW$`gf>35OsP2gIzqBreTF!8K zL}MJ{MEX$Vfk~rq31Nhun|C;`W*gi7M$N;9ll0Nf;Uzj5GD%sA=+R~+|Gl2=Lf+#` z14*;xl6g37i|t1=iVz+W**zXqnnlrF`Jnf7M*2Cqbuvcz*G`Vmc+wob3=;MqLH_t_ zs^p9S?MMMfHMP~c+@HU}j#x}o^V&-y)P5)GVHHAmjFB1wLYymq)qHn8)&k~M^k@DP z?nYo5<mmdKpf7N8Vy!Ki-5x${14i((T7Y2BbbU&Ux6Zx1guyqDtAKC^CwpU8FS1s9 z%9J_3@PLb(spcqULuw%|xyNc?D^ivl!~8V#rM{^gL&vNJ?<(aXsUJNZCDt%3xgfv@ zlekKe0dcTHkk3_EMA)0)ZM^V<=0R3%D@&cXM9J5d1U(ww8mDW;PLzo304j{C;F)Lr zWLAAfmQRZAkazVJRp6m&Vp}-$%<qnu>ztx`@gRe*qr-A(s8A0`uyW85^ybvwOyjH< zG-!-?_zSr-5evoksDI!`Mf&JWd=E&YVSz*y+vTk6N6|8-0f<C1ECB8waIrKueSNb3 zvQ5)CJF!xb@w8My_x=7|$kIOs$_my&JSG7@m@E%Jb-8!HCWb=HZ`cH!fj30doiel< zlu(?`loRm9XE7FGzqGTDyh#x`_n!_4$~z;OsL3TAeJ9+<LtlT9^&uhaFo2$mjo=o% z!eAbV+S07%3oD~Pb6SGk;>v{Nl6{-2k`vwKzBtTN?&XPxHbLMZoh-aon{6({wL&~Z zIUOV`*#v<Aia^crA#3DjX`WrSh=)ng2xsztAKM#$Yj%pD8FJlbbkwGukuxiCG>Fmr zWm-Rs0>2D_2)ew0Yk<R&30KqQG*0@XEXRI}xoj2XzJ9=yh-|;!`9DgbG>G%<92m1c z^Ue*+R2tMjXhsYL3}=^-A6RmCh)>6T?N66M$!KR16|zmWxY{(M+Nrco1BvkG*8YzK z*v*nZEn!<t`8G1afzz`$22)nF!1wci)M_ODA9!^RLPkOdV{1ZQ-v1HQ|HG?uaB%)_ zVkTr^W@6#`-}ryy)md2BIobYy@#>ytn*ZU|>27c3k8V-6cXonAj&5%Q_ffX#I><YC z27|i6Kn8bm*EYWLl6~iT{rAQpXEWH$Rw}gAY}n8<qqvhRI*X|krxpieBV#jD5eo_` zPAwe{2gasKAX;48S)70ySel!hi4~P1yMg4kYw++$Ww!%-0zB;1fy`Jq6lo`dQ&TYm zVF=+}fw}@9W`WCgfy4^3Bg5KJ6W|4H9x)Z2T-{8V*_^=PLGfs7@d8{6kenna958KU zXxjI<I5RT*EI#q*#^4fIn3~<5U0YirGB`6pk2BCSfu-Z}2#eVQRu_Q{VOp3Qn}ImB zfmj2$f#lqz*xUkIvYN`Gxbavh8@sxblZ&VS1FUPTEu@%(Nk&jxNrD7u#{gN$xyA1J zvjrd!0@7lD$lw>=@3;xa_YR_xu#2#}sFQ4I`_F*>V+H}~>DKzE|1j9E5Sj-FtOyoj z(8s;{qXR8ycXo0;G&Xp8c`@sBb$2oGbZIj4Z2XKW3{P#M?_Zo7!vgts0o?@nLm%B5 zA|x%(!n}I~?Nx&)Hn4+ocYydqN^t@BED@7X(7>9yf3mS8q5gaG4Zt0;10?WQX>4lb zrCt*p9UVNNH?lPtXJK$;5bpTg{P6S^h7m9g@d=)_{4IwBh2-Jk^r0v6U?4*OOaH`h zX&hIOd9n5Jne7R9i^}Be=>Gf`$^Ol0%PbDAZmrI~+WQj-1Z%^y@9<jJzc#aZz>r;3 zkyMjX(gl$WQt^PBfrck^$;sILxAW)ZhbO-x1cV?UJQZhPY#Q1SoUO7XxU-|UmoK7~ zX2{`#v_^=#ldH?K`TK6H&CT)I_5Mcyg0=>4hR)B%;r4c<=)&;k8X+b1oxmdj`XGK5 z<s8Bg94Hr9kb#9JZ4dnSGJVgyZO=Rb3D74WCl3UR%A--x-wKZO9JqgFeFzNJ(b)m| z<NM2XpAQvygEz3fIRn3PS#T3{ui>r*2`d3~w`Y!&><|B=fVu!^Rl5-UTG?J4oWn6h zXc072a&`r61-tpp&wVv$E!n=gPLaJ1Z26U0{&i<<Y;Su4D6IWDFG2v!WvY+QjU9~N z3`|z*lvniyUC?bfSgQL=f41na%t0>wl^|t!2rab$%vOM1W%q(z@LYk_{&<G}FyIt# z{;`3ZOEas$=a(@1-#l<oD2M%6!7IPBm;=Psg{34^^Y{H*rwjs8kSr1|HjpwvJeV8< zBcr1uIDzOZu-Ce}KnCoJCfT690BZ~&*yiA397?eL<J(ij21i$+_uhhST_B9by|R8} zjsUT1#6#c)$#0<^AdE@>Vviaij7otB_yOV{$VO02Qve~t0vdo&9w>U70IZ7s7c#Jl z=3D3vh&IX}DI$7_0PL{nKmI!CVbSA%C)Gbf1(%opNEKaU|6Q*8a2T0GkS?~ehj#@I zLWmNOCsfw{Z!6`sADMwt_zn>yHuIYVFQResS9%<_DGPwp=oCb53}bD)0QhN#oG^WL z7y*CeaA^T;UF@gL$?2zief5`aYz*?u_yrA82Yp9`LK!(kG=)5AZvdzS9C19qAI-mP z?JVw`5I_skr~PKEJ3xWmpg_8)@T~cF1V(866hfn{O>IrWoZllNCd_^kAd%M23J^*P zZ21c=%-jHgg<5WY1=$x;eiJj{S<S`;(1dW}Mj!mGesydm!u=_SA+oBL^NkdxDNq-{ zO(9#}n{jh&e@%YA7{AgpK}A=g&mY%P-yJk=`)ya_el=m`6Y`t8NzRj)TEF6ZY;$=1 z#Q`iFI5?7%{^#=$NjC(|KxVG3EKaST;h+`w`Hu8RCLA=F`vPfbtSlS~<Nja)&K<vr zS8qw(zjx~3sXtf1ga2k0Px7k*BfP&sgH&I>CA<Tz|NejmDSv$*Ai%r;cYV(u3(WJR z?s)(V(*IoLgWmh&hXIBz?djv%1nq2G7J~N$bkXFtb!&Qen}h6$*%R=dpXz_%0L4K6 z@@1Y07LASL^!sFUaBG0b-52c5kHDxvt)o2vzsNSPZ!VJt?S$tg08GG-A`lQrZ-6<} zG;Eytw-LLQ+`$QOl9&qmf@;sqxEiN0w{xW8bfyYkh$qU2z+~Xi=pdbt*2-uc471OF zV4gt)GHz9)b@zIl+R1;(Yo}GjTjan|z#)`LMJ9i>XR?U2qGW{7^^RR3o&Sb*mFBQ$ z*+trs0?jsxIPJ#WhHJjwIh?0g9)F_S*?=$P<)5u*HR@h7_M|O9aYLt<aS!h7;x`<c z$bO2ZUs%M#4m*t<8|HX*GkFY{@WTp7EZ>?w?3hR|@pC%VSmF=##k<~!l7f&Rl#o_6 zq(ChAEJ+MJ%v@`X$OV3LMuOyNUT>b@>r(QN$tUA@MeIfJ|JSoQ?Q~L3Q`Cr^ME<vD zvpwHjW-{G~;ifnZ-F}09`<g7`d@^5{0a|i`nltI^v0{QHan$q3um9uG%wS&M1Mc93 zV%ztqiAh(LIZ|X*iGyWCQ|W!0DjGM4)PUM~0jgtN<3w(V2SbKcMAB7^*BECPOp@<5 zx{9Upr-7MQJwUUh2TOMDd;HDHZK-)`hdv3%!!fph;8n6(+TQiAmjrv~Aj5*T4xYA@ zVub5y^3^$?)NoJ<?%KBJNGa0C?mcbi&#aoGe_GsnQCs@ai7A$<aI#vy3ctIfCR0tA zhzSn%z7gO!T}DAuS*Mi1+!<3K^5pxK<*C?v`!7j5NLwu7pI^}+C(<LH*jb1ExODPo zSH;IxC~+y2DmdN?zm!#lxcHH_g%>}r5@9uK)psR=+E&~b-fY)i;;*dqpPZPB@t5~O zHCiHjWn?%4D3dzbSU{PnR=Q~9m27WwW%s%UeU?JUF+f`mhn`rZr%>(id!=4_|K~~; zODAH}Qc6^Nw<y$26;WTgzo4x;?=cos6R)VDD>Og{bDTnMx+6Li%7MuPjrkQ{*~xNt zpl&*l5)`r#&^4pyY+>}u8PKY81E6Oaf<I%g-f6&6$J08wXKURmJ6me5k=z1}_og^X zsxkd3fB|mux};6Ki4NxE;i-J|X|pD2<31!B)Zn<I8PW|uHdum+&`?ZZh#k>m0xSfD zh<iAh74K{8;Yl90gu=gl39mz&WrMqfG(mn2!o{IQ!H5)P7Ex50*4yCc4i>@#qh7!R zNr{1p3;flOi`%DOaUnMT_h&g2qjyxD!lR@zR0ciepLCU9B_xi?CJ3u{8A{=NgKsoS zQ?c(v?iH?3@FADU_Sdr)y}+m|BJa%kZlt1Qe-Thbtk%&zM-+-CSVv^nDaGB8W#(N8 zKcctZYlNgfzRnL8sydxxeT5R|<|WdnIvi-K!lRu4mX-3I)}vUBb-j8!a;L#MWCxha zvv3|h4e+SV?R0{`c44~OL8>+G8Dz!`hcmy}^HZxXc3r1C(Sx0KmG2*HVKwuc8u?yx zmgHH24`T=W=9>|R)D=<M1w|@sWO0A@SwurCyd2vr?Yq*)4|}e*Y&1lsVd4np5$??S zh^$)Eo*%8Dn*ru?mal(yKR-CM(8sPkvkPY<QCoHFF^1A5_|ZV8qbp6Jao53~5N9Wj z%rk|&A@XCKC8Gc^PL?YzP$E7~;KGDpgj&f5co3Q$U5rAV)A<$y0sh6?;-W2_?8Bb< z9b1toLCb{t_QMm~3{)9)D$=Q0%-PfFN%TSN@f{dJYFnuhbTNhM0+pEo<*q_T2LVu- z**Tgd1eQ$m={|eE>iu=MI9g;MyI)R#wYZq+L97$(tl7r{O;#Pt@)cO`#%H1RI1-UM z!Io3_6=4_ppm1IfEA<nW*YDTkDEU*JawMfr#z1f!jNg>pzqN?^khVU#42u2YsDW<V ze!O4n*K0z-2jYWMz0vnI`e7YEVzRri8dMFV*7+di!CkesP~%Id;L|f9ne=6>b9XJP zYtYt%CBZv_fr>%~uKFR0nfAUG@GIA4$-Z(LZ%s8!R={phn)KKj;BVq`uM0az&EblN z;Y=atJ$=KJ9O42&*vpxe`Xml@2N`>|&e%CB>SXXhF3z^73ktfwEw6L__SMvFgrdFk ztd!Ufw)sh)bJ92w#nbHo<EJtl`^JR7#F*^35c|j#b0kBWzlRL%Ny=h`Z_oxI0-z*k zL8Fspu>SHlYO<T<nU7uOB@L;Ej+M%-K&EtLd0W1681o@Ll390u9JQt^KatX+=~_ad z-B*ctk6z0;9$dlIw5U7;^s(rT>+U$Igcz-)_yFe%M3#qwCqJ>9VxgexFgzzGn&F+> zOmWqGH1}4rS)VImy?mjXuKamT+MJ;fwETmQ_Grh~OCe{4dgE%}N(P#bpUeNCEf=eI zlGxZXGv2|54Yn*S#nt2fv>6*M-7*-5OQCj$VfmZA@>ofv_%eC)?ML+*CRUZ0!!K;l z+zbf%n&NQm{z-N$cj@T_7CUu*Ey&FpM?^!5mc;fVaOMJ$)?2SNFuTQQP2h&ytFn#p zyRDlHo31i+xqASu<M1uwjIyc7NsG!%t5B<tV3pX%oTOIeAub|IretzW(<41nKcn?b zEtzY8I<Zyf7RBHpOk{I$4nNSpB3T4s1fH)3&e;2`OU>nd@ZYy>B|U;hPFn~1$1+JK z%)JDhU;Ss{I1<Psd^8UqFb=A7#s!oDLR0jY?3PW-1D7@q+-2Pb#g*VXigb@#Ti*W0 z<?}K?o>S`VB^+p5`H-H<k&B*u)HWiWVpb>>({I|xQ)?zg)7fqq(IFQ*KW?4(0uM6C zW8s4V#I<4BQY++doJt!4bllE03>`95RtVl4ma2ycTMed7=;;XJI)jNM&jfNwOX={x zv`COWw@%SJp+CA0T{?X?{Z1rXCBB%?I~utD+8|lDTn@;vM<Xb7qLk$=XUndsd0jS& zL2JF!HW7K~<g`Xck?7<2fIqK%W{3o{LK<9X2MZ4fQt4oJ;VHdxZMzvh%VWVnobH1m z%MYzry~-qUF0&MNy57C|QjXsf^>Ph&5Tyu@(5_NZmy?&m3yIg(5@+ED&eCq@ZXs_i zq|k)ozKMjYQ&va7YrtYVFwi08kB+yURAy;0CRKdhK}UMUSadz(F*^={Bx)J$SS0a< z89<j7_=oFI#>c935@=d2Ru%)AKgT||N*A-(Bu3GZ-@RG981Mo)bfnANM*p=g37NWa z6DA~m@+eDeifqO1xYaDHc>PM9>lwJ=DJ79q?rf{;b~==`)rO#GD)_qB@sN9%Za?+7 zI^)i+o|xQMi>K$lYQcdvqfzHL_3#6dc?wq?v4^MJ<44TDR<=xc>b?4#FL0p33|_)U zZe_%%60G{?YE=HkN}M$xe{i9eb~$Qy4$@boZ28$y--frF2qUS+mlQA>@M`@Y3YU;o zVG9uGD0@xbq*kIQU+=<xPX4CaiiN^>k+0x5oT2}bqqF9@82vGa!NH|>qNM=4^l>~L zP$DKY4>Q0@w!gw<Xfmg|kb73yOS-9T{=4nHkSr@j;xQ05@i|yf-oc1mJ}KP*t?<>J z=E1)m{%}fkEI{0%gnlW9H3u`6!xN$J+a<L+FF=eUXU3~zAXrn7nKUzjF`t6qmNnVJ z&1f2yP2=gGFghV(#(u^Skvj~}ypwP51N(%60ob2x0uc6JhXJgh2M5OTGD9|J$vaoR zR6__i3-Tlr{zU<?6k%&5KR4q2oa*ucFurnAD*sUXcp&x*7IuNNMHOQ2x%lgE(p;gx z+pZZc2RB!KDS7r8^^|wua4$w#<1(3f7Zku795NF?T4A(p#}wI5WSj{B+U92m%L53q zsZ4XO1c8QKWm<zK15*WyafGaWSVxP`*tGb@6=qYdNI0oa3A%QBVU)quOz`5^F2a2Q z`B+<l#Es?O%!<U5#y{Klx+&<=3YaReyODKV_0YbP7opdA4y3r#JsG~46<=}$<4u1n z6B&#(E;pY=lWy3Md)HwUGK;rMnCx#UpG|!~oh}DG!}hUPF$aSVvJVFI@|5%Y1oJq= zCu_|nt>DSLoZ($1xm6mfwK>;K`+&hU&Gk}IsXZ(TtxanNsKnZDQu4xVD(a%2{7SYU z)pRMu>?x-?p$>Z|BbnRnhXm^w>mE#Uvz9Wg@?~ZcEm3?kdl&Bj?ChQIid!Rudk#)V zV~S5wjNh`$)X!fHQ%J9q>+gtj2?_-98WDX4*rznxwakL?=^kyi79II*)u2{op*>CL z&~d8MvX)jH=49@x-RIkk1ND8%h=SuPkF+$V#Ob0A1AG+i95wC^5B=UZm_47wyxYFY zEoK#q78VhMwO;G`1y($l5*_MZm$^|!OwDmKG@C*Hn)>2tM|tmG#jmV){zh==q3Zh0 zoH>l7I*V-OfcX6&ZF|ixPmBFBis5KhKg_A7?G<xLrajf3%OX&mj3F=?tP_XS_=h2- z>D#?phVJ_GJCFrU%8We)6Sav^5#`kL@XWh+NZgDFwW?DBvW~)cw5w6Cz?P8tvvnVQ z*d=qik)AJMf*#RAu@-}r9kJRh-}OPex*Mc^q{en%;eezPVBq{NAVuMgqA7`Q>%$b? z6xy#5X_1dPDHqsU6QZb>1D{<p<a+2U*3z=9Zske@-LkbUKh$ld+KQK<e=6R32^8m5 zM@5EFUXk;*n8YBc!u+L|dxERjdKgw_H3geFzNFiq#`tO%{etm3LM|>Hc{g`>FZc3n zMCA-bpX@N(uZB3zK4GdSZl!bPY<Jrr9@G;dB^GayCoy@xn^?shU4z$eat~Kxvvkqb z{odJMV+l-X&6bRdOHV_&t!^YZaIu8Yz=A!wUg8iNfb(b5F9Jbvo<rD;(fo={xob1m zQHjNSsw9lp(Y4v=!@SDpt-B8Lp*8a@J>NiBtqOsh@dsZH-_5(16N7W6pR$x2P=moJ ziew_0FNj$cmTb~7+hNnI-rX)oLWx6W@AlkUfxlB5rfXzk&(JDc-tc21j@bWjlw4jg z?)Ek>3Hxh(H2LQjy9w}4fRw3&n6}wy(-aZ2)Y3$rErsGqiKTjnAbbasybE2l^^<mb z8{Stzk{^RH|LR~&)qby`@52MSXiHlHDd$opp(MW4@qFmIxLE$aELb%2Z_of|F}KCY zPZA>&SowqevRZFM8=!w|1`NT3A%$;*+=Z|<scMqY>(`W$;70OR#`?JV5$te$t5il3 zT7Ouz&92<8G1vDeIgPq>!WqROvPEyPNuC!Ak#Q}OuhxTxeM~Aj7uTe|^dT`>pwshI zfvdJ$%}Opa09`<vCwf-*>k!!8tF0mOXC1XRvaeyE)RtKG*n|u8%Y&?val}d46)i<- zRx<eNBgvgk*vWl4YKLRWE>x7Ag<-AW(*aHJ(NY13#}4B{P4yOHdio<*Es!ZOosWI+ zw{V}#zk`D%d82QppUlI6l&k~9>r6FhlecLmFY89iMDCtZ%B{_m2Q>}r@FySWRfryN z-ymN#pg2;W{-F$%jX+Fe^i+V3AoOtmf*NEJXQl-^Rh73|ox)3x<GqTXPlWx<Kdjza zep=mR>>gpL8Nc0!sd{0nP}56FcpmN6StTQ5Mdq^KG2+P8X%dM=HAwJ<<vJy#T}Hm7 zbM_jz=$1tNRFM1d^!57dvHCbgYzLDPn1364*d`mq-5Jsv*gKLJ#)MR+RtCO5=Gm=~ z*}g4Pi6v*~v{s!WfP_Ba@UPC+ro{P2I#6XKzAAbr)KME#gf^6<U}dgAU#kk_Op!`~ znXLf8OkGtgRLR*Ffi+Gd%whX_0-;L^H{Jnm!BZK)e|q|5g37DMS~NG)sDnf29npNO z6d46BxO_X!_<ZfO9$Wg#k>CAZPoME$avs7e7HlHjTwt*1>ImB~X^M6kmiV+<BNMrf zX+hlUFotSe=X<5K$byW)FNz!raTvP8kkHL5-hI!g?dnuae>y|s()_GiJa?Fo)rKYM zCXB4tSWxW1w+w{!&)qLXJX7`rwj+GHHz*@+!<CETS4fQ2ShJQEeR&8r+9ZQUwQ1C4 z@`yU$Va7vp3#d^)Y-D?N(djY2h(y}e^*@%4eSQamQw)vyM%L_qSr(N5Ib9QZa3UNB zFv((3Nf$yJ-gGyqbq!pJ9I;Pyl1-CE5UCGjUBJ{ol12&}fxYAoG_(2V-M1Y{)$G|< z4_B82Nu;mq1QtypP~_G+oUecR;EE6igU4!%zfXT!Rq_dKis=HKXnQIpo78!}*Wi#( zNN@yRwgkGGrQ}~>oHz3+FQVHP^9Y%#zHFEa_UHHuR@6Sk^=-Fk8|-H?-Zfu$>rUTP z)OSm_{H=&uYQ>1+9e*<7bfE?ij}h}(r60_Ua%Q`lQ~9|v7mByjxT%G*vmA|VYP`U` zfz;cN4~tyvJ?^X<;B(}%U;k-qPpYtnhRm2f^OUp<^_@(`%5X%^YJWj3R(*;iHF&F8 zH0O=v(HN(D(mt{hw%=qHEj^zlGpG8lwsbqdosk9ltNGLBO~gLPI_EyE;M#e0D<R<; zpwXgI?EUqzt82w)8ssDh8d56Pft2|zZSXCBdeT`JrX*fpMXk&hB%+<My+nnxk!zw= z*vW?eFG%Y3g2+4V`S+&DI5)UCFc_Ul0^Os7e2t)oELR|kvR`eF8-QDzIir0v!3vmU zVjs6AUcTIk(zPqh3TdQ7p2Z*u!zko&E{U*WtrMAk3>{a-Jc|G<=rj)e6=3C68M=DW zshil!F;J14QL0Dldp!)ewu0vWY9O+@=f)Wdpuys$n*LC)J$vUxEo@@@&*Hm8Wx*Ay z9!h+0ZYwPyl0kl@)KSE-0(Z3g?~~*JU8RRNNpEeiZhn_l`XcBO?la!+HBhd|kd&)? zV@O`vq-K4_s4%1V5Qb+$nhx0!leKm-XOOJ-Zm-npsOqq`mLN1s7+mStW=YPTbQEZe z2drCtqLjZKE+6A_&Y=<ft)7=Cs4}5=A6(YK&3Wo!pmrJ^;{1}Rjk#8Aa&|H8-3i=o zu43D|!EZtFKVMgVd%?J3Jz2^=@xYGwZ2$YwfSd<<sofPMxjKB=az-xt<N->A7<_{W zWlwZe#<oghYY)xeE{^3eT>i@(gM6aE-a^02?mcrjm-xgH`IfJufZ_Botg>mD;?lpV z>9cq=RjzPQiTSrdm$W<xVjRFa&jHHvxS#}Xcqo>D0SxAl@B}#ZjeG~07BN-W=?Mns z_u)e~ohRGU?1)N(G8m&ZmIdbYQP%!*R&PzWWYuVfrXXnF;-U}Y#}wXMaF3b=sl%UO zXOyJHc5WT6530GF^7W$*Y3J#&Pq_R{jgEbrI3tiJaL_^<a^*zua}0vuwACyZ{_-p8 zY{JKHe%%b>KqihPQT3A{sOtBxfi@Iz<=3ha-l^uKtCb<4uzw!Cep)M>?nTHA`AN&( zYus+P-iJw*WqX~=az%r+DTWO!`T_GHgp(ATD!v0Gs~sIpk&5&Ombgi3%*W$iAp*?^ zl@t;K9^+JLa>vj4yl2mJWk&xj1C3C6e1p?dD-s{W$@sr|dS<`ny~#uE9zK%jm$>p? z*>I?nJFt!0E$Mb4dw84>t}K>3s2AOpJ~CptrAA^5vMUTg=?jvH7J#gFd)uDNMh20s z^@JCw2KS7}jW#Y_-Qv@RGqO~-ApRO)FZ%^fdl(tan4%f#)OATRBH$b|0@cfd5=ZD{ zs~WY5!kA{_9-!0=dNzj{-C-w73P{`2+X%2wZmrd!<2eUIs*WU2kxF<RH*QL&xX)o{ zeq^t62?<XO{}9hFglcS=`>-lBl>R$oLX069XHK0fhI=ukccjy8-SV>+<=kl&YQA|U zrB$=Gl|)NTG}!X?Z|PYuT;4TD*$G=0Zn6BDM)uuI0Gl)1DgwRBo@?Kp=MX`3ZIxnS z#FJ@cX(<;F&)mu95Qg{K<e>@YH&?nv;tKePu}#MJ_oHw@gTTCE4DhOe%cT2agIx?i zQ;xGsDx{H~bNNv0rw%=hWpFyU9^4pm;*-tFU{8Q*JIgwVwV$X0kK^S0k4Df~uL&9E z_g@FgBRe1A!)v#yL@-JhrnKfY(!0kX$V*V55lfTgbrf9d?2)<)Of|M=pf~AvR(^*x z-`{Z08KaZ1I|7u>s`RI1sic)CGuvFcKFzi6);@E#KJxx)=4gQ8<(`A5H~Y}+P9VB7 zs)-3IX*HY@wTA$D?!DHiO9ndn=V5fj6*TK~H!&~Z@AZQj!+1%}_}1Is`ymXr{fp{# z@UJ~PdH<Cu&dVPCs!%reEK#kjGOxt9v6r+pzB!aX93T$dK0ErP>skIWiW=-8g%td- zehWfOr^1IU%O>v=_8<<91?jg`gx!DrrFEAYydx8LRhdQZeDdJctTJHf8daVW-;S>t z$9bpD3Qn4#SDrL_U+M`Os)$qbYo!MIY>A%^lBDS>o<N4%A&<-8-pbUE1Uyo|@1@yp ze*0+Rwk-W67{+*t+nA@)l>4VnU8=vYliJX;qL$W@ihVa5_TU3vU+LqMhRK%j_-nS0 zyJ#nLHxwNB+rP{fEu*>&7Z*o}4okGmuT$)?qJ)4TRo-LpC5z?#)y;r6fKJ?Xwx{s$ zw-D*0_2N#sr+@6ajh<7D`>%+2*lBbhn|rLg?Ef>_e#7Bvo%0GsmBd2Eoua{+&lFlk z-hOFWgAJS9Y50y*-v@>YMu3Tx9D4B#Rb|p)o`JpS!ojOL4yGGpr%647CGt}~8ry$P z;7R-<3(FCN-Y<xA&;Hi}q7b4{Gl-J&1}6N15Dz+Xyu9;BTJc}BrBl6whDs3(Rl)0T zO0xB?w%Vu<`rD&fV7inW-(PesEz_3IGi+&Zp1(rPq+8Ikm4*LCck3OcxMC~_jMY)D zPEJ51mIsHYI_-GlH6Po@r~*%z7g`_MSlIXxD@*PV9mMO=@Grlln-ZB3w0LfI(N*Bl zE)vB{sGiQ2uX;D*9YGK&vh$c^(-+8Q6I-GKRdTweuN2UIs2A9GjG*`v#AAX3lR5c} zuA-Q66MApQ;Fn+e5?YTfo<=`&JiR=p-dcukSx-Tuf^HvT(A4ASiA}<XUq2(4o1tfs zAZB#OeV?&9uck7NneAKfsdQJC-?P9LU61NFT;kI6$xF+qx)q0K4P<h_(TyDC6+V`n zvItveB@f5#xpAp;Q@LZ?&99O{(wEG_OZhyts%XMxDhDRz?gL`NlRR58BH*RHk(T1W zF~+gPacEy%DO;hEc_-nw%9XWD8g^<3x~4%Mz`Vpa=;TT8WsuiT_dMzeB|yc;lSCcr zVj)XG*2NU9)fQUXr}uoop$&7Y>+fk)=UVrsE6f?7t{o&gfqUlQ>Uie*ta_?XUHp-& z*{0B3hmF1k+yAX)-?`Z*P{HIXd;SX<3ldnfDBrw}l1qY`QL#|(*gO1}peA<QyH2l! zRVDe!Kk2yN!qf0t+pl5#!#U{il%*|K;e0ly^=)a?fno1;05^d)IG!rN&cD<_qND`@ z-wKXzD`s3)Ybih3wQ%KqtYjzzcsH#aDRCF$r>~6NH92Z<!2+F>KqS|^s_=DIuMy{B z93I1!fVwS_(U=FhkXdn&(?l0}J19>m7Osq_SY5jb=yNYiqgSX`Xp^7E*dP5dqRWhY z5|)%X7}jHy+PfmZSj7-f>?2$+8aw`i7HXtz7T`R_!iv=#R*ynG_B7S8FmvenPySxK z5^9pr4u2n-mOT<WY!dEVhFwGS4?r?8u=))+ya9Wdpdn{!9GLUQJ1$X(kx74#sb6jF z4H)lj&uE@zbjSZya&)XOA4`y4cBZ`D`73O>w}u6lw$KB<tG06K81p1UjB$vKzkC-5 z8l1Tn96}60QC<u)h0BNL(9?~x_c~{0{Og=;pSu~Op3l&kho<2SZ6R<)bJ->Uj?J&s z5MzhvW9(w{BIlDYl%2DM{+P#o*n<b}VhD&v_7~32+|CM^wR+(HH2xTH^ktLs;MTls z-0nR`h~u<w0XvStKzjP~brMy?%ADLl+6lE^$$LE_hp=c*h)BS|X!*AxsnGqYfOr|I zw@%^lRy1PohP>x=JZy4v?Zu}cp=cqztEQpX<340T%x?5=arc%i$ub*D%*?;)k{_bt z;J@DbF+8TN7Vm~r-!QdGZk;lj6b^+el^n$rkI^N;&LjHYn5s-w<?FI}%LGPZY_Z1& zOFgIU1!EVlaqZvNDX(1LpDphM*|1?QU7GI>p+?3^t;jY{Gtj4AMlQ8+gQ9K78?01A zpgQ4trB7xyvHgEEjzcbB@idqHr&enlpK#4)B2S0hOqbU^-iV05_UqiJrzm9)ufcuG zYXVxc67+k2N5hmF42*MIam!Aqsa+wbB=@(BeYiGBr16tYu6_PhTM;8<p0KBcY}ovH z6G;~{c6qgr>PW3;gNtXyFZ!`OSK72FrhutOIuni)_rZamL2(bLv&@+KN0@l@^?pNi zJyT1;W{kxNwVZcCFTOGuvQ+<Pn;apzaVlhUO4y;JxkEoojvwMNyaSJ7N@~GSC_O5! zhyb+7c$}Bw)q96-WK3^IxehGKX(E`Iov3IK!c)09QwL%O&osq%1y-k}pN+&+ex<vG z&DC%+%0JgPlxv~gjk6}W${4PA<qa8F6R;93$uu<0g4;AB#635nv_DsNpC3tZUW6X* z8ev!vPU=WE^+Y&&cZKx;k2FMRuyd$%@?&+T4U`^Q!Sz*@Ef1+Cl4ulfP&!Ul>15MJ z-L8#Tat2eo9rsaMUo065i9rb=G@Ph`yc+*b7MQsB2fY@&^}_4SUFHQmas039rn^6K zWaUJnhR(`M6{bAS;ydJJ+t35WNsNAJh-sp@R6gGyOzgqJ5>9P0bn7B<$Bi-g!KUE! znTneQklt^~qY?WL+-#u-@=HboJF_FbrI{uDctTYeV7WI17qlZorQFh!SfG_EI}Qki zrh}p;D!6#;3}3|j#;6iH4-n@3r0r_5L~=;4O50fdoK_wCw)~%Nf{85>OK`fPS8@Y4 zhQpWp?e)d&5Tj}l9<e+|vWA<toC`6!P%`xlsc*4#{;|@?=kS5mQ}9PA3!<lubI<A@ zAElC+&m5`*InJ8}(X6}G!#U+X!6_e!6j9#<`7yrWok)LSIsJ6r%<?`l`P8e-B5PID z7qPbquJmV6(k<Sp6McjGZ|T23em9v?Z$ULB49#DkaHf30IlD5fh-8KQc_!Mk_3Jrj z-AEx^997rz70W~|HaM!90zpgZA%VBo|IuEA2Vw}M&OSqHHH_6;6}*!aLewSFsrUcZ zwMBI6Fs@)u7BN3SpHlymM^cR0gWM|>X&F)hNeRi)NfC`n7<?H<+}4;;Zg)Xko|<z~ zUN7jPDzA(!S(01B7pMUrnt7q5d(+ohnyIK_SQnG5xddC5lH@zUA+s)cK^Y>Yi~R%2 zcGb${!DP8<qaAI@9r|5m5s(~Y><zzG=m<FBYFp4nF}QN+*gHo$Dc3RFY3hpQ+q&Lg zUlvUzmz>xA2fU=9ssEM*Gn_(Q5k`3{&X^Q!L3y-Lgs`V&7@^O-?xYS})41tH+^K-x zpLP?NC#=`FO2$~a4|-zY&9CS<PwTtaHf@?UQdwgoHkr78*H@V|^TX?Xo1c&?_4&jH zrgHn0ACfp>qn<1*dx6`&x4)5Wr4>ZsHFv8Q3K!{a?DAdx?Z)_!7QA#<8{2N0QINsG zQ2oPh&@O?=R!ym#+JD+#_M$B00buU2B-8~qc!rBVH?akTs3U}F>d*a&{F5&sH@k?k z3{j)2XP`}%E{=^9QrQ!0(D;Xm9{Z2bDVvtwV%a5Wy5}71CXW&lW`{2AW8`)42W7D> zy%@^JKz7O4Lu7+j?TFZWZ-fPCJXiC&3=$Qdw<%a3?Qdfkf*z!ayEx{z@mGtm-yn5! z&^AK)4nMEMjok_Ubg)bRXrhs<6vyh>M$XOB6ug&2+Q?ww@HockV{5`6&`L@B8<$L6 zXtP&`h!NC0%#4$f4w1LOn*~X8MT#7ybLt@wu1YVd*h=)9*ji!5c(NGNZialvv>Ajq ziU^p7Wj%x_tPgwQ;1)K-gJj9VR^ji5rV;qI-KjC?eGA&*jSfSF!sq_5_tzRbazBBY z>>4#qK$owKXipfnvlJ^^3mNpd#GK|ZiXH0L=xMbm<wwqTxm6|@S~DC_NOe#}`yO1) zr<k?SsG%*&RQE1v1L+9@0WP$zb0VYVB=X|NwM1m>J~Ewl8+24GFq$FhZ8Hr$qMuGW zGNv-GZU5o|MG*tBk(NoeDoVAtU$R5z1{Ktv*@07T>}UsBg(YJUwN514Sg=a)dM1rt zTLluYVj~4;vbp=6@d2Z;rS@_G10yeOLdeaGX=OZQC;!+fj50!fX;gOdG700JpC~HB z5N*s<&0cFSiO>*(<*(b(dbFcBmt+<LZBkOt=rE0&D;UXbmU}tyzHF`LL<s%iHz^N@ zZrFm#_}3qF8y9a<n%W+jY^Yz-ySf!d@vTt2QBeKC?f~`La}icXIsg9yK0v|0h}}y2 z<u10Vo}QY0Id_N(k$IOZj2xVT=yP<&*n(_UZ=fIE0<%Ou7g4aKW`tz1C&LH%LK_&B ztpSvE`%ZNIrcD$ci~abaObkp$MPb|TG4I8kZp%kBU4J%-yIvxv)S0Lg`CXVr9(K$i z++TpbX+!eis=Yytzx?_c;OSqp2+NU}_><8%XT}93x)Bzef@$RmAb#t1=sI#Pe&o8F zuS!ZJ<!_ldH08PZBdDhRVP(37E)~8<R4%Ma3%nddk3Zo%CNaN^37yW@$XoI9obAZ# zG!Jl|U@=)}f{N9Rosm4{TSuv+W2N9|7V`>0uYS0`gxBMy?jKL%(gx5uvBH1|FrKDE z0YlNE-QB}I6jMmyN!Tfsb47&$bqk@lC^K+J@8PK(TSQT>d_F;Rx?X@%%G5<RN~YM4 zNV~&lpUC@D%jfVi8^vFPiRm{O(&(d`1FuHM6I~1HcdQ>6%t>52z=wDX_2;+_YD^f$ zcQ|!QTs1U;f}otCDRwm2?aSg04!Sbs(+sNAfMgQfWRsf$Zx!Y%U$<=1FAnGjKGTQU z$X=Arm=`jZ5*S{0KbjJ92E8v{rYH{~-s5k&+XOv*kAA#Ah>{n8)&~y}5D#;a#2ft- zsb=qup3vUYY}Wf)B&HdR7!q8iQ8%nwMvNo5o$&=MVYLYvQP{AcK={kY8t(LmHy{?> zZQ#wt%hNWR+?Pqrb7OuN$gc?5&SiZ<g<D6E5PevC3wOJWILl*eXxU1wGklFukS&vK zh-^^+Q_(WgncyV<%6W2Y_SH<ph;@8#oT16t9lQ7F2SI_+lzxqgA6Sk*CBbGUPO*sH zky(~De(1x3N~bf22pf{3@xw{M0RQ}hfxU}iu>HV8Tw1h>qC~vH#J~S*Y&3V;_wlIW z3%8p(<F_tUR~F4R@~VD(!vvA$jh_7$(PwyM;i3Ez28%a*4-x(t+@@8N9OQeyoAO$d zoIznddZftqi%OmT)q_moIVr_nLd^?n7*o^_iJlAb@2EaMEy-$heh!nz(e|uk)a5C< zNM&2V<ckWiJ*$}1-Ri$X^0#MFOsjR*6w+scSweMDEbC#uZ{85yAXK0V7kmE55||vA z-II|GU52^b!e36rKvG-}ag5_3w0Q&1Se>_jofT^({!aU1q*%MEgsk0%R;6{Vq*<AB zz!Ltw?^3XrL)>1qY(!vY7ld@;)h9{cL|Gj($qpi<tTEoo)5Vjx3ZfWKk^0j$37F&Y z@s|5y^2^PGJ)Gy#GR<^-a2{O=qk#3u@ANoXZL#PL?%oe*^=`GFIH)Tdyt%3ppdt!s zcsr-zORdr47Fm#ChpXilo%LKr&U-z((dG&0bIcnNWg;a{{dqY9Dr_m{MB*OYXOhkD zN^E+(T<~r^7EtH45Cek7rMv*l3kuwEmlY%Gr!T9zSwvuBl5#87`l_Vra{MO?d7Jfb z^CVlTNhju)Uhk`&)a=fky!Zzyv5^<r)T9>+)jvD%lr1Dqfs2Obfw61B1)u6%W8!eM ze_u&<F-~G3pSk2BMwcEUX`gU5|6z%YlWI|A3Om2P46xzB8h)wEA!^5HNS<eR%JVVk z4KfaOdM&(!CVP6oF?!!?D$Fw<<)^0b>jTj@!7jMOsk<zkzWyR-(gDAz{CZCM`lShH z1vy38WzPYqVZAdEbHJPdpPXX$lxU`s-<+ZS8TBZyR3arrdj-R(Vy!qBbrKYj@}(@- zw#`avQ5$6{9~DEvK`w7s06Lx<0Ob@J#m{MaBkD#u@)u*^MTZI5wy4n0m1Xj-8n$VQ zG<*-c1(jN+EL`<3Q3j;r+SDFarN)qqHd-Tnyx!1fUn6Hs0Nb4b7h}aPG>D3D^dubQ zETkC)CnLpH?tJR1bQ+~hzZ_1HOKCf2o{Zlq>mgwY`$yiCCfIvmhNFYA>>bcDt1cXJ z&$z*xxavaslxr+-Qj7u@By?SWFg$fNvIIN4v}M1AR>3m5lSK{OI&#rjgqEe(jnpj^ zs&<paj!Y%q`lM!e`6O#*M#lEro@KLl%gf2$Y1Xlv+VXK4w&|u=3bZhOv<TVVKGKSp z8aqv<;cv8jXB5)+1=&85)wp#G=KcZqt7fh3Ppqns-B@E1eQ4bhSVS&#B<*Mcm4s!{ z4g+FITTrslcodhyYW@ZDAp`F45u|KK={I9B`}cA=skjfJpFaq4ST*&MY?9m@W^$#h z#4e*PdP0ZR*lZkJXqRlw8C+9#*-suVV|V?mk#;&1xbg10x*Cr$RE@kJ39l6T<*|}; zqZIrMr$dSNz_)X8W`UEm?Izxo3s$NS{H#eTfTh&aU8a^6QF6C;na!BPb`2Lf(uf<m zQ5WE&gXVd8&yyO-+>{rXBRRJ{eZMZgvm}I4a9W7lekDRT-Bj+_4KcM%4Y=AboN_#i z`iSOD9FAFCSE0LA=PeZvhlzUbd22HcC2KA~rxRqHrJ+RyH{tz5b~nAn8rOXK<&I*l zA|%Dx(d9)sXwUy80Q}%7rv9=q4IBGn(Q|>=)j}Arz7|lAcs~ioX9HgW|0Z)Faty=U z)qFw9taYe+&?lLDs1<J`Vd9sr5f#@njun#UXPJ@2IScVZ0Oy>uwFUpH>zQ68ea{Ji zj`Xe^(a`);V@h&1G@~==%MJSGgU`?AM8zqMWysvzFKQ6^c*z4gl?kw)DR-{AT0Y5h zMN}k+_KHXQPTpqC7r)ASsHM)rIgaey8ww28TpX6_1LG3TDedt3h;DI`PB#21v(O1U z41A{)E`KzI6MoY_>fS8)1h+4YS{%_#Avok&EyBRQmoaV}9ak#6LpV~d;3u~`Hj#|A zW0*8-|4rfl_!dXCibyg;tZ9Z>L2_+O)ynV0fwe05VFsQVj2GtI4f3;GMMUX17H~|a z@+C9)mtgPHB)!4TCrShPp|^sgKqxt0ea+*-qmW)LbtfJf^*(D{ujh4o+~#uW7B4m! zs2sbz3d|P~laR(+ChER$t4X4DhxWFUDA^X4yUd{@MDCy0-pcoL(F?ch)DN;qVK}vR z@f0cZ{tu)SjBx}37O1ZtU+T^y79`^th?8N*)VaY?uaHleC;OPf8(1DlzX!mGzyFd9 z!5*&Whoz*J_$Y$A>$bCf+X6<La6cX-et5f=N${gp`S2Jh_Y;NBT7XHrHYH*D+*8jU zzbQ8L{nBD0<$P^<C!sIgi7U8eAa;GREJi|izE<F;&zeZf8?=%#uq*saY1j@f>H12x zGkZhj_I+6!z?Lb6w6a?bb8Y`0117swr(g7|38C8bkHq>g$0&U9e0(*o2{pvIs2e*j z1e}PjG6y~%lX*t<osc3%{`9<I>~@n`$t+ST_3-TYqzUE%usEmcMN@ueHwqqjNpmr) zla+6StoMr^?<%k{uD+_lv*9L#%Al<y@fvzI8e|}9ZQo>QA*GFUikSLHozM^}HpXsD zM%-U$yTBaE1R%)Giny%fP8!y~k!AXLIo8g>;8|hnI*VH-j}*$@Q;ClAsqf|Mi-PEg z8`!=FSH7*ETXP0UUL;&yTu2Cs{?*{dV#27S;=A%z%(Jjhb^hfBr&4-5N)fl6Arob} zmx9?vuYBSkj$XZGTg1qSUlp`wbQP3{d`XJ~bw{af182n`Id^0~RStKexb1w!BD3&D zsT?n9lvmRa@BBU!?k0BgDxs1tBjQ_f!!cWvdWID@YHkxF@GUfKNZ0`1bbaUa$f@+D zx3dj*otWhV`-h))?~T+-Ge*>qFn_El5vP=Rj=q$CRSw_Cwy~Q}=PXliU;gk_TJzkx zncdt>#B}0ZmSADXLbt6MyRG8h2qPru=lTSB2t9<o_OH$2C%ss>Rx|W(lE<YjLQ^fA z0jt{|cK6rOvKurD@GeU5r*7sggpQ6KvG=a7qeY9p*P^|+2Y0TKsW!!Jo_{lSW63o7 zn5VBj(c96_;J~+-VlFm@)yb%(Gs4qhWmJ6}1H>w2$;4BCnQAgH-$5~+XmC4(BJQGr zY4tYkP7o9c?p>&uE0g_+y0Mo>>HaN#tnBHr2A*oj6MNK|g=+r&l*Xpc>;VDyw?-94 zsULFaRi72f2_?v7*=Gz<8X+OUuF=6uuM2}Jw}$VyPZMn>_pm;Pzy2Rz1?qUEFsPK~ zwE^*<nybs+V70flT9?}tf8JA_n9tj&wVNW-Ve=8FjRINu8p!h5sw?4XTw~I@d`uO+ zSiPY#Q|Z4N&!al`-7`3j?3n@sqU2_I+cewpXSJwhm($q=?tq)}`-U!;x7@^`yAkW9 z$ncF=A=yRCc0Jxw3dH8y5TI96avMXLx4id!yhu)AZAuQvUbU;%^o_1ubb@mCbp1JB zZ67T$MAR2^>hr=PBYG|mny?|^rWG62a<ybMuF;fdX_4?;euX2+*O<|m4()~6KpdQO zzC2e{K#S{q2O6tH`7XpGTctjx^=@#jGY!b>VXOb*$kXQas$GddW;^dPTzW>D#K9LQ zc7pOP3zupuUpU{g;9jArv?;IyT3Y$IvBNm4$<euVs3`j`R|kxaZwwSR!Rrw^Tv!k& zmioE~oz}!Xm~2lp!4A_?7l^(?Dh@YAs9v26lb3OVT94E`N1JhcD`0#<Ns{hVX53F+ zz{@RxSi&vU8iz7qPD}_Jo=aE?k9<ZCs+*2Z8JB#1V>C^XG@;>r><*X3*dL-p`GGAY z8*4Z~k#1ym*JfA>iNSnTZ*7dO<Zwlk#OC<ro#d$lMliB08Jx!)Ne(OeYe+IX2bwE| z%?Dq7RSUyj9B=E6^&<o$`v`5D<nw#@C-CNDOUNaQ$s8;}m~YQ8+*?{u@Gp@9_E(dD z7{AglsB}pt?}yc)l?V*K0}=)KB_l9(xWi8}VPg>j;%D+yx_Ud&OS8`NBR?u$tj=A0 z)GF@)2TYhWnqU_L{Ld0nXZ!`NBh46q<F&~Jt%&Rx2;KK^G^<@|@sF8mWZx*6Ah(wc z+xfRj=8o>lUpDt+?GFbpXBU~d8n$Z+)?oH-ls2GI_HBlt{*TuJ9|+Np9a}GigcmH0 zoOhAAvKVJut%3+n2D&1eocNvSIk1=6R*}3m5|L9<J-O9~Rn08Io79_24gwy8(L4Fa zSHW8;M>ybu`p8p+bn=y{pOG45n`8q^mfle&X^~Ya{R%2ht%qS*<x+$+DS}q6sHQc* zhi=DmK1l<RH!LZf!}c!MPa#5#ByQ~~?=6n7hfzJGxU5&-FV1sp%NtQGrB=b`@&!#I zt)fLb2t6>maY=OaQSt5Tef=2u#nPlrB|Fe8#;!y8f-oZCMnvbLM|)h-n}E}YhF^kw zFy(P>aQ8U2PkE!RWuAA+`*}_4phF&yLo&_rrmV~;_jbe%6IM!I3)03}{6fp=0uoEG zNAbO(`jS?hH+pDpoqoL1inOix=^dn|#E}Pn3e}^3P($ew^5=`git2zPVm>zWk5Nzc zSV@9$w9mRE6|~dTh(5fV_W?fh&*zw54;6S9%OjVqU*3nRm0OoG|Dc|%5I+ywcq55> zRe?T_qRso{MM3-?JKL;l^;?r!`8&rkU4o00NyxqAC3lDkh7zHQ_oPW7)G9?66A0Sy zRWZ*(ZJ9`t4Utq00&|Mog)h*7s?|UIN4kdDs*OcnvVxQgM7E}`!-0-GYiKDC!tEya zz_UWt_PY@ryR2v<KjiRN4BI?AWG~{T{AY~!zKHt0KSu1zI=teEdyFk9Y65HW<ykEE z^dp_8eeJO3zvPo)E7Hij^Oakh_bR}c9j-5t4+Pm|pg~}m9gAjtCl2KlDtT7@7(m4w zQ*6cwl`v|-*<EteEL}!l)xFvC>vBe{MPM9yrlAA+t1I-eVzmGnm;p^SNkt1KH9+j= zN&H}1gWFTek{SEM^WA28QZIh}k>BL84u#WHV^i1tQA%L2pH{{&osjfO@!`T;AgtbU zTo1?X^yj9nrNW{^la^XaX60a`ilNzA4g#Z*7zAvl%DiAoFkw-LR|e{?_{#cuaQrWv z0aG*JlZ&yZA<@-?MZ2lmM(-neDbGrc1`XYiyygl9W8bFobS~9Pt#2{Jr6wMnRJOG) z$?SEC?ezIbiB{_7A>1LP+o^&`IhQte$SmA|VI<b-%kHUQP^t^A)g6OkV8^h|TmxJT zg@s7&VG$ot$<!d6b{{U}kLB=XS1~C3=culc`Yb;Ae9tW3dZR;;L=;Cakr^IZ;J_M6 z6XKJYNGIHQNv5N;Nu_68WB;N~S0afo;~;F%qvQ3?fw#CjrHT)`%!^f=C9yT_s6_&u zdwU{x^&xL5;XLx)TsGtenFtLGPDbSU+j-ESqVrn5xu0Se4uEg3A~0a(2smSh|I<Ps zZtXZxhmTSBrmk$N1iIjbW_NK?g>KWk60ulp-x`7bmp&BkBxVV&9Bkx8&CVAi)t`u7 zKQYv_zOn2|dTS8#Ix9p_hsLXm15<I-o#jf%q!^GrD{wi0!m!D`c@nv%q;Clw%7r~| zRZ|T6=!4x3^i`0Iv>3lM6DfOV=Hj}U=0y9FT_kaQIlPU?CODrsidUJmA2FnJ6_F#d zCZ2h}E#h+b_u?kA<kiC9u!z}CG)q<%5Scb*mE1l*_5SNsNA_^NY-VOdH=hIS`gU$^ zNkV5t1kYEh(d$70muQ5SG*ASJr#k_135DdgNTZIB!PjTFxe$DCR=*T}F*H!BFx`i; ziJ_KN=tM}tp8e1k28-Twl!^37UyB5auSAH({mw(_<gmF=MTOy$2jopKE0<cTE^2Ro z`ko_?i%WGW9WrA&E?^1;X7D`w;y^Ppy1MRd-XR-%TGFPC7faad{nO*hosr5=Tc!hP zu{m;fsY=^?CmM`wmZ;uR#Y;vNe9VmwNxWF^`uCL{YPD+i=6H9uW<itptt*W>&(<v# zF4th9>-EN6c0HtFC0hJtM82^#kYiN47IKw2QZwgFXXX+L=H|`^Hu&T}PWf*js0ION zi4<7`{lwmeBq}Se4&Phvx?q8kJ+Cj@$_{29uMMq_=k_dmL#p9CemQJu3b!eUgvWWd zdiRTKJIZ7k*pJZ2muo(-wKEvu8oWhkK(rxMy{fWKfvI~$lk`eN6eP6Z7l&u$y{4*n z+fbgr4l7W!P~Hyoe}(=5Jj$_4ccG;=IcM1(fa~bf*V(P8dL=tR$Yl)T?Gd4XYF?v0 zPRVMVyq7*i$+QY)_RM%w>`9V;Eu;tPA1J|ET^}Tv1U$}0XeBBpfPWIUIb;8{qjMNQ zkvF!_d()p!qwK>(F=C@2vUMbbB;8eg3%qO<h{PgG6>)@*%-%km=^!Rm_z2E_dYJwG z$VSOiK=#n=A>D`AjP5E7KbMe*-B^}=n%^n&nxZc;>vZZ?9GbK(s&B$D@Ygqbzn}19 z4bJm4uO%;Ax<t9afcSm(<@FU?RlUzC>Q-b4O6B6Jv01`}zCt!u7v09$VhC;%F{xpq zcx7<nUW_D595v(v{SQq)=7Hv&J@jjFSwpvx<y`rbPa83Pl00j}DQ4D!00|3@F&W}s zv}de}mIG>Ky_Dv0!RoY))>-K4*?U=yu_9te_g03`)vREB-?j%+ZM2Kyc?xH`#hHK= z6V;~ssb@X{B3<PDb!w!lcQco-gp==rV~KM$Obp_6y}3~Q>~>te=L^ooiEz+fpV?r+ z7(A(e4BLt;=C$~JO5WWpXPS1}2L|1pfr%hr#94ESer7ENe*5A6IbpsFng*7^rzDAA zQeYMmF+}rjFzYrnP4O$DI}9EiYE1<<&CQIBe&UI#9BTL8zyl`7!URu-XShTWH*T|e z5)C~0)PzbIVbPtyS~ali!t1#7c))Y7{bZH8lT)e^Ciyg3*5nXk04oEIpUM;=^%QZF z?(xm#$Gp#M`^-U9QObTkYO@zJZ7K;QN*R`=5r9XLzJKxCoX#)&cq!b&OOmPQhX2RL zIW^Y;ATYS?scqY~ZQHhOo3}P^ZQJdwZQHiZ-IsmaACbv?nIx7aR4KufmM0>u1Ty6D z51zGSsm)ffF826s1>9$9XTty?>;Py^1L;PZXh>M*Mr|2Np|rUY3}%pI7InhjKM^_S zA%0HK>i1iezB}BCiD*bp37hKAa{Zq3ib{%mRsmXc_)@)nIW2+`=(iCf5#6M_*>rPx zKaDZ^Nrpd$o!?i}X<i07Gk#LmAS6e(({1k80yGBn?|^0nv`z^QOt%4i1B>2H|5^H> zD&i?yZy<5&@}fUBCH>G6Ls^BQ{q@#Id!W!p@&1huPDP_JtZ>BkI}R@K!yXvGs>&Z& z(jpG5^jCGpa11V$+liU{j=qdrFmTGSv$_+6RAzluu_ws9RQQ7&(?`1iM11OZ1vZ(< zYnV89!<VIXMyWE7;8)f@RQi8}APGh)MyC>6DvFwUGm!5v;iLpUWif?+zvbGO%swfv z;taXfCbzKCTp1{GYFpo0fgB6Np#@A+_j3;A&r>5L;%=0Z3}TtnaNzk^HSn}}!Frj* zyo<g2e2ghxgg%{8pxg}=p@17TkzWf{AXE&LI^R2$0>>G^1!t_I9&7y@f(DNI5yJ;6 z3!k~#&vd+35U@44QdI|h*XF-X6^K{D!2+XItj9ZN_}FMca5N$2FtdWVld_SDkx=!y zn}RkrD6srS7GOPkLpZfsPO_AKRjJ$;uk+ltc=xhRok3HL1*4EIRTz0;=!F~F>*YD| zE{FNH%Pq+!0|)@{bWz2>DqB)>&s>-sMa4ml=_#06QjY+Aak6lWmT=|(nU;$7y&*RS zLr7N#7xShtU8%{Cv>Sg31F8}Y9&`g1`tuxiui1xk0biiGinnsNw%GFlCERH_YuT63 z8v*uYM0P3^1ChR9p)WhTf6JJV&ct{d*=S+v^im^kI2GMvaA0JOCut5LK1~TmrF_Jw zkkMHd_&~6J{l!20P4$m5yE`7PYLrJ<IpN|k*_JNT{LyP1u-Emg{|x%$I-+2%^mK0L zOr#YT0Ea{E-!b+02bQ<<I*vOimJ1KyCf&rfT_MRsokC&mDh`MjsG`FnO;dZKtLC4W z^%*WpE5nNDSR`Vh`hHd+=o~hwi`+{S25wkM5*PN87jrV{wHV)bF=`heag|}Aa~|2| zJKtEb&6E)?K-cwt;r-}GAwbhs<WVT{J}@)sFBOxKlBHUHI&B_B;H=rhfD;3=3m}4w zgWMIttj&$2hV!Y;9jVT~Jw=!BD8_1Cigu7wB+`5{>(s>uTUGu}=~@1ZdPjSTLX-(^ zMWUsIrcrQ);Ii3jrJP3X?za||P;~eVMwI6-%-7DAF@k$f(aC6(u=Z-}oXWK~${BA5 zJKC!eb1gULtp#Em4gj~Nh@cJpT34AaU$WXIYGd!YK_N473NnQbsI%g7gu<rjZA0G> zcLW}h$b1hE9-AAdj9%x*PKO?81V%SL@;PGlFD2n;q8QcJ_m6uG^!F*iA?*3I7#|d9 zux`{|83<7+dsFXzFqAzcGIkFF?{?oJOt1k_X;qvCLW%{XM2hAjsJ%Z6twIoFruGda zyiCNd>dE8I2}M4j-?ew+T3ZvwxqH)UHDp$#?%c{f!2kolDrdeP?ps%Mau&T{FlZ6| z8;3(x<exCOqIp^cU_uh|Bha0v>}l>g(xjRu1zIRb&Lh@~ym*kU<8m8qsvmAZdFqp$ zLT)7YVFmV=(nX!mAk?|*X3U5{IH1Aix9id+44x>neI9rmpq`T`ShK(yQ_k5`Fkx9p ztF6R32@*WdPxN5dd7uWjRGqJM0S&~6=<d#=!kO!x9CUP$KU0LbZbN&G?2WG%Pg4A+ z<-f=@s?GHyW=g4}9~={B1gsQ(e^Ohu7sri*b{QTgwl2D{Y&wbnwP^wj!@=id;Nq-D z?^Qn+2%_h}LW>T>$Ze<9@%n;8df5gc0b&dIXXbm-S7yJeUM1jF{azI-dNsQcON-IA zSGLhw9;?e1I}{SZY-1Ry{9B5YFd`XgxFdwK0(=S){(D%Urjd_Gezf4RPf67+ZhA~? zwo@Fc1DR~mmZ#TRj2KIA3sC;Hq8*UL`o{Q1>ut~q^pjF{UtsrRLh`^4IP&LaqHtrU z8$IBdQlGjeI}^A7J6*+Dg##<F<RFY>FaKOQk=KDoH&yQLD9q5GsY;xPwj+_GB$w-n zBiGF<p0Mx*qOxR$IC=@23*Bwn3QhDahh^%6ZHquU*@tiM|Df509HLW#wh+;4kvjqY zKkKmLTx~NXkETV<Dr6rUTO*c&=%LS;H(cPM$22e=^SGif@`g~!XqQ8>)W-J{jd)l6 zQzI3Bj8O1FB^MIF`^fi6JmHU~Bd&Fq{e`Xu1X(CF<ScM)e8a^~P9Jrb1gk#WAIo{( zy%J|<x5=Xyc-96W#@A7&4ZeIS7CE=syorL4DH<_!Rx-&df^@l^EvF@U6D}wc5jge6 zrYjneooEr06Qzr>sh?a#Ay@DyULUt3xpA4)re#0|h1V*V&;44&ER#K%%R12d8tf%x z3UCB2`RMkSo^H>@fm8%`KcRMCJ!QqmTG#S=V=v|v&l>@)1R4tD!5f^Jp2$LRxTi!i zcFhzH%sKY9RAulXV@%8Mo@RUhz1<mywlRtgh<C>(_pXDXwM5_;{H()T=wPS28D4kS zA)jNz-IAJ0j3bPGL}gh?hgxMy7jx$nm{#>!heZ;5@{NQXVYF}uA>qX=|M5~aBI8e! zjM(`J6N(Jgtk#%98=FL|5=+Oakvv(O-aokL=4e4|NW%@kENo#<YNg}4%t~&U6W(3e z^<q`qWHKr|q&Wsz;y@K=`Js8{(^T&Q&Q_hr0}1`(5aCaZfIPTN#txY6LNK2np%~LW ze~@EU9&=WgnfIbJLRS=51#{LLMa6Knt$iXi2)kIv_B#zAsY7IO2MY|iM_O)HTdF29 zjy?UZY!nRI2$ElBSV-(2&kDD37~|2-N+3|b-TfrZx~5>OW8>4uE<%`i{HxWAU8UCp zXo|=w>2^l<3MF0;joQ@_Fw=e^>PV_Ikl(LiaGLt9Hr!2Lho<t{Tp;FzFZICn<US*& zUkIJK^-aTpn%PlaU`Es~98!15kMK2mVRP<{kI<n#u%-`ugIfmE#kb8R;=JY8C<jc8 zYG-Zvk8t$kF1*FgR<x~strbEttVtOU2bv$*OZ&ksLWwgT+sinOQ1=hpy{?e>zLq4@ z3~~mc5JZ*S;@MfPggH3F&yJ24dT#zyEVl3dzyv25!^0`176l4tF4%qA#JFG~HGRp! z@n6u${E?^)oAq-v92rL`(_<@rd8NPcnKM>Kr**OSNI?817xJ;8oERJ5_BkP3!q3JW zEM^^@Y8T*%G%Lk2dsgoWno7jef?`jlBqQ9B1}FBYrdV2L1|&Lj>I+~;gS)h81ZpQz zAunl4YKpWqrlUR0ZqatF)wgtru2m2xd(|c%-oc`I?1nr;gjBhf{csY$<G0&_-v^49 z$*%OpcKXsu^^m**cwq`|9Q2_b;5Vp_u{7q-rTUzXk=B=R)GL1`A;~hRhFG*OU{T+C zev6(}r^QJt%KRZWl^y4j*=hUOt+aV?WaY>cy;VQI8<Ry>_UFv-NfpT;rRkC*kCU!I z54K#oq9QAuRNs8~bZ5P_K?bbzT&w!<G_9lEpvvlgoP`e)mNIkhZPG3}5;Nrt!-~A# zCbQ>coRYGAf`#rkUO0kJ`v7vPoK#HMNYAt0=$)9mEFQJm;5;48q<@(HDEZe@W_bi7 zV0T0HDMNH2HBwj)KCl{9cn{fQQ2r_r5(zi}3nNQdvBl_G)F*qK7hI_2y>QZ3?hg;l zm3j2VGO;l~XU4R{vI1dB7MR2jJRn9nl5hvlIyTdovbW*ixel`>FA3{z*&+|ZM6>?= zjK5(RLwrX~NZpaL%RIUKU*Ho-9B(0Bu<|%D%0tD%YnDf$W>i|Y5o4O=#qotc^pdvM zriCu38!C77E<98&eqf)07>Y_nG4qec6%U<@&j68-0$*9a6)MZQ$W|OL6mAR_OuIq_ zEaQ+~W>@V+syXzuC|hTey>(#u$f_`mhDo^!Vht!_eZNjJosT}+PaWXicXpmfO~1c# zPYsfZYwS!?qhm13O@v5Pu(4z;r(hP^!DWotUy{vlMG3`2s6c+-2HD??29}Np4SCxN zOVHQMDV0*6>l(IBXo43tKNim5f>JnfM-DWb1Jw3e+^<}}2|mfjEMJ4#K5Nut-j(eD zBMPJ{G{j0}xATJEfsG67r_6Y|c2f8N2b1qz@siJJo|1*07$^yn7YTez#}wO}Ju^`v zIV&P@P;kgH|9QEp+AwFR={mG*^MifLQnbgn2)?Gq>=OSLYCpRol?3j-J4g~c(d$gy z##p&a!UBd8ulKML=1`!`epAw>AbXCEL{VTL^1V==S`VwEE^IvWR<nz7hYUOZEJTwv z6u-<9QymlW*$=KHj3h{ujhDhVkvkH89fI{iRRp*ZXBMnZJRRFw#AysrT&)jlfMM0L zbXCcD<B)p<Svy;vS(3zMuT!!{IUb<t*)OYrI<t7ZLJVKGtuVkAwkQ0@d{c^p&Ng@w zq-MkI(~6{A_b{R9MD1iXX+Y~jmu8}#rmYWj=?uYeo1(?0FYOs+bjo^C42C(Q3Kmk+ z2?j-d{@{$AI@NT`XX*@L*!2rlppD~`3i}!evVsL0;R_6MAJ|9WA;5TAUm6?eV}+=* z9)p8B&CbB2XOsMgW7lmpu`0fhAx?u;?_SgekN7d%Y=rJ@qh!>4JK&qae#T^-;^*US zDm@ZOIHu#9ggO@ZMaEvYA@;i?>3EbAncn}a_|wcRY5UXHVIh|U#>%DtfZ%BK#_;dk z7ctu|E2TBQ)LR45X9AOkjHq3u@HZ=ptsq9zN9=tTw+P8LBas}=LhPSzkQ_kwm2&fh z;giCAyPt+IWH+etXXX$VjBxtycyr+_R&llc9DTuAEJMI<9(i>Vr4A1!ZXM{^CM}l7 z4vyl8gv9=MUTa4b;V|R)KhPm1`Z6Se-B66nWc(qJ2?SEbDa_^tO6L#u(G9nhl-f3R zw9)bxxsuF(u5gi0#l1-O7=xh+ePfw3uxlNy69ZOn1FI%9++^AlZwjKqEi|!~bTu~5 zwS!L2lQva_jDkDB1g2RAcRGEK$+~o$A;!4=YfS#xdJ1YBMY(SJfsV@-*|Yrl0@<X+ zVvGVAQ3VTV3{4jHZx#x+yT}XQM;$?z8QArgMDRk>swdvDK8~H;2HyrEaAgPNDR{gx zw&XD@`~5M4mcs^fy<N`DIi*k8&VqLcY7SWwYj2W3j+r%U9=2#L?jkLn&1vyFb){OT zUbVwa&3l?m|NJ+Wfm&z(H8)7r;S?se9=%2haI}=*mQ=cdX$IMP1v(8!Al_>RKoZ8- z@o8W>!WMieSsux?igT1*N1;GtZEL)h+*kazVHZ{R70M^oD?FaOsM0E24fYb^N2)15 z_dF(K;LpD|#Nntk$SHNC05v;4f#qZ}AxY>v`UvJHh`wR7_k_f3ZiYXzzD=_Y%*eVF zH>zPG?9%uPK{Yn8*MKB7_DC~p?t8Y@a+Ew{ad|QTZRcQ9W8o^F`B%piXcv6K$a-;U zcbb6B2a9UC_%Tn~a;61T<Kpmod!hmJ8Alo>rsciA#VGYY;}kfigU{m{Eb!Z<s7$2K zpB)$SoKZrh{rZdvTpvI7Sksl9NF_)Z43SWCu01C31&tR`CFiv8_4ssbu}@z3(l4iw zgz=dx&K)(6Gx|R&K%YgdOSglc+sm9ChfpA&b9~(#M;xn{_&Q4HAR3`rg2(2EU%w|M zn7=oW81#R{q_Y9bd)9Ab=MRE-p0x1S$S=_QYF<U_=R%Qy)|dC*_?liTHFoT|RT)uc zK1O9`Z(o`70Pnd5^Ia6roAgc;rLhe_eSh+omQx(7b%8NrFZgHCOjSkZFdAtmq$$Zy z`Htuj6{mDZx)V#36;%~mesI+%LP%Yvua$^lAa&mZf;jO6w!3(nnB`A)seEvT9q{l6 zlph?x<PwPr&ef7!^*afZQO%`b{`p;!YPGV;-i=H_(ppzajaaJP`5xPMMIeAYMMG4& zXi1@3k7V(LsYM*CCQJ_$DXAvw#v8NBb6~#>E*C;Lw!2jF_&>o{v+5{kNdq-G1!Xd? zfF0Gc&jI7AoHp^nM>;tS^2u#ZNUR5P71i8C7T<IdM_-g>IMX4=wor!Cw!1QWf%`=t zstT&ce@38t(3Uc@c*T*$6fvbV8kduwSEpoNSD#;?Bw9XS%w{!!+h`sQ5;v<%D_KMw zqYG2tnUb<#>`Ak8oKN3E^;^?AaS77+ue(w*D%7IoQoA+V^6otdR<T&Dj+KcM0sGIh zs=ag;ab92ZvRp|0?p_-Vf~dG|fP0pbJ#tGxA=81wx|E4!)wHzWgG2kW+TN4#k?3AJ zlvfzo8Bu6dUGJS1Y;i?Ag6x_Vag@Rm_|m&_sTTN=_if`DeqangL}^4^y*!^<qp%yb zZX}8<iQBbcT)UDA9OK*6MB)rgRo{*8cPp}F<=w$XbLI>Tm$<FLtDg&`{d)a9Gzli2 z8qNycK3@LK)VoxJ$yZq+_4CGiVAp9R>9lT^<vUL!-Na#+H+Ai#;4-gUV0o;*=5!^J zH*_o2Y?`uwGpyfjYzp|j;ko4(uS^Zl!}?RS_99!MPYWsFD3w#uwTA}?o2nFahoV8x zFjB>hfNKQb2B9i!3Qz`SA39tZzt}trtCq31q!;J6awInYoCU4Uf~_)zu<y7T$Y4$O zp#X?#iQM$g>sLQrUqaH<2X9m*XcRGb^&w+yYwG6J_}F@%gTlQBmnNPP$T+3w2>^*a z1mL^0I--|=DFpbpRybQcjqnL3_mmgOFzMbT(+Jjq_wj4J>j6wfza^+tqAR!t%W1xw zrK~f=8e?!J4F05!Y|G<Za}R)jG1?oWLzcw=Yix${jv7o?3YLtQ81q1+^SK2EE!vS) z3&LJ^a+K&k{e$sPL^3qJJJ$LBmxF;ctQV%_64`9|apBF{<hyim4r!KnqaN51=Ul?V zX;@w<cKc36T&d?~QArtstdbOBDt9A#rb0uzgics#p&uoZBS$a<kn#Cn)tW*M`u|Ko zAZ!L7D-Rv^u=(|EhqApUNVX8K1D(!0iGX;BjP+Eu?m7-QFBMAORwNaCD3354G^Wgb zf&*z}rv`$n*W;(gTjM{bX0q=&R8VZ013q7|=s2B2GHZSR01*XAF!HsZ@5A&^SH9{t zGw5#%c=gMG+>u_|2jeMA-Y;ruH$*h;copM6BC5$K&>A?&)TL36F^mvB@$&u^EtAux zjv<Hs*QVpjdt11kgOEhJfm(rp0)(kxWneJfivDD<VM$4X%IC_sqKw>te)*3;Mf72- z)@m=_L(m;of5Edk<^((dXE*z*72Po|^ppSWpUxgDoXFy=r$Gt)qw_&F2?FjDG{FFQ z!htkEc-|OiacjDsql96;6w>Z%J~mgk8SVZGM`Qawr4>)qMN4MLZXz)APIw&|-Xm{2 zr;YnYNtwx8FhRefFokV{GcQh2q|;$LBv-nX<8zIK@M|FK&bQvgpVCEu*s|{6)!%Y- zKS%5mRD}avq807fDtv7DKoZ>OPUe8oCs#=-*bFHzhe04~cUHhyCxY4RHhOj&T{ent z)85dDbB}~&EUDV#KGotqeEATY&#?C~vM0Swaas_gUzI8M8$Qeuk)PUq_H!H$XJy(> zVBx^8^#Nude=kIf`BYXMhu;6{V^=0A!=Em5Sy9xf-BDz5bBdZ9;IkoOVyllO4m4o8 z`ViD?2nO5qT>sauk<?rT17dUBx)fm5ofYn&L|N9}6?cpj*m=n=>ilBI1rzBAi-tmE z>MYc((3*(0DCj2afRtZa@|T%P84E`G8%jH>QUz?@cus&UY%dDTGH23{%8`rK;gi)0 zDeRaJIjGy-M1Q-}Br2Jjz!_o5*@S~wso#U82NqiTv*4mQ50UW0M{xqU5hs`w@hqMv ziLg}bNCM+ES121|DZk}4rxLkBy;Nk)V)|VJ?WsuB4;eu<brb2>fStz!;dKNgges5x ztUxc7#SwM}a0MGvm!^7oaaGZW2+SOm+lt|DJN*%<Tw$oE7d{1k24d$f-%T&e-YV2f z`h0P?oJn{e$?4C8bsM2E9>4oan8HiuEE6hDw9%lKYhk>x^;rA3%oA>T@i}SIfvv5? z>8z5|Y>RQf2`ij5$M(bRJ6P<>Zag-$k@rnDtgXP|U$g`V3FWqaxaO?l-6FnPFje5Q zf{a$HSSRCTAywR%(bd&^M*422#3K?qTR`EEn3}nm#5U)`GZI@hPkNie0`U7HR45^t zMNE}e6}qf$x~bG*oN5+}6Fygz!CIhWT^ADeAw9M=3F^j4Aj<PtV1NBk=~V}(a^Cr` zp*j1H{w-t$lY$o<=;JKUS(B8LL6XD-I=!WPJ5uIErsAHMUD-+9T5lTG3u;m|EIM*e zCaK){<EB>u-qga`M?}KyHf6!U{vlqe`;TwU%HFs&l14|tKpQrz`CibocZht3wscEC zo_x1P0w#|x#>j6&vk3gfr_W+WEk}Y@r{pxMneE%40sOcqmMUGr@&?OTG~PRJjW+<% zlaa5Aq6V#5ldzLEQuq@EiCr^T7>TOMjlO6sUdyf>Mml=J<LtAR9o6P}%7gUr$wKJ( z=$TuNoyb4aSErpHQm#Y{ZT|uS#Uw3G_`Nc|j4{hyCNEkX6*bG~*ahL~-|br9R;7sP znDe#E&AXD3dv!;DQR=MOk3(NDf9>SLH3boO|BsPVE*?|rUH{RHL-Vb<vVJ_;3x8Ce z>859biog~S%Z%>$Y*@r~eT1~wysb}aqL&Rez7sxeKzf!ET>~zr2S5#MjiU9fNv;o0 z-`F9d`hwo$>x;XZYI`Jzv;L!kS}W~snhNO3Ow(fSf>r$K1H%jh702yE=_N;1kQ$IJ zepBl5h#v=0s~gUMW&h6=tp!*%?jn6+qX-0a(o5@Thz9nq*$mF{;_?|&2zGNaMTW!2 zjAW;GkooqW&Nig4eIX_MQl-_EWj~kPIO=jlaP)(mv1cluDV8wTQ1@se{`Klu^-aiY z1r8ednOsVG9yi58ut(+&+k4uX1-d&|h!1a|IwtaIKx$5k4(3a6ZPzA8COET^D?zMy zRg{gj>}SdY3B3FIT7&IqAH5PRxuT!(29J)MA{NylEgV(Tuj@<IJ~BJD;&><EW<b<> z#ub+id^RIPb4WW;NBHrH7FO~@DQvORzYF=-beAc!wtpJdXOn9OLc0n<fJl%^HEt5{ z@K54FQUvO`b_!~b%Je<~+ea~_pG}-$*$3!*FMbzBVpkTd$LwQKXNMvPal7&Sm()HF zSAgBhQ&Ub%H9CsgIq5}TiS)0X`nfYMm~cL}+Y^b%8$FNiZUV%5dk72L5X8rTEz<9C zQTy)g2J&*warr@E-3kwLgxg`WtgELPYV9=}g4m_It@JK^FXp}4tV%#`c_>(ru8wN@ zHxy90U?C0K$;Q}d|5lt}{2@9#x8-o-{Y9q3DelYsxp23WejGjY2WKs|Hq@11a_a-~ zE^O7*KfVg4*0eP5PWlCCxyw^{i9w0&H=&xX6i-qO&KU9C*lr80v&EflP7fHp<iB&- z&KiK^WzIY3KG8C*5f(g*g**8#I29PbgOkR461VZ+*3bwS#!qJ}EMCTPJ6aaeu8@C@ zD**;gZIZ{RY>i=~Ru*=}(71Xoh1!S|pi2Wy(vUJ5j?Ga~XAFDdBWR6G-#Q*l!0?bI za7)(ld(+Ht?P)<J<&apNN!b%aO*#-?_g?DS06F0ZaKJ)M8uG-N*<pP*)u1)W4`1^X zcEQtG00E|gCDzk|Df-}h=d&2F>pGO}fl`&=c|i8HAsyIDh<3RG1Ho4xIMzh!bbR_n z7>1c+ceBuWo3zUWzJ_aUKkbHqWhoBa@^5xYuqXYE0ItZj6nM8?e-c0~9cVga>+x3e zN7{ZBeK|?#>1E>GgAuPlL0W;0qu2UlpwP+S^^X+62u9a8T-I3qhwswzIgTT#yS@vu zn&Dr?6!0<@ZewDlW1qUy?N|J?C99^i^(*Hc<ae(Jx|itreC*Uh*%pNdxP2P8gFu>e zE{?R;94m*3q_+iZ=VfL_@0teqwK?agA+Z@nQsEm(rct9iDcHrS$f!6@8yAj=?{GVy zns|MvQ%>0Kyl6xo2;b(7&?-@(>g%m+CB6gWxhgi&FSnm1b#QmYf#b%VC*k(3=_|T5 zaY-Q1JVDq{;&GN<7D~9tIl$(ZBwwto1eWtQ^lm_s?B|_cy?sqRvX<(R+gv~MOvFyp zM@<@UBqSE(2&-yN^Db;caf9wmTS8b5jBc~Ff6C}?TVG3zPjU&HpOe7{<4@-(nrbHx zlLEoZjq>n4IuqCkBtg2_F;`u8vcWW3M_3mf5SI51FG5HOJXrZj{#y>?4nOSB-@{H0 z5VQg<m3ASp;I!sJEGj4;t*ee}IrQ7lsbAO^$qbzOx469`6cO_k?JQ87lcBd`B3v2T z&dvhu26H!dH*vqJdyZ0obQ3YSOXZXyd<t{8^IhC-7zLL+7_=K(z{LS>xHj+pQ0&1l z@&uEMGdOg0L#3aek=EHdGU8pla61kcs5R@><{UXuHDUEftFCGoC7}Gruiv`=oGYl< z4%Zgt_O%YAjCi>xVi4-aoQ5!`gICo&4Z9J!Tp6y3U$_)jSJvBEGm=uyn0M`X*Jh~Z z4TWAXl#+UR0SKg3LCW&p?V3pUi_{IF;giUn%B{9<ZcRFkZZ2Oz#zq((Is<ugtEMQa zo$$6uLUriUO8KIGfBcm>nk#Ly+EPo(3)){M3}z_A$17+Y@sjbo&8UC&mr0_lzF9$x z02$73kk^yyQT?&joxi6H1kP^)BKR~!rAfA{Eey#!>ZU&-Pil;&My&=zj<cXP;!Ch4 zHaLR#?!ztrDUpvsulZ(v3)zi&&wbDHA33@k@wfUwG-!oYWWytVJ8u_76X_8JR!DnX z{&`-Z5?`dOpOfIGy3md9F2pomvuxy@b=Gf)v38zIZn_brz>H;+HTzXjVPlPIw7*S1 z0W0Wk2bOWuWwkPaz$C%gw}|$#un6*ZHSh?^dSWncFN)&|$Eqzq|4SNu2bDr8*PF0Z zsAueqwos7$^lthVZS1UW^wbpK0)e5ulu*9&vWBhN3$tS6(S=E7OP%EY%&bZ#F-2F2 z(s7e4Sxvk-egzR?-xy$TJ_jsKMw0T^5+%S;rtH2PXU8tSEhkG8BgZk{u~+@vz!;tu zTB^@_^GQ*4a+~qFvvK9I0VkuF8FBl_jQ!&F5GXdKBI#mJ-O<CW_P4c4g<E%>Rti=j zmnaU5e=(pNz7e!?LFJbv{z|K1hc6JCt6CjTe~zqBG;Sk`twmkf95jEgFP+3et<Ir) zy$&ATLwN2VJPOX4;v<q#=ZUxKU*Wfj-Eua4y-?#}PR?^w`FyK(ucxx7HzAY~@q;(7 zVZDX46C)C&@3QUI5-!cZuOGf6DG;pPXXjL1sK4h2!n?d3<V(1-Ivu8g_=>`GD$3)t zfrt=l-W#9%1m#)E8EMQRmK#08vv8WhAP)-gdl@!sHsxkrNS}9*^W3hoH8$w5p|)%J zopLS+ui41z?nWE8=%Y;7MjiV~&~zHEc_9*^c1^R`qZo%3ZSU3mRA)1#y3o)yA(Fcy zaPnDG#4W4MXXgdim0HF{qFt-6iWmbP!hri|OWa&D6bS*7PH>S{N9AeIMbx$HHh6cm z&KAY;y+=FXqd?77lir!;GU=kH-6~i!REUxwkT<e*6$M%h%N-TRt@}U6VjXnc0`J_u z;BfE=XHnNB;(5F`0r#Xs1cs6nYd-BOo)C%jVFzGJA_m6uTstcb-ZI|zr;7{!LNehj zx<kqZ(DRJ#q2{XJ7cG3GOqPH&IW6);-^t!dzY?U&b@<)D%NHrJa%V{TUkomJ#ncq6 zlmaUu;!jm*=Ci+7lDuU3pK5bL@;X^~YsQ;dXcID3_=iL8VGAGesM3>SV{S!Z0~Dqa zJ7^e6k1@H45t=-Z`cA+bsOLTq7RPrEXU0xPFN^EfqdYc{mG44?^Ov&}b{2Vd;2SV~ zanNd6XW!(k{^=-g0=z=VAP$y95<PV`*s8$?$+)KAYtV@VW^-{;QM>n6p_08aWPYc? z#yU+fcb8I&447qKLt&HoqBQRS+M^FG*&T_DZh?%+Rkv-h=G|l|K^i6={f+BT&@v+C z@^>rDeu_p$GpOJ1V2Vp`Ns*-SP<LEt;+C>x)P<+h02_gb07v-9iZ&IO@3eqjG47Qp z7mn)LE$Ad46z@Tbo09nzrag4sD7F-;vs<`*^Oe+JPRvxff3!q&w2pDvX-1m9aiy#D z(jx|75)SS-+p%7_&VG4T{Lk4djv5{8i&T__PYGFbm17~_gO!PuhBMeC;Oqao&T!o| ze-KJ+>qDjLxFel)e`eOgsKCe4(zhI*&)iTQgal-T*Cb${Cs~6GT2hTPxXU#hX{h5R zpG~fdUbzVCOZXs2w^I2r&&JsF%$w+5d2EWO*TR835U@(9=%!^E&yr#`QQS%czLM<# zH>H>q#-Xz?5Ts**80A3|DMeJ*CkI{Q3>uz)jSJ*WQ&G5ac#sg%*XR8m+Gtb>#xd(6 zmMQ7rd<KrKbqzzf*|G3J_pf5;-;SS%2eHk7d4tn#tPO!Sb+dsN%w|~k9~a#tDtV{_ ze-5;^U~}Qvvm7<oZ;f+7JFna+gf=L(ZKM2GzqwjF-VCAL2gMQ?bE2|)tQJ~dz{O9F zPur~0_SbYfT4{D5ZbHNl5iH+UXdVs2vF=K(wyL8*t#o}e=_3hyuNw1i7^ObDoqCzz zLn^k)JY|l^9bkyE7|;vmJzD{3Y_`vd@pvF35JUlWZ7EvMLnCe_94dt8x6R}|N}*|? zq_Q@}O$rCw>uxosg||5YDd{K%MSE_Cs$kw?f`1M?jgHK3J*&{-`8bd@lt@#jo!wEq zl%F=uEahyMYDw+Oqs=V(+=!=5-MS<?FO>+P7@vgKYOcgygtw#qn1XS0p86trt-v?< zWXrQ%KX@V=?#8D(S0Lb%@LK6;h4?p5B6|vesq1!$?8L73z^x)<pfg|^j3pphih~EQ z&FfgRQEiZogiwKOkhQZ{P34D-Lg3l)5FxV@ksEu!=UijAhX*=Ca@AP(V8e)D%CzPD z88-yuUKxf;hsk9oM#drS@M{aVk2$6Znibv9f_ixYjtTYJj~Ip-v{i&b#5?In^twI< z!@PQ&DVy;yF$-|7%oWq9_d_Zp!@c>gi&Xm@$@~fpfbb3ibtKvqe@Pb~d{v?4{ijgE zgqB#O-lxxvs?Bk~86GJjj?6g&hsi*9`iDjg)i?^B5U;=&ZeL>5B=I_VJqS3;;``|Y zgV1E}tF3=tORTD+mK~}-s9&U#?q=a{hN{{Fek!q^U$H05sb+{?x?;+8hu?jsYL03c zbvcp0WMh42hl~4S*!pcf4v2z#w9cOjZq9ces`Y;9Z%0CfdFx`hnEa|rSkp1IZls^g z@|H$c*Z5Uvn=)2DiZP^c6v^I_p2Sv-a@rH1HOh!cpTwIw7T5I)ILO{qy`bM}!7gRu zmnP4}zy>juA82rJ%U@lk(+GE6X|bY>PHlj{J%Muhmqx?((-*9|>T=Ahyi3m60MNZx z!lE{N;H5uj54A}?Xu3Stz!F)9xBmsMuQ0iO4fbDU?06K+rQ|IqFaFT3$Ag}O%OD<r z6$Erod~MpK#@_&RK#RY+0KMW317M;p)uxper&|59n3N^x{iuM-fZp!(j17l?yk}98 zxSeUA>U`$y-Ttq~6_83x(tqL$9Ltr!#8xQ!ns#AjaI5xt?+R3pplWR=qJCKAI(zqr z=Rx10pkOFfs=->Ak!WlHvSYIhhN%u)wSUUm9vQg-E>~kIu8(IDyXH!Cz;e3&3u%L* zxT%OopWnL&hVtp);c+~V*l7l)JnBm|A7og!kgNVe4Cdv+(bp!_*G*HZxjOFe4pCsJ z#NP$uWFSLB6*!}Rz7CdhnItPy$6QOsuN_`bQB!Sj>UPkXy~!y`Zqsa5(STwfGWXwi zjAAhU5-eXK`>C2Oz=#$bFZeV8kk#TwYuJ-cy;-q%7gC;TiH9E2|9AO*Nc&xxj6IYi zu1>_{N5b<v;lUuH`GHBT-h4Bvu>Lv;WkE|5bV!=$tDX5&M7OSPc7mHu&3Qx;A!n6c zoPWy+`2I(ojG&-4G_n5-9UJr@N{FaFJ}l73F7Yc4Ha`i)eOMcCgdg%?1><{cG<z$x zWKJT?J}!`)_oZy|59%=;sb|_1)vcENX7~1^Wb>azAUhqVPG?*&3Q7I6OEv5kaXG9( z?F+T&$HFa^Hd1c7J?WpzHO8s>BE^x^!>WGptds+&>XKn7@U@{f3~EXA+!?pi3|yQ0 zD~$cKpmK-(ED07qMm!(NTh$g2-&bkLDVv}5csSK{?xtGK#RplF+g0avSX6DfHy|NH z-c#)Lhid=W79RAR+-iDyK4zjQ_8{J&jR5f===N9XV$*%trcsk)?15pE_EeKOGNF_m zAn>3>8Z7jH-BK}nm`X6LNz?5UN{WcGC&|?awp+We?9XeL%T>62R*|=9^|M7KI7Tk* zq{C9*Mm)`g5!wxi$RkK)7Q^d!?pOqxPuh^6ecskA%9zhk$Vm7}EiekA>dOv=XLIRj zs(kOevCdS5=Z|G~_55v#zhdQ>OZeJCmS1#$tOpaj++1OC@m0&ag1FPXe{xHhjP7Ou zR%sU9pG0#rL%K7Gtowv-x`@8VCyu}})9hvKBcddiO&TtnP%KFq47;@CR0;{k%G`3Q z@un^#Dx_n(QmzNX)4J9K6!XknxS${zLmiAa$+88SSDoYGe#}1kg)0dbSwy+|xb7f? za)dqw#6(xX=6>OkfQv4&!r9|+j;}-sBj_wIX8in9O$%s{p$LY|iz4}UGHRj)g+HD} z&zH(`Xo)bPZmcC(vx9WX=&6V)&?)6u2idV|3k-!V60w0sY6>{{w}dF<n&Gk_^@@Zo zB(9SBfNag@B8F4;fGkiiuIS22_E)3*ML@0+C;u}jqI$7F!rV!*FBwrkSX_*Gr1;-N zzAiknyu%B((9`~=`K-R?H&1+)_{kYf^TG!4ilTOx<akflVK_!iCqs7J&ZL>KTtSB- zyDPDT@`3gm6seX{QwlrBme=H|@wsn6Re`zVKfQ3N`jOT$ML)K?qz}!;2#<j4%2UM# zh^f)3`40HOz4HCZAYuYt><)V8xkbQEpR3BE)cJEA)PQU$WbuWd*%FlxR}}g@@sB9_ zIfQdfPvj+WdOjIZ4h*@5k9#vt#iD7$G|E=dVpuzC<|x|Ls#b(eZ`isP*k?#;4Azf? z-h`uDa=7yWMAaz_l)2L?KiOFu<+;2Wdg32u$$tt%uy7}&)AK_GWz*!a5-3S-dCwwe zi>IizSqP%MhCQG20Ed#%WEFrO&8^1QQp<1ilHa2K539)ht33s*;<jJSLF5p96-50D zT;hXNz+_uLF|5I%MW!L{Dc#$HJ5Bvg)Dan5gS~^h-n#a(;25u*6Df?6@u;XLQ5{3% z02j@w_R{YrK#Od63$+-ZUI)S^TJ~s0n|N#o9F)4Edatxxas+N(k9Py`cd#}{HZR|A ztT=w2mVuE!nH`LuW{%REmx-T1<j#+8dq;2}KY1&(=r4m!za3qkXe-&Cv>Q)wdb~x; z?(!q^t0tQz8(N)hMBMhkcZzaYh?BqE*qub`x1X8_R*K@%)|(d4|KsM3l6-LK+z2XN zuPTha+umTb#ovml9I}8Pll;}o;A*Zt;59O+d!J^*+kG#RYETxA34u-%4Kvan7@Qn0 z**?)7CRai5@T$+`5d<9%jR$PLW99VD<5Cay<BzUC6#YomP)62i?VIiYI-YExb>7mj z=o6CBdkGhIu68@#E5CJ`S>m<{Tj!+3j93TQ78@UZF1l96>-`ldQRN^_;(hTG0bCqk zIyxv*zrkWJ9^EAr|ID~NC|B&BHxKsY$p&<o!n}`R;F0-HA;~W#VVJsC^`PiiXjviB z*oh}5y(4TWwaHtEVp^nsGLyo;6+y*I;SakdUQH?*H@OIE`Ct#FUld=U>aAblVV|tQ zFRa4$r<wQpyn<Z<NQ$95d$%p-URPZ*&&@+$VjzB4w_LrRUD4uJy);>Wl0&;;X!qbp z@Y!lpW*_rLe{9QBZc?NLh`u;kL4GAttdz(Yn#u5YXaE{nhNJCIyC8*cz*9cYf&RyT zpaqLDGN>I%zTPa9^WDp`sEMfyTI#l887o!D1pZWQ4rw>M1K6Vyez>fU;tvS&|BI7I zm2}P_;^DFB=qAkY8Yfa{6>8%7_Ef|v^tENdaumEBbi5A=#v<K47m}q-xA=F=Bq1>} zyKKQck%(-fylFHiqme(5FY(f{PRYCpvq_y3ff<)TQp#Gl}sfqENM^#|27gB6&BE z=KVm>JDDd4dwf-x{`foHX_h9RPZ+L7CpoeH`o)8!EX)NA>+hEk@)`I_O=zx-A5l(< z{P1uaPiuM~HPF1^?!;Y4&MKH}*VNsNy@4n)2CpCaevq=69aH1W0BL~JUnjqnC^6B% zN^ilO5vxLNa)`%%=D!Pq=F7&Bb<=2P+c0VWFb5n6)NOuy!rRq4Dfx_FfViK=0|<$X z-kdTX+pv&adVRYJS>hjk`eZUGwuV<wN7qoHPVn;U;6k-(5rB`5(px<|(NoPz`)fO~ zjlXD9q}fn<gT6h8sgfibu0pw$`Y9Xb$?<Amzf{;m^|tuW4I@VoS&y^$+prYYACE4c z{Cv#;p5nz?F1XhvhX=W+7N&FuJnXO=6;c0c_QwEnT9Of@Z?xi^VqLZ81LLbx1mxKn z>h5rz8|pao1Zw7OC`5LIvY*y2=vl64-es0O^g@f#Ojg2t9ftm8x1==T8wjK=u=mto zgd6>884fqt=9(O`Qe1O4H!)!gu59f?_mE?!1cG{MQ(<oUf}Qsw%qieAW~jj?Z#Z*L zS;RqDXhWdbzpfB`ecxV7$b7uaJ>@4I-a&8%jC)ajeBjJ@cI^c{`6o0#=~7dyM(rV{ zR($P^I;)OmZ+i@z9iwKCiES%Z2*FN6!Xs@{LRcs$=k29FU|v^y)HKu-h<Z0it%4NJ z_dr!~SJQn)Ky>yH<-gO!0%~;*W&ZNZecOiax&wLKL5yDsSh%;H#kp!CiFu4hhtLgD zDpE-`KUM%#YOaW-z}Q90EyvVI=C_)^{(<_B`6eys==k};t1cDSabT%i))()79XF2s z{YI*)CJ_>n>csk+5Y29T9j9@2v^9fFt0-yoQy43P$JHp#H6uV@C20D4e}Iu!vF>iF za#6$P+*(dnr{*hMdZ_}W9YA%fdSZj!*t!xNsbfl12DH->|ALbY`4-@7t*D4-8IizZ zR<Oifaq;bMEuw#b%8v<oZ@j1veqnPoNLRqFYQQn{XK0o?TJZ`sU=hsMbhr8GXH)q7 z*)lh=V1dn+YAqkxKYJI$e=)7nlL<X7sqs~=b5Ukt<`W-6IJ%aXN4liu&z@_UmjAez zY|XxdCXJH6!|;E9!fF1A#U&O!7$(v((SJ?hs8!k{xSe;1_e@~^<g>A#*Z|?YO~6Ci z|D`u<fEos|xpZ6F{tROFdc$)xe|Cq#CdG74nhF&(+(3MLfLz;Qr5sctnzr5)ImpNE zmV!jM4)pDmNNN-_9Z$Rb7e|ga0(CMDXN2}QRb@F|57?|ZmI50rxt!sq{K(cltN9Mz z{#aSbNueuF@aSIV`V|LzilY$wfx7wXDTcq?Sugg>ca1Zeowcj14~B1aqhX0W;R=HR z5Q{*?JY|U5EeQ27u1k%AJ1g19e;?V>rJH9F@1J5XlxJX;gq5tk`Q@)3R5+|tUYoDX zYv;;n2?+!e#SG>!a+8GHff5Qd?85Nt5IwiOL8_LDqf%l)R&}>=BdqJF4gRNbx>+kn zI=%trp~EBDe|DRFjF~no?b}KDm}6?A90u%7WmpTPnb3Ca%mDX?H{Yu~m<vnw%zUhQ zWSGbHx(lqyl%$;gFJ=ZjsaI?M?Irn*(1v8cuKcQ2s?=X?v@S!{1BlzV#`*iOeMBq* z(ndP@f16jBOTMH5Mk(p~D}_r1YzB9J<BATMqF`M6_^6f-i%FX$U5AcK=hY=z9&+Tf zzD~#1a&-~kSM90T;rs}bhmXV3YK2u_syDI45k82KV%OquWxy1cw;gmw+jRxy*l=-f zf8ZY-cWB(Km$nv=LnK`XhMEqiHTuy66IfAt7a4i^{>c3dZ{Fv~r}r!TGdhk-b8wxX zl>;u5YsrUW^f1Q<i+5ifs%I>p!$Si-Woly>lwZrVKjW!ERv|Qd?KGp)$3(|X3z}G^ z^2|Kkb^SZZVV*Y6{WR8u7st049-NChBdiwHozNPp7AxmBLRxzCA}51-QNcra<g^oI z$b-u)z04I607&i51TyI!s?<lxn|I9PD=PHV)h@<`R<4>52!k+24GlcpD<(HIV1a;u zk%IEs5?%^g3R^p#l-`_=&)Zp0$llHi1d08t=dI1u?Q(q~SPA9=2xLiADdxv2E;}Iz ziV}1Y@Dxy4R?|KcOgoI7)DYx_J>Aqw#&dih7N;zYMq;uV$gDPZTgxM@|8f$^=|r%o zLcrx<wCH$7-vyh*Er?}B(x?Cq<JfK*zK)!_AVZak;p5g@;WQhsL7``R7Ofi6kJY!) z{p-s=8PVhAd41_w)+Ewo0$Z~1U4#62FqT#!o%l`+CbV06Y;k}BDkM5t&c85HvFRlI z3LqD>`Z^Y^T!vUSz~T^)S}G+qyr{~zSi+q1&HV9U$^tS0qOZFf?ynaifVTD`J1#x) z?aVWHKG#l6CiGdLL^6@N-y{N&I07-i4)>hG<ib`%;<a#mth#seg)X@n11>ky?eHd3 zjcMWtqiIBP-N1ZFb_~hYil&Q2;z9lcpcYv9&8&pc{5nJq*C8BT57>R$5M-!6k5y47 z59iZ3*2@RyYV1Yu|MR{j;O?vrV9)g*mIkmpQgM4EpF`<<r7*)+%L$)nt|th!Ex_ks z5<>>nN-BKL@2ZI_=L?yT%%@$D)K|b_!2NkSGVu)_r8b!Txfo<!|5Nank?L$<KhG6x zHjf;l3}?p-xkz~GIf}aInBf~dnd5o{7~G}TG?0@RRG^4>4W-Vox5bkyg_fE3F108Z zq1QY)OZkay8;GQZ#>o?N6&8gKUCY0lga;LcMsk1iYeFrUMLiA%?o}ku2USS`5u~e8 zF=o6Cs<GOiI7BD6X&fW~zVc|S^CFuoWDt<4qaihz7VsI{dAIWp`V1oEbq52!^5x7Z zZo^f-5if{$tX-bU=!dz?ZT0Xim<|%WEmE+T+tqX`=$2Ho(}fPu(H&O--Dio(7ZSkg zQw%<qv)_M)TYD{;r~^Q(WC7b#QJq}D{Uy&&95{!@9mTb&v5)Z{9pu)ZFe(sEIz+A` zx(Pg+JVuIwr#p8Tw*v5&&N&N>?ii3)#rI)7^@Sxd7nTlVALJv~cueyfyun%-xSuOk zg@~y`cfbP+D^uE;Du!PpWtu?rln?xI>_F$&G{d6<_A7o7NOz`WoLz>;aT<SbvM@iL z*+C3{@t=R<RYADsJ*Ot=jt@TEX1dU?!aWo_FZVGTSJ8F>x;{V{;Ljc#!E;>4XX`q> z+TO4aFy+0g;u@NX&yR~E&ENt(ZPM2~vqXQJMg!His-pt?z@>p%Qb<M9;>B+c21EdW zwaR5N=L01?!`1-&DX*QM<u^EgZ%HOskqY7l=H^eVpxR#Cr`n_Y``bvMnc{X@m);N; z$rt!JrT{X3(G5wsC;|GMi7_DTO6ztMbtx}~Zhv<(cJ6)?u31gg)e4z?Koe_R@@31V z6Znz%FiXGtg>d>`EHsoW)%W43>`)K`xchr)IIIoKOi{$x@CUrZD)ymfM?sMzB$V`0 zuG(T<bYG5KZ`#2J9-W>Dz#MYyd>zkGOC%iL6Eqm@hjR!623}uiz+&|l7rX-UmGj!B z4-4`)$w{8MVa$f#l!(Jl><@E`Q|1J&Sa<@rTgnu9bWSo=OfC8JTm8;ZBg}0qc~b|B zT7rOre}7LaviDi0eX8s7{Cye)hM4N#uRr+{6@$NFOtI%Tta`jvJ)X^Ch?uZUTRgL4 z{j36)*|YO&A$jHm>GVwxjxa`A<w(XOvDw4rortvTq)<EvWCQw5gJtabdHKf=Pz+2N zMdGh>Uuh2xBUb-K8?A_Y+ni^f6gX1_R1=IFzfUK=4dK|EJY0lo^ooa_Xx)+T-2{xX zlpZh9R?#ldaE5fdgY|$wb(}XLHyEQP!^&8Ya--G@=lHOKO%03$f%MKDMK~=fr_$TM zNpyc8N&VDUCjbR0sesZ=er-P#ie6&k<xHurqvOV==3})jZLk~yT><?b3vp9f)eBkI z*nL>-e=1ZXU88<<oK0i7xZ8LGW{r-J2X+weZUl-|nDnZrGYOx^^o@bfvVcn~IBbq5 zJ0)5vx}sQ+IB)h(2$u;3My0cF)--5z472|$xjU&JdBRD?OX;Z7Vi79HSesv`CK^9d z>@+r?jY><49bRskLFJd!rKDNtUoP49Xz^t&GE469g*XO{7SmuS5%(}G3SRVWWPbu5 z2x)e^$}%{M723C%d+B_M^Q=AIM%1GdIz25Jxw-}ZM>xW?xU^TBu^YDpU37W2i%Bdc zr#B*aloALfrjn9QLHe^{E&UIAu9CP?R(D-EGt^}o6U~h9;MI~q8JSO%H@Hjnze^3o zkpa+6V1pJ5CGFVt?kV1P(6-L8G(H2y>C}JNB+<O86`iY0?UR3E`@0=5GjI0faTK3B zs3v}iPsBe!$P*I0efh)UyAJgo?!kbiuBzL?{1zdm;v&mG(nQ7gExysB1QCV^&Gs=| zLelulK5@fBC5Ai7%?VynMUR$|ac3fVo%coPH?_Yd3J5ndto7!GgU>ve$dnm^Q4F5+ ziW++GrD4!C1w0jR)<{XV8G+4*p`10-k}W(`k+m*(XNAP|2d$0~WJOzY+~Y=*w-}ye zD?m@L6S0BIS2!#mfT|O$`9qj0u7l!i-sZ0F&|FAGzmjDl5YAAzcRZ=YQhE5pRG(yn z=~zrUuZ}c^dtw`HYJ^CPahHYV2YQNdSNnZ53PTYIu^sq$(Ft~zxGeT8Z0%^-3E&Zk zMqWjt8D}xAa8>MpZRWgrXP2O_*#y4$LuhR0HKkHn=DU>_n!@Y7%}-`tLjhmqUh@=U zf)e&TT@?$rWL?8u5-&LU>SvfvKS)(RsjLSJiXj|%xtLpAP>$r&-fadY40~3#@Wfk< z98^Ek$kl|35?_9C8YxiJ9?Rqzd;N>h4^OQGky^v)41+|*JW-pdh=z#Kbm{ujO>OzK zI5L&{*PR6yQQILn=?f^;pf*Pw6p<xI<v3ajJLve(=FN_Y?XI)n3g-r96#{<g)8(zV zdwT_|scj^E<U{A^M0=+o6wEtWEYJ9UZA=ztLu93YM!l|}8<vKqj*-@F6){g@==in? z&Mf4f=l)p2t&4It%0+e=?kIc1z*$rWjUi@~9+{FnuVt<f9gs?V0k$&0UmR9dG)%ks z;bK%~dpQ{1`t$=p(Sd1klA>@I{}W^ZoBq#aOiG^<BHb*2Na1N4PS10bZDawCvC{G> zAL&Z4O;s~<=q5M&NStk@Ix<-W8cG=MV}=+H5jSV9imnoqDq%h5MbipHm1wDjWOO+E zqo{xn0)poniL{m?k#?)*t)ym9Ju+~NcEhax@|3l>5p+1NaF2T5GpMqOv1b}GU>6t4 zX%zlO-MEGc%&|WJ1J*$4Q<%S(ONlL<?|-geUuQ=$JaP@u@hwDSRwp)gRz8{XpvYZS zzqUKRM`B%i*10s<`G}-yUVF(al0hd^lMy%dL7mbgf_}MR7zQ<(EWMMnSgT45NRP4) zkd{A4NQM0#Ei6i=gaUBqt5eafSe%V<z4G=+NRm2+n^mMg=jxZ`!Gvp_(9IM;Dbh|7 z^b3V90F4{(qk^_uC`Z#hdR;fHarv(4PtGy@7Uw0vg@Cw$&rcdJkASlK-Ep@Z5$nv6 z{mr#q;Sl4?!Qlq+!@W9rM?A0EslW<lZe(+Ga%Ev{3T19&Z(?c+HaQ?LAa7!7AUr$@ zFHB`_XLM*WATlyIH3~0GWo~D5Xfhx&G&eXj3NK7$ZfA68GaxVuFHB`_XLM*FGBz+d zIUpb)ARr1aMrmwxWpW@dMr>hpWkh9TZ)9Z(K0XR_baG{3Z3=kWw7O+foXfT~90=|N z_r~4b-QC@392$3bf@^Sh4GHe<Zoz^(L4rFU+2@|S_c{0d`;8v-!(2Mos#R6p1IUS$ zROyAyKqf#5ki82%GXoP3Ku%sBWDjCyqE`W0xY`;!0azHAnAqUR$wi%j#x7PMdog1d zAP<1k#S)-s>hkXTZo$OF4Mz@;1lj|g-j!wm6HkCV(8XBI(*ei~pfdgoD1n?^=uM2B z-_<~S3oCmd^}CBG$idUe%EHp+PYhOi`ahBWc#ALqWQ<L1K<>^qRsdsrGk^?(JOe-h z<o+(S0#JeM0VY68V_S0o$Q+;s)B>ohimRvsBvlmEl~k!2-UF+;Iyiuw{)daGs+zha z9Y9Q2K}{S0)Sv@Ms;jE~c~=A4zw@`C11PAy>;L3=H~ix+FRmu6rmZB-%=o7U05iZ1 z=;UnmC+&Z6qj+Zq_?z0htGN@%?ym#@DoYm^2OdU7cXxLN3s+|s29T2lgM;l~{M0P1 zoB{42CmX=~(+Ow`{Hrmp_Ga(xbg=~fE5M&c0mxaI0_~lFf1D&h|5Dn$xANWTUGDO~ z#NHd>@+YS4zsv#7K;VC*u{3u6%U4cGNe*CVY-R5Pv^TaleK&M5c5!tE82u%C{{fm& z{)-?GAnNMm^e2b>zg15Eo95rtML_SB>DhYw8oU4ZiW%FxI(z-2H~(3-DahX0%Gt&F zUlD--b1PfmANJ0F*38QOFPXfsg0zIVsv5oA`{3Er%Y)v#W6$8?;qsUDpLoJza_^(a z$pv6xVF56`52?7lnJCE4?wz$W+@JP|S-tnk1?1$(_<!cw#vbHu@BM$}=2rG*=6^bG z=IX$xZg1u23X~T6AM1A!+}|<_pbLNr0CWTZJxnbb|D^kCTK<Tc|A^n);Op%GasZec z+d2b%t;~V%4>)gUV>ckc#mN=u>-|r~e<C<$PJo$}smuGIzi$?}zoJXqn}Yz{{}R75 z`M2tSMu6(CjY|E#OU*#`ww?eppgA0)0?6fkAgKQT*=PTiOTyLGR>9Z~NcG<>{ck&C zJ1bky|FHZo3r*l3u2c#jCp%-?|I%4GOIUdT&6KQMOfCQF;=jbwF2?VpFKlmN3w&Rb zzeMVPc9ZS<*uEb<R)0<|06jAY=YQ$mC(_i$9_Z{0;NbpC1$^(qfAM{9{U5dfMg=8l zQDJG?|1&awnTgw*g3PS!EdVU+8~|e{Cu2`IruR8uVP^+;Gry0t8PMaeK>;u_*n?c& zT>uWQF1`SBkQ3aW#e7fCDE>$E7vf|FFiQT7SOJXEe<Kb6quk$!6Tm3{H{yC{`8Rrx zsrbK$iwVG}^fzJwFsl5G-ZQBFjo1K;YJVek0HgZ<BJTHm#($&td?tUR_k5=Ri`d_F zrXbt*zW-ao%=Avd>>u#GO5or2?{)pP@c%G)Cu#l<_|DSeAMl-~<v-v%Ppf~xccM1` zfbVQ<{{i2r+Wifg---Q$C-XZo&_Cci4Tt}QZ11)X#_uPiEztaLu58TzBX#<Z64>60 zasWD6f&Ni8^E+>+f53O%&VM_+({{EscK%0U%<nP&(UkX-fzkEvp1*tlb#FMEf}DW= zuzIi8?H};HUiZHt%X<wT|A6o0J^umU>-G8z{^w3m`g0Ndb;dFMy*2*lhWrbwx;TMs zfSOij@1G9-VIptr;$-Ea%k+LgF~7^-U;qA1|34Ct|9!Up!&^iI<l#-v#?B0&XMJx4 zCoA)x$>H$*4_DKF-Bo{`jqh9d-}ui(0RRF$fTnQEiy%|p5bH0EVdZ|}h0_&~<lGFu zsxSq#WD+2jGp5_|u*LGWNq~Yyfz1J#6h$C8DIR^lltB9uE%Fcy+t>A$<m#zwGi9M2 zV?TL6JS1`9v0M!X^`K1orGSb~66zzF+yd=Vw%N?qgjPa;`q;53cYD`E49nyj>SZd4 zUPbF#KBRl`JaZGelkF#uB^2Bayrt<5FqgLn^tfo_Ug2e$IirFw%rO}#hn_AJ9ojDi zYFfwL-f7LhD@O?DBR6!|;Idfxife^(RL<~<O)?0|bfa<#F~FP)K3mz^q)i*iE!7x) zWE}CXAW}_kpjc6EP$4k7S0zN!5%o9taMTzq2y?1uO>9S3-V<PbY{RNI%@;n#j;c>p ztJ0NX=+Blh(yN@?l^tg7(_P8ICi+$sjGJ34jEz6&!a2*Vn<pAgPZ~b?BjD@s7pg9$ z=Xr&k;K%Qh63yjA#<)H~_|Ci84#tgv-^*a^IG`y^j@uAFZQ!ygAQ|TxAN|PDzWdEE z5l{Sa0j@$oFNLVf>Bt`IYHb<6PTrr1u?l8gjm8{r%k762=B4mfK+9>~PkQ&qWfZ5` zF~zJpxDO&&NTd4}R5GFihtl_}{XnIZ3+~l}M}mE?>^AI#MeMiZH;Y$|;3|^YQ7@1? zS>X9r`!I7^{t$n^#-SFrBaYou(bsA%h1bv$n;dyJVrU+)`srOI*64Wml7K)BOu-_Z z8#6>RQIU<dduBA}xX*cI8aaK!$Wa&&4aH8YTIwT}wm&11vINSfSGEoW4ta}1!%x>G zUf70;Hg6`;Dn{nz@wKDN_3K)%HG>c-RE)S;7+`oR`b9QH;&*wbh6M9wBP*QA#W)`( zGcFPr%H4LT6hCaye)zdM>YFjgmHV-rZ<;4|QQfo72HG<Kt`+7S_#%TfL1CcLOMk^^ z;U;FG<Zp2RyMXzPZbBHfsfvbv7cGL2)8QFf6%0SEgw{*PL;VM}9^bBVn(*K<hfXGq zq)=GM))hEnU+Fg}`$(N8N?d%DJcl{)`_F2P_^>P2$qwLaEfWLW^-`Dm+NKvUzKL#q zKyz%RA9l!@g?1%rH;o8HosK?&YNEP|KfR{%c@0=gmS!S}Dd)9jzpF-J`IuIa6vVNB z&s?nz#T39@`JfOVn%AM#%e|CvDXUb*rdW3+PEqvZru$!QXBc%1yo8I=nk|L*qZajq zHhb`ITk5FJfgqXYs(8a8T+9RHtt;^b2Mfz5Kfc6xVxZXftoiB8Or+D`eg%014V8@C zvL_C%J^+@`P|rm!LQGv6kl#YBh&l=2xE{}OfP69fdie9^=!Wu6y5Wf=A^xG-MzT=G zJJ3mIH=j^dnOry$r<dIVKk45a{|?B`5Yof6v<%&LY>eI3lbhn&H2g|hvMcjzKRYD= z_9OQWH>bW)X&Mn9#q*I3+4@qR+T?^~p+v&qu@rux*xI?4gv#mDk78nkCGFI#R`JJE zk<0Nb8S<VLxHO2e-;Y7tq|7kldE`IpB8#2vrbsodRrpzLLrE*fBZAbt2637&cqZkq zEjvZ<2bhm{zfX`kk9f}Dqjr|N^}7zYa0iv17C;PGAbd&^j%^nsmnIK{<Iu^DC0>3Z zPL_|F*@9EKbmJ<KFHz1pq^fyMSZfObGA|_QXH*Dr+?^Q}kGHiVaWam=8QgG;I&R|M zTCf?>aYOh|w>~D!a^>PP@KVtB8ep6X(I88J`>q=wPYc8xoC&Z}ZEP}EvXST~ma)1( z$9@D&U8FV6>WWg}i2VAByU+0yE+!<gCQ#~O^Wb$$Ok;r>k(s$NfVI?a?miByOM;Gj z5jy-r7=w4JOV(~5Pvt<z{)#(uhV=BYTZH>dh0x*4m5Y1EB?qg;^Kx*UMLeF0qq?Rv zp8P2sPX4}xe0o#yrOHNsZ1#K#51E3_0dLwpfR|?X&9W*ND1eU^!T7E2=vuA!2I5#D z&SX3-^+lZTs+JVGF5xaq4+M?q7m%BWzy0X(Eulr_Ir=EzK!+4Q5{^TcA0vv1oDb6` zzTex%epVJd;=c9w_Ydv3UfG&8zqi&VPbv<5Zr0lm1e?8*x1Aj7aho8+BH;W^$V!6c zdJcsxC7jz&@WE_+B(js5$A9z53o<yR0gI18n7#UjMQg!cjjrxi=M+jO;u8<-G!aLE zS^&RVv6IXb!+W(o&+n?Rq;ixar88;?4n;MPkEGtK6>UponBkBSZ1P@La{KLOE*?Wy z65w8VsXK*{H#Iw`2j9P1oQV1ugVpMa%hf=it;nN@bRvFb#;u0jjiO_wQ%Tou%p~oa zwXCqZzxIa7D6h%>N^*=!3uzv6Q~A{?+SkU?P;#I;7LR}3mxo`D!AR_y5RNki|H9)U zBNcORGo9twgmN+1=Oj{bKxU=@d!5bEZlSe5<b_?7en~b~=9k3pgaDc^U)5;zUTmHX zcQguV8?HFJ^={<@Upa-B*;In|<<*3S6qzlMBsJjr8p{y4v_IC%kz0QYar3RcVuklh z`SvqEP!{rY`-N!=4KiBL(PaXUi;DP|bqV&;t)0>Lu~gj?+!Jjlx81ES6=NZ{LceD9 zGJH^!ygbY0T{n2LAvIM2_KLUp6HtmghyvV-5Bd}NbnzDvqqr9?ZJru=3t$%W_3hpI zn1SZzP~!=Hpm#Hp#W+MNl9BdpC&kJAq?*bgrkC)N(f(DounmhQk{Tc91~phC>N2%V z;iN}_qE|r|p2I-{`<yqjRVUFme{k^PIzJZJjod&DcS$wcnNV+#lF=L?R~K-Dh@e<B zyFGwbCOd$4k-b}+*6OADn}_28YSRU>`DbvUstjMOboNW=u{a3Z?rQeum({!a#@<dV z%q7U`tTk5fX#z*Cl?aySpMlmi_1NmzXV_rI#jR92rjj8IeNh*a1hA$PzidkMht$c2 zP8gd~G;IAmkx8cVAR?3j9OYqLzOkv6ISItlg(6=R)#CxvW3hx+_xP9;JD&uB?7m9U z!k-YE_~JbAFl#pA<$Og`x`;6(#m!Tn;H@B$W+hEr7r5m5LPX(6f{G%8^q^WG7a}yu zGmp28%BH|dE`JDG>pbf<8RUlEF8fjY|9<9Mdng>Y8nVF);tln^K7UxrmQa~AHx|Zb z4C7$_Xba18$HvpxtcXn}PWghH7Bs&X0k_Ywgp1q1c^d?Zk9xScTMnz6XD1abK{`Sh zgCqCETUlQ&Vb<*zS0tM0#29UwGzCjeWe^VT3yw(!qkwZ^Iawf`odv7xZO@8WcF5=e z|8>fBy=Q*hV3?#0)g{2FCD$Xx1<DTCYz&T-LzYHXo>Fi!5o+wTbC^np&u#KT5hUda z;zcYYuki!#`wT;~4uQWESz&yQQ51#j?oywe&y}OsIlKHr_GPZ!ea9{xQkqS_gZ6dx z$w0JFpdhQ0rX||IW7=+wM>$KY7W+s@C5L2_Gr$>D@Z&G>b*t|Q*le)AD~F_hGHlEJ zXw;Bg1KVFd5vU=3U*-A0E~?sqkV!w{HIz30`pO8{^M^<B;PcWDu~#f3?piVv2RkAy zdxQwND{%t@yj-D64js<ND}@YG6y#m6({SQ}x5pKIbvXMD4la005+$Rey4?(=Kv0+a z5Rl1&Jyripl7Ro(uno;gmuj8ohd%-1lGGV`10H>vT4=6oBE=rB#Hz*!3g9-?YHD76 zyl@B>8R{S-YQN<doA;?#k8TDpLakegc>;QSyDp&3NW5#ILbkweFqek@7W{td%jQ<G zt<4O4^+risWq>|xq9Ny@_|O|zNws&j;&XVTn0YD{!{T>zFaZzk#pn(Awbv90utYgY zUN^J|jb-@wzN<mtE`Hl`CkY2N8hy5JT4acS>~2AUCtI+@P&<pQV$)}l-f&jLW^!@A z^y!AzG;Bxc#P25L`lyu?4QK*7`tV9P4_osTAuMJ9eCe*8-1yhK`gWLK{6v^A8Mg8k z#~+j`*SlilYROl5?JQECCn-^rVvKaE5Z%^_khLY2DeR%gZUZqDkFQvIGCLUXF7m!* zK7p-Hq0f&RMoI|WPERaZ&I^Aq3X(^=OI4}EIa3FC^Y>&ZKUJKxaIdpKCRUIA;Bv7O z$i<&};&=G~oAoR}D1R?%U}hdsGCGI@C(Z8u0ka}xG3#&;z~eY3BIi`=+7lROO~5|q z*y#QtGYm;SNsW3uy)hq>!1Q)BNz1%{1yiB-R(@`qi(T#25OcK_=X+_3{w$Y#BI()d zJi`MbJ`&s~Nz~EpuHNrZKa~ZoUh<Ua?-I2zLg#C3j>ROZ%lfznDjIN`Lr5920dPVk zv6ATr1{!Nla*1^=0-A;oo(WO5$*1vias5+2(Nh_yP@w4)$v6+f@EoBsn$6k2`CUJP zHXT3bS7b&Bb^hkqEBJ-Of55BrXfn7TG*fuB9tcYqRp3~{U#-jueGw1qNDcM^p~yr2 z@iVk(*_0JSc6<H<B-9Kq(P23WN?v4oziUN|hGyPw@!W$=d7N0DEz{fUBimX5!$+3s z&yvq#YS4+0k$yj6TMttln3BC8q#7&LaDXS4TA+~RQ9i;W>u80dP;>Tyw}ZW)Jxux` zgax|sG87G0%mP(cJ#<jj>|UKNB>C(b-&4mcm4{|V#?4&^ibtPAfJkKx@?Nkj)u6^b zTNYWe+1$K)w~9L-6}77lEh*h7IxALUJR$2Nr##I;R9F;_lgPCKEprHw2|-g8Y6H=8 z@<GvHmHPxUos);^X8L|z<PuQY&%i$V<|9+sM{Iy?n(8GDI=-w4#*7Ml6&$)8Qy!c> z7<}(kRm%NY>qh=>pudU`bt>sjGH!*+KD@z9B=^GBJ&nFQldp^+**?MSkbdcqyS-XT z(8m;%V?&dU0s`dtES)fOyly2GZl`{GG~3__)STZ3Lf=f6^G1zS$auqZxF=`FseU~^ zHDO0Xn_piQ=X|H$opzD$y*jsC*A|IU<^OtGBD~{i7*2|lV=*G*A6O03VJZ6xGct$G z*+}=+5;Rp|7Pv_~mM7dN4GZ1P&x;a+k%Bc7V6c&D_F&Wysfd`b?MWWqtM&CkrtGwe zyy`<{Gj1#4FFffz{Uz9fR!r$sTFZBnNCijOs%w#ZzmkxHYPXQ<(=an6d?K`rZSV+_ zt!#=nzw_LRbt9^{#ZvzaCW2ZhFw7m!jLOIi`pS>hwRmK&c_buM4p3ek;FF}IvZ?|F z+e+9&m^NJrHO~4<b%3dvVpHWj$))M;671!}m%7ETOnOC+ndDUS?9`sZGcQxr`l2P_ z4`6lE(88$>=`<DBTINfOoE-TF(zb3jo=O+dUUa-pD%q^DBtkSy!=yif`c;yo2A4St z%&nafz{9yFGi2?CZeO}lTll?jwZp`%{r%usHC?1lHh!Wzvr`EDv&@8w)6;u*h(!FU zd=TP<(GAI2JYsbO3U*VGQNg-c+NDn5`UnR?OLYVW9Tz(?nBrk+XyGmBv3Y6aVB220 z({LX@)7j%AU#K<>0^657K1>{>j>@LQQCM_#*g7_4yrnw9$AB(J57rAS2KukkG?T&* z?aLeq$qY$)!Lf96g<m>pAF4c6@1=_<i^IX$b}ZL>N}3loT<{DzKFlKacpQJVs&!)Z zFPGLI9i9x?l5>%lOc%}w#l7Rh@z}3E7AfGGLRD&L5yP%&2fGC~(X#mo$j4R~FG|xa zla<+|D>aj^0fXfDy7+@$po35Cr3Z?rL&f%^-vC<1-h)rCKb6oU2Z)d)cr*{a_Iqtv z_w0G+`v;Rku+I!})@9!H>^KOC(jDrW6a?v~2zd0Dq|n|dXMWp$M?%ag@GQhO^$4w@ z!*8gkCuq0={@*>(4{pO&G)}nj+QSo1t1kW5)A(vdl|__ChRz<(a)5&F^&Xh`j26vA zkd?pdf6T3KGU`M&Z&k6*4JT?n9^JLFXnz*~%(^Is_OM`BE+5`S<y4ItZaT)8Na5#M zKfChj$12nX2=EbJ(<iMTonxHMjn>w;PoUurohQiC4M;id;G&2SkFfBq#S{q8SuX^G zH?7EhFKXUmiZ7a}pAybiFo<zZ?H4@!g;G#f?1kQRsg?vOi8JWVr!s?L_q3{SXMW7t zJHnPWCS6d>ceXS6TWXeXF_);Km-q+RpcBVtv}eIZHJ*G}PsH!-lOY_U=vx!-J}9|u z6_;?9QrHxqZGP^?55M3!5?=CjE=yT3poM#tIRy)FZJ6_!yPHZILM_Bij?rh2(E2>e zzZTZf{6w<-BJQjEQee5A_VNt^<4akwJClUz&7*AAHB)=Ug#WgImhNjt!h^u+ED<zj zaX@Ji8{|kJ#-cx%jdc7}OB1V3ZQVER(z@*Kv@W9Ur22&q7qGpjLGZ5gkE7>BQn_SG z4KcBvxXw0Mzo9<Kbu|<dATGh_z(G_>7wGq3sTUL;w^r}iARWMf_Y3M@E;=wa2zYDE ze5?*k3MxM#1mG^-064ui<&9vk&^6(wK@&hN%5h~pq@xF1`6`bdi@d!_?1-$*dYO+H zFp7Gb4e+BHb^`?I$~KI_s<*js4L>;U^*z$q_Z)v!uhh&G>qtp`*RlAC%+qgZI%iLv z#>U32k<Awkvr}Ocdqj+G)O)}-kiK61xG~&*s88c3_rU$L-;<m^SzQXxKZw=LC~m#a zg{xS1`X*_EY&7OpI}{>EjEh}vurV>x%JDK3O`Dbqdq!vxw=8ODH%q-8&vFpnb^8ho zp~oQn+j++QZ*}u3Y6Wak?V&t^@<F7z?tF<8Pcw9H@cvOn7^qg2`?7?xC`RQ3QvZ;c zh(b4IB@Yg0;C_Pe9kH+(@|+tGvf{3R#mp`8_a&OSW;b~?nYmn!E1uynykdSui1V~2 zS;|RVeLPOZqM|?@)~O4b;2xn(btGQzc-6(oR=X0LcvSc%c+`h}uGB1s=6*AKDMc^U zg0}5#UZr06kAC$de%uVql=n`StzzWqQiS9F+sJLbU+R){c=V4H!UCTyMS`ha%-bfy zaEtF@;8pEaE70UK{W%LQf9W!6sD>}iVws256^Fsrj37CpF;q5hF<iRy*OKSh;gK^a zu(hdi-f1`{P>~{uvMbS1;Ve>UT43xqxO2*ZB5|d+;#km;xsuNBrC$}WN^-#u>Ibu` zp;cO3ej%RX9i{qw9`}O~9-L4-jwRTdgsq}tKNqaUX%G;*JNqvDK{*^%DK@$Tvy9QK zAj{{#hFwPQTZze`WIb0Yz1rzcd6!lW8FlWQ><kCwDW=m%@eYT5_0%3cO*VpD@|c4$ zpy9?0e;rThw)N2otIA<%d750TSo}5u>6DE-H<Y+(aOsy(VS^Mxy!b=<=e#!p`vBhr z{T_JAWv<=rQ=H{Oi7)Vi75zWkvv!Pbm6z{MUE>p=7*1)zVm~Md`vzJbz5PGFq}u5P zVjJzJ8rzWoO9uw2g&t_UB<yxHi8(bf1TDROc6Lro>MM&GbEb{mhTo;kysE($ctj`B z+h!S3*Z4#VE)&mj-#RY(e5mTXQNu#SBM~TX+a2omC%w}2472#4hy7yEb>QkmoD<cU z>~>B<+?#4`9K$pI^$anGPcvxzxhVcfopgJZOEm2EXPTZ+z0Yp)$r?ZFaHC-IiUnOZ z1VH)80E$bW31ONCZiQqpj3Zc*7wvWQl)HsA2`mm-yrE7~bRL$&E)z=gGd^kk=lCtw z^)|0<gDe*dN30VG2;4XF-3xO>5L7Jd%=ai+jXd2cd87yw<{re&gx01L8X=rpWfhEm z@0bLreMNIS&GfPseT>0la%NXE+FT7=)CQ3_@75B~Pq{pSx%h{$FP_OA-IgVIhzoC7 z#X%knCrONvcu<f{YV6;kbxT(a&Dfed)G$6a*%`%?=^hlW>D8AYI5kp26ow8v1BJy- zf2E2#DfRQSkkA&!ubTK~k%6RzlF$ysa_2tWqT(u{1`OE!R@U8_KQ$2m-*D}ud~mK{ z?&P5^BOZ%ExQobp*{(^=^lD8z;T)r*i7jR^_An+y$G^Fu16OjOqUgr7QPlF<#c@Yb zc0G64aIC~cRG$gM2vW87mT78%%aPG8C4nuitnFn7E0q228ru<Hh;+;$HK6ZlNJ^3n zm?Bf6gl{s$#)5d}S;3&m<g>XLb-qmlb@=ZG!$;J{A}NHgk76sxiuO)v<rU+cF}8o< zl-5`XY;)^2L$nIA@9ibRe1JYNHPAplD69k4)UM?{q#w?m-hcd|NbzauktO-);ymdE ztB*|kt<&7hPB>k?5{Ih9dRNfH@Yi>6ke;9jx4Xi?Y%#~)2bQ6>nZ9H|SK(<MSf%s= zV7qPhxZJ<YOX7~{dUQhKQ5h@0<wUFu$ult!Mu`3@%Y^!l(su`%hfFpK63rF`bl@So zHH82p339{x8RLn6$-nzKOURKc*eCj>94p?Msnp!pM;p(0MQ?^AJN=#kN{1shu_+X; z9vpGkg9hIn((*)~(yH>_Rl;izaYcCqp(RjvyMteNW7{%LLXxr*e<SyXG|PlF&aVxf z($&k8${|xO>K@MHX8SaxC>a~|l+Ru-))FL0!P^Z!9HGc{)n*Ut7E@ROD+S6;b1B91 zyoD0{jWy!t?ajgEhyo8;AOubF(H!68a0~~UuG9kZ5DQ$_i>tr&+fRtPQdnQ}=#vK5 zM+sJVc#~zKy8!o1)F}8b;8myDjlVH$40mG4n>zwePOT0jp7OWV<Tu+eXkfwaTETs2 zHck0hhj)WG0=r8Hm(m6tKbU~w5J$0KZBqb<v8Fotw+C0B;J@kCahudqLut-xIqtkg z6=pop{aDG5h!}p=w*ByF!T*Qlhz!#~`43$NDpO(V*{avr9mlAQ+=@HO%Oxsf_cO}Y zX`w;$_DMFKK4+8wY2a9K)r8h=PiSoR#DG}b?~Fko{m<c3*`M=ZI)j+~J+?9e7&hox zJXw~%*JeM?A4xNuE$B%nKsnL#?#g9-XDCN?Tj--!U@`-<4^?YvKsAfn^Za1>c14t^ zZMbJAnv5l`r+??BZXYK-sq~h8&MPB_cfuugTqx-*e-x&EP>`Ts%OC97=KN`EFa=zF z9h3ehaNstoV+6{2rwtPG?lq`iUr^yCiX_YiH$TTAf0<rNL;q{A<Plph=}o1u4FK8( z?s%G~KJ=P@(dy{-N1Q(o&+qtZMX40S9rwY^51bNsb4Igs1yf@9fTpBRyNq9n^hM#< zThGWYkB9r@+A)OBhHzpl5*=!yAn=)XjoOZhKe&&DPE@;qEe{<BUBKm`F%FzmqCaJ} zv7iKd`c$wFab9gC1wf1{<h)&qntZMa)ulh4w)*J#Q{5w9gIRXybE(o1UKRA|V;{m& zQ13E)1UFohBTb*ksYZl|X&<h$4<E0PK134wZ+Xx~lBEdsl;?(4EMvMNsbRUL$>N^m zi1{9;`~Dz0^7*}_+gctDh^1^cbU@znOOj9GCoJvAUMkwYEKR(5CCwLD7)>TCo%Od! z@=EbD*;UM#)>z7u>>_sIAJaJ_D&Qy#$G<VXKSUG9F``;d=2ey|)UyDEy?wR1$t|6( zh%TuX5R41s=AzN$4|_NvPD+B=Xqjv|61v1uhR7;e?3Nni;(Tq$q=gv<!IR^4_%Vde z2E!#2bOe&!J~=Gne;&j6X;M=Jk3?z_Omb4dT>oXirS?%ET`58Cs|SIa$eQssdjaC3 zTQsD7r4zR>Gn?3Pko8Z)rAM*mYXt#nw&(BEDO|1(dg|xFf!}U0W4_(gd{iF`$eOAP zxCiqJVFQNC3@SJf>8v6jJoA(aX9bz~itP=9B4_r$JfD;>*qE%L9!%mZ&}YJ8t4vcs zJ!5m;VL#>VAjt<xT(?3jAZFTm)mx}kbEy=m(UQpy5r*Ds6l0BD$3r<OM<6AMSSSX{ z*6?<`jaLXf(q6dHB@oi6#2-BRiepa>ac7pQc*Fu<rrS-T3wyQscETmW&y;6$(VY>z z_dJC^P>#ErF7quhBGHFnBuj4MMsaw!-#4Me)G+6G1n2M(qvq-Vj#=+LcE{yX2_zG4 zhws37ow&Ew4rpl>jCyUijr-|**keV4rG5STlaK>Ck=!&6dN)DaT-|=5_Nj_FQVu3c zZkFhVQ1v#ZuG5oDW8Xn!sOsC452A<3Q)?jv@8W{H-cbCmnvS#WTa>a&XYwE)Q3$!F z)*EFtR3%L2D_F8QnBZ06p`{{1=gDMFJMGp;>%0SxL6KvL_pfHB=<WW4zJ0!Ht0>(& z-%WLz6#?{i_@K*i&KgtQa8r?|Hvd@hF~;QzhVoc0T(DL-1!fmlmrlVrcTr7oiQe)i zP=1j~8Qy$-u()VYd|ZX;T{&EjO*Q5`{?u4*+JPCh)~1{zM#IvE<e(piFR5D--`-K8 z7#{e<%1~<zi?wt)>i5jVMDPl|);%g+q!yDU2Jb@pL-Eg*DgKgah)s(3L;~@jP(hgO z)LGL-CoA8GCTWT6zSrh=$)ftn-hPP;55Pf2GZav$t;xp?W4_=Hdlngr>7m6<QkHBH z>GObJ$asJR>_BHJnfLtQ2^1YJXeSwJu*#Er;i0baau|oQYDe6wU73Y|21QSiK7hSm zl$m(9-VOW1j5>=seOvh8Y4fm_=XC`ue-(2OX`oz04Iqn^z4P*L^UNe#(x~`)nAZ8t z$1({QK@M?)nhqVjJbqr@xQgh4SKy%+!#Ps%!L2J+BWCat;+(1VAj|A?6LgHxmkk30 z2H!aZZ=SVEqiVPP@#6hGQTLcaA6YXBq92Y0*EjGp11q1Rkx^poC?fHyD96&u(PtUR z>xp)hJr_0so{((w3vmf`oBcSe0_g>tF&5I7_&aDFIss#>AWh-z0A`{_RUc!#0&yY< zf(2R)yPN<T2=bny%W7MbyB1cC>K{Uks9;SNe6|F<Amh%w)Tufy<T>mr@wtNmVZT;p zsFE(dh@^haDNVniH<AqTySHhHv%xfQA*fvmV=D5Mf(NX?Vdz4w{DFl2qoOaWqFmkj zvtcD;g1?s0lWpO!U0`hkaIdDl=8)5w^Rw_{XHB3D?N}5#OX;;UD7()VwWE*I^96zN zk)mjyTMsa}@Gd2n)dv=bd#%_L(2sr)9Io(~|5P&&$;Y<xG|F0JxEf+icva?eT7z-r zWGz?N<*c5qyFigr2-|F8pe&!wz0S|z&Pnlt^nP_nWyPpn=M7h6#x*A{7|xcE&!xnt zc|a4GR6R&(@o#BZ@0f8cL_w6dS}F#bcRvbLX`Sq{lMxCqN`3?WQq;5K_ou<ACo^sk zzWFHYB^ueK#uUXrG6T)EjPrgeg@|-xZr~&VlZo6Fqw6kw)zTV2Ykf4Y!anbb5la?V zE#xk`nQp8W@4Ak}yC0nJ6Ia&b;bPuvz@iFxG4CT@=_jGBGTbJ9fmDc8N%t_k#X-7_ z{5fV4Sf50rPI!2%ZaOW|5g9)!2v4oiK@kS?EW{6vpaQArR^7My20X(7vr&rIOQf>3 zrhy<@N-akUL)$3(B~2BlKF;BM6j5Yu93r{K`I`KUonx#hLAR#2ZQHhO+qP}nwr$(C zZQJ(VXZvi-`Eu_}ZZbb+l1g<YwYq!NO8@9ot@S?1{6qkz<@5sZk`wpS=0VOpwW76I z(#8529?z7C=8J<i=?KEjN;zke4JH@vfJ#Uqf}}i{PqqQe6Rfro^0xHmGZVAIvPQxu z7Sg1KM2{PtVRx<7i5H#KZFfqq`~t@2yE)&4;)<IYabB^P-)<IqaI-DENg`Xr=I4fa zr?E6ji#K&BJKCjBm3H0Yk&w`Kix;6FcXP5%LF69Pq2!(VT-HVw@a(ucUUhcPgb%*_ zIgzopA9E*Qet%2mg(Tc0%*p2oS*C*bCv>!9q^%B}4Zm~uCav%p5{K$%xR{ZmUs*vw z_t=kpMh;xtXdX{6?=ZEJz^xuWpvx%Z*uA6Iwfw(NY2$vs)-Uyx#aAb4qAnnbrM~5r z(+BqC&zYfk2Ui5|wwAOW9i^ZSKyn7h<`-`pl)Fr$y?J?;oEwkuKGv|Y0joXO!Fy^z zGxv<}0_qv*wL8})_lmHbd-(~QbN}2M%7i|ViIiNqj3)GE#kOV0Gsjt_47W+nse)@* zdqyI%>wW5tiEH%KcT2g*Dk@|K7c+(pBul18^AX~pYVFxg<azE1ETp}*2s;No8kQ!{ zsHse8(qljuqy*o&f3_bFqv!*tUxeviQ`NzlaiH0mM%>FV<*eStfGfrMbfQivRCdlQ zWqL;F)%s+oBBxQ;Mmdcx721%gp-&@L>w7h5ifep$F|{47gj_({e2EPT+s92vSz@%1 z&E|4KuFPcbCk-~sV$eHZ6p4(uwbwX-GbG}y<<#VFv%)EP8dj#l(;0_uPlEQbkOw80 zkS1lRn?A{-r<YQW{XJNBBKQJ8ywM;qYZX?f_c>Bfk7YLe#GM<+p&It_?Hru6Y2JAX zG1*(y)_(7}{zO~B`?ZhU1j?UM%AHjL2vj8jr9IqVT8(5rbAt6fYCchaFXZ9v?;b5q zA*t)mbx9d?#eZe@J`U|p%2o^nCp<es-j9_1{G*{FXzDLPZ&&?0+mVxr2jNNG7f4-< z_iXiT68Ui=t8d73K}<8Butj~S)5n@neZ3%<erf&WVH7iaXTUIBnMmSy{d$epZeQnr zbLcjd?%Dr-JigkpTDYEM4$|2m9n>Q5F+`PkHG3M&a5R<Qe!*$%3ntfak@-*05j=d9 zi|*!Q;;ERpjdJWXW_J@;03HsR2TJoi#?ZEv#U<oS&<!MRme@>Cv)B}1HoIHEiZMl< zihlJ&rAM_ZhD;*1hxF~nRayguqWWqgEW}7rA!zoSXGTolp3V1*A)~R<ixR=u)^tq2 zC&?sQU}}NmkhECESxPi5Yyw(R+v$po56U|lmr5&o<8NwWR_*9N;9pJiz}X24X@w%c zwV#L40CXQN)2;WZI6<syA{1|bDWwYp<vEC=RTPWfHW+DMl}EphGw=2k8M(&*B~7KX ze|8_BwKx|RXZEo0K@?>vx~ehBU{=*q&IuI@CigsXxjELOn1VChw@Zj#XPA_nVw*cq z^{+4|`&m~6G3mZ4kQDFJrfqa12l1yGu(fh$F^aaPgkltX)#=PyYv=@)Yj^cR-_Q-X z<>tJ&aSuWK#7P0>T)@@WR0_%iD%$ju!N|@`)6<w|HpudN*i(R*F{5WUjLK!#oC+S= zTwxIeolec|gH$=Zpdt(dSH_DizDuT8jA<OS71$wUD0rhhcef51T5u>D#zGGy)_y}@ zln2_G&N;n8g1rUfdBaP*vPSAnsiE=NFaOU5g^Xn;jvBNuCfDaCKuN^4)x#-!FEFTd zviOR<aQxx$)M9dd*x?OPl<<P}-v*6O6&b3Iz3p?5%b>b3PE`*cy&}8(r<D~Q?fkyi zIRC<w=5=Od1>UM^*3vTnm3D{#&#$SZPAgwW&0+$YyFnLz_9JoJ&fw3~%*raBAW7<q zhd*a%aAKaQ*`>Ru#(9lg(~o*;3X0KvEr*+E+joizEH(Fb#EFcr=JBgrYB<iR<!}RZ zYgDeiOB?C&Uyl6zH(=e5!4Ec_XgkGo9@$ij=Yhr&QDh@V-5BFm+4=NA6z#plLj`<D z-zGx(2nLQaP%=&5S0*^oZfB!&d5_TqvtsXvjGdkaN!%@T=-1{)p{2IAT?boaRRMZp zT|2pr;yn;wvCw(!C50O5GnZqbeK@QLvAU!TJ<sVNH4fDYm<%XJRbtiKrkQ}#6VV^& z)}}`k;|DFiF+oq@CdJ6rmBQd{gkki}?3ei=j7{j)6Z6P(eeef=qVSe^Y~3|rTR=lh z!ua4p^0#0j;Z%u68Ch@E9sN?f64a_~sHxrD+E~)nm>4I#e8lGUHXwn21Mt<QUurMh zM_Zy&cOra#jwnN%*atm~oDnf{45LA=9~`3qmNdHC_>I-1%2b^)rirr(ypsqw4Q*1d z{g$DMR3!Twz?9HaCk7AvO2wkuHSks^CbZV^pf6phxB(k!ej!BgV}tX+rWCC1jspQ| z?rM9Y1RUM((*6_xJ5LugOOM8?I^6`=v3A>uUlipsI&k#gTXXLL(<AEmv>VW_0<J#? zoYjNW<#AIdu)~OmHL9HO*h57@cs2Xd#rqwk+<BSU@#j%RH@)uq0CYc$g~BIRVbmsy z;0yy}1ZB>JKO*W*8xAhQ;>ARKTkZWdn<sjj<P<G4P1|A(BaG^dpjS61?z^M*Y^LtT z#P5v8sNKY{hL$3~<5%^kFlPg7avJ>AqH|pl5<L>{?iQzHG0HsTo!U8zH_t-Jn+B4R zlG(F#X4~&V7Ju-AK44gx$EVyah>Ic<eKVBz3_4iIuBZ1SZqrmsRo3W9<D;3WsxO|Y zFUZ=FfRl8(1A{m75@6hHbnu`~S9RbjPC}->m;F&gPaZ62i8%>6>oy1S9Xdd20Cgyn zoAaR|nm6DK!mwVL?;}XohU4uuUL%bK=Vl{qQor?IgX~s8NWFC1rc<Avfl=p-T*V0p zu5rV#Y;Bd;s|?b5_dv7DE+}%k=_+O_ue6;PwokIjA(F5||5P*B=-NKbkS~Fll9}3M zLeD89CvoU3Nv0P%PxSq{Jk;vvw(&M+vN?_{%XwT`3euOKV%Ts(T<Q(U9$-jDb<%N6 z0ef{WAY~g!@H8&vcWSYt2UT-Ja|OV-;YMRO5^k&83>r!@6WfZcPMu|#*S-=hl4n4t z7<OXnpPTL4LzM^J&~kCK6;Ge<e;@j8`4otIJUVPJ;7B~NeLnqjHWZ-{z=83!af<rU zS+4bXSobcC72ps=#z|!a@Qg7e?V-v@#nE|sJSdmdDq;ph=MR84I1*@s$IAkY>)fJ2 zZt-T#bL&JQdj9l9s#^A815+G-51UF6kYKz_4#|dHi<ysYG;GTytsL$YBt<C|%-JCl zhk=zv&2e?`U<A68rD<=vrI%6%UodzX|3FawX%Y&yZEkQnC&dmIbd#jf_r5!RZff-j zv9*jE5I;a5kXTY~OU5ix_~N^FxMEiJku@I1*;^Q=Bt2v0$)9Cno7{4jlH<bl?)J)P z&3e*8XK}$-t41vt;TA6jhc_D$n9b)}o7X83aI)s_)2&;|MBOc2m=-1z#;;`m%@)7P z6HcJcL%yG!{UnvmxoE`|8z+1igIve+=8}fmcR=MuN?sr3ur5Auxb4GW%$A2TaH65; zf{iK}Rlj8Kt#DbAZgP`6tjhNs>rfIgTXsb6w9aArW`56+jAs3#gYS1!xg)8L%9{PN zp9|dd5Z@%F5(qMWp2>g71w95C%A#^`B#lug8EVBK$z{74HaXEI^F^@9xt;b2JTg+E zz6%v8&)5K$VwXZKwh_R}7^Y;~teAs4H7<<ubcEb88*5SL@=Z<WYRh+ICT}(07I)R? z)Uo*>Db5P7Pdq*&2_6xm&kS?x(Y~wv_VAkQnq6(R7K}vSxESxdPePmf;0l3Z#Airu zv6m#<gT$92p>&0Ygt|6s&vi~B58Rs6C$s$bIEY$jex&0mu%2xd;-oUGOXDv=EkuG@ zVp==-d|M)TmI<**?(+&eF{S&<h_tocrwMmUHr6&{D14}$fK79D!*aHt=!W_NiqIet z@$Hgga8^*7vepWK9gw=3{erqd@=2Pf9&n+@CE8V}LxQ5X%HOd3eD-I6)6PQWkSNaX z!6cp=OkIcr2h&bYx>`6mj}2)`l2#^(j<W%(3VD<Dw#M*|^M0%hPpr(-cl2(`8oLI+ zh;cQMFs{hzX4w(cQvziv)ZLY2yUS4y+gp?41^K<7jVR`!(sGx<Usb0}BWK6XwnC{z zM6@ql9}m*gspL<YZ))ks<!Uz}>-w%2MKo6$Qs?(lBQ}C<<K_d=29*4(XUySg5)Cpl z8)vV44xpQNNSgFfz7`uERfkAvE!M*wwVvg;i@&k9Iue$A`yPtFu^t_O@xSA&rPe-> zvm}P5WOx>9XdF<XDPpu{SLFuv>o~zks8FiH<V;c2q9fKUWM`($sR1OL;J3u#p1AoK zfLB;kNiUuktwdZ`YkC}#*8n*=%V20iFkh{3Q`=kLXK<k=Kx25Vb4*dh-Oo6|fqHM6 zNHk_z80Na|LeK$PnuA-R2^PH)NP;GVMM7&I%cF7Ru#RmeGF3OaheL}c%*l(2ALaS; z3c0CSg6wSFB*iQ!7vc#3KW4SB+`%YlI^t%m{2KWFQRFP)`(osW#^>H^#zHR))C++~ zkLY;seluoIYnACj#1@cP;cp!&vy{s7Mg)6h?bv#4-TTKX{9ai3sx$KSS7UvUB;t16 zY&gxWRtRLogdF~#HNUUQTBg6oSZU`MaMZ$&Z;0^43EjTE;=d&GlZ-JG7W|3r=JrhO zuL3{B*m~B5*lzL8*qedzy%r?v>D5FepM9cu58zsk0RfomZy=Z>j>ablV4?Nd!_)Q7 ziS~a9^TpfRy3V~TSn}IRMKDKsyJRF;?NztX1f`6P1fU?@aXId#CkM*CN)KeQsu_%a zBrCfP-@(!vNmu`jY-cowPPeFbS%O!-9NJpnmgW$#dajI*v>ak}7Mbu>LXzdy4rT09 zN~|p(BfBzFf?j=3DE9AU*VQ-gaSZxHS_k{Z%04`CeVL*C<I;gZ9Vf{Dv1UZ+5FBON zeO)&28$?)YpbkuL`;tuW<=Zik^O1xx*A>AxnQa^!l(ivXanW9;C=<wovcR4hv1nUH zkp0SKlQDSIxM>lHG4ePCCC+-fRgmbYthIefvR}1U7S%avkCh+*r6rj!=s+wFtoxEP z9bXTI1K^g%Z9Yq)?t1UkU9dCwshw8VKdRl2Y;Uoqn1%Eq=sazqBF}6a3Q)I7Ip-YA zp)K#+sZ*ALqoz@v-zy$Wfiu+$_3e;YGIWDyC5}IXjsQp9$4RdsW$uXf?Wq47<Zqdc z!Pcb<;N&n#TqEPn*EbAyubQ=^BFg?<WCM8KzIvV-FZ(uj7A)TNRc8Nu@Z8!;g;$KI zCJH|Ql|>FqO^uBKa4SxkDtN9BtcGGL&y`(u+CupPc&mPrX7-gP6%qj8kD><!k`Z`I zwzHdjfA>fDq_w;rSr&hBMuv*JxT2C_cT#2-ZMBgUP%HH>hOvRJgDbJ`3e0FcJ3lp_ zGFT<oQ3uV=sb=c~a8+H}#*Kv`b-|S8)P-13CjD4(|7h1mwv}w+{(_((%hOGB0z2V( zWRBv49$zMi&FlgEDDjePuzAg2ZX-}oC?5#__X!th!D68d@}wP<yKI8GOFL>U(s@)_ z1pvNJ>aN}j*`8nNg{O81#k<l4yI7H$qDg9sHbRu&a0Gm1P-$ZypH`_A{J+O+90?Z> zYfEGJpRh;<bQN#IjC?!3$7~`ydx7nH-y<)>J~?<|5oT<MVjq>g#L*lWEPZbFedRuq zdxI>PnBa`YHc3lgkt+3}Sn-a&Oog3n!~}Q%d4#Fv2(93Fp+Q^mf1q;fC9M5RbTLY< zn5Z%;1PB_f!&MWCW=(c6ZS5Y3_`=|ZQx?HLum|Lu{S-(t>R=@lN|nyVubm&81}eES z&hgsQex+2%RRO$!$T#h58@u2=ieH|?#?#F?NuB_nHNedv2b5C{U&=-9Xn((8>s)MB z$R4LmHZX9RFSKiI!Y(WlKgy~XyO@6|Nvr%KT6+%F(C&fC)g{bu78PBB%9>ihh#`AS z;x3DS9TW<OePx{D!or~YU_s!>5-<hRkA*xU(*uXfmsG#bTYU4)_gb|_ztc^*d1oW@ zUiq}V_cUJA-)sLEIyOo#AyF_P{L?0Q;Txebb26;!+^DS22kHwEBL84vS`C0O96e=3 z?hsb_8iTfUPar67i1&0TOH}prEv1zWcuCu+?$%GMN;Gyt;2^{ae<bJk^vz9^Z**1L z!b?7<CAD(rNW>&@_Y6+#7?lD1%xdt#HEeiDzbJ{IU9Wt)6K3F&|I8Zh5#KOCgzd!l z!=x)j?oL7lH=xAqdHi^dhAoBtZrUv*f0Qy*?Uu5O;w&0km}MgiSp-9mm*W+3bXd1d zdXMBT3wb`~1M2fsF<m&KovUS;c3-54&nPp|Fmv)u<})W+k&9vQ(f`XwNL2UW{pjXd zB7gv28Ji_&1)Gr@QnoXXSQWYxgNzA&RAS9?lDh?tes7^9YxBpfYZ+Xr>0Ie(#->c6 zuB?dtdC`I)6@OGE-w&(Vt4x+;($vNVL>TuI<P%YHOvS6z?+WwU&vbLwBvA(tJr>2p zn=z(mf}|hXxHrF*E3(U*$nky?hWpdbIu^7kl}j?Q;ww!P7&wL3w;})gkhpcazv=U{ zGN@*lN6G#*#;^kMZe1kwyj>ibrww4Y==6$WwgHyp3xRa`s`uUdVTLp(Cqaf%rPYw2 z-9?Y3El{-FVj33caXCi~aeyJv<GMqd3d^itRpTHiC5iK68HYBIeoX-QR3rvhF|bM! z1@ToKRV{<D$dfNtEQ&f>hwHlhC`QYCEm{f9+hOY|avD8JO$_Na_v*27@fG@8#gl!s z(Ie{VhMgDs`bvH1Dybp%;T5b%lJlqUxz0e$ttO0;w1zn%@?uiWB`ER}4*XB_XPQ)v zr@OzimnSxphrSQ%%aLTIAC7&ILL&0N|KRdZH*{DJCvNeRC=av!A~vP89+pjo>q+T9 zEVNk8(Cmgj%03S(I*5QlwG7r#6}w&wvj%3T75RU}9RahgXGUHE8}%S}_mlBX<JMI- zqk>m>b2}4PP_VoA5xm7V^VTd0658+3dCrECnJv(kY#QXhzw*8EQd8-Ss3z}(k)z!? zU2PDh;)EJ#c)Rc$9O84+6XMl}{lQJXU6f$JFqUaWNWDZ-bVzo2*j2q?+92_|?Sc)> z3<_g?YMTr!m{bgft!hI=i?n7r{VgWr9tcs7(P*SKCui!@(78y)p`)~D10N~lCrs)h zenu{6s-W%Bw^wg=J~0n?)Vk*4ZoM#_%}4dbPVL}u*Sj4WG(<fL*Rv)YYpa2<=g=u3 z#(V<nwLl$k1lTqmJeCwcPhj&2<Mxu?X+g?&ft6uzqRG?cEf8%!GV>y;E`aUVQNrkE z{6z72o;ny<$V|>Nw%iOiwaqi&Ktkkg(I+z&&MBv{gz&;~TUUtv#*suKW0v35GD>+W zFFud%Msq<IYvmv1PsdzZGh!hbIaYhqZ>3=0e;h=ccnP2FzEjhZY|wl=8#%ivc=0-* zo`Y={MTyxs<XWP;!Wg8JQM%Shz9gKf;dqORqnbv@t2sfC$2hSTYhgrpHd9ZxHe=8s z>S1RbSS(3V@Tm-nN4laV%wWsEtNJgd3*%`GAH!SUlJ6Mtm4S4{8bj<)f$+!QrM!IZ z+$G}2%GKDCGbDIAtpm=()X`%OU|S2qY(%x1b08t7EQ-$5Slk|K&`ucqh|aicuV2NX zbLQz=7w8FTfi)cBwXsbT6z}H9AlJ+YXfZJ1i(Gzm$phj)T#S#Z;rkSsO+06_D|}a_ zz$d`S;|o@wXhV?U<<f9Iwffu-5CoKFRR}8nrp{{o8GTTzK~wF1#WFh@TSWP~&Ab*O z0~-^iVq*I0YPT}CZyZq^)1>RtR|}fz1d@%T-eylF7P#+=Pqp3F4u!ldB_({Drh`tj z=9k?-7<#ai#i2OCq)-t4v%r+iWQS$uM}jA+oPtFrA%H2Z^I6Kl28IUtc5IKb#1+Cx zkM?t*!t_tz>|;2}*?en8DwozPC9Y;0mAyf986#dG^xsY&g7{)aXz2b;0$Onpo1-x0 zqXkl~LWW_uH;fjyr>72mR8Ul<oa+aVQpw+=oWw0|QA$XfX<(BREUUe(fFp*WwygJh zi#&y8#gxU|VElyYMo8YrnmTnOr$cCAz_mirRa$*R7WtUJxd8~A?3F6kiU`6S55+Ji zAkfDK`_>=DyBvr^$(nkRTH`^>W&-8zx*;m>k-#LmBQRO(r6$Ec@R`lLOkDZBj}l3Q zsYDe-Z8`OBfb8uAuhLhaHC-iw?h-8Xl?Whj;%$sN>8_#AW5%0a1unRC0&|t`wj8<4 zmqTT|d0kopW1Oan1Tkk!MD4;j1z~=&9?33@s+GL<e_8V|<Zka?RC>5+Nb8x>HDKcM zTQszx!2oUW3ZJpoxXD+JPqBp*T8dcDfIiI590q(NWLWLPGoT!;0*@n`E`*NS0|=CX zk@O@nl8hal-U%MZGS>ugflG1}%+@~*xqDjHI69-pMxai3u2>QMMhCqhM-?QX&?wR5 zUExv%a$~j(b+@j4`bT29DmHT*d)vR3aPuqTnGqQ;pZ>xtpNHr=C`DNv2`=!<Kyu>t zaj4$`o|lBIe4p7M-Lo%To`ZgJV497*XbV#c`&D$TwGh){oPGbrH{(LDvkK;t;;2wL z=vx67eCmw8!prKd%h6E&j_ZHvlxYd!mRC(glR&6Wwv2eXP6jmhxsKjnD!6aPXL zg_It|`gvU>QT6Ag2`ht#rETQ55o;wcWkhoq8^9!ET$>yL8!Q7|P9)xEfimvnJw6!A z&vAs|^FjP6g((tlvgeZwP><0^>Y)0p1vb7<{zQ-Yt&erKs0lgDvbAxSyK%8`x7lv9 zEgnYx*Z-$o`OKf}E&e5TyHyQVeHfezSghcWtM883O56p?<$|D#Nm-&0Df7oeo+0yd zYqdJgM`XT{kBr)m?qvpo@;{doo-<(SdTd?OK7teL+2ji-7CV;d(Rk$}N7AyHl}=uf zi7QK~!IsFYDsQMz{mGla+Em}%ebC&bZj9Q<25o*iW7|H{B(%#a26BRtPncaWF-@`} z+Ts@qac~3Dm`R~&1*|UR*`spOsK;K={S)WDO8!3935v_Dkzsv$9WeM+C~LCM%9uKn zWj3b(U;n68&fYxuTY&>dJtXU7tG5xT98#@Qvx0#*ZD`Ux<j9YIH@mG@wT|KRB1#qB z)>}Dqmv4-_=DY%T5L8sBpS&LQ2sNjXp*j0)`j;G@yl_>dtzm;>^o766sUjJk$BnR5 z&}w4W4YrFNwC>wf(l)Y<gT06+<JsUQGpaRh$OeyRzk_)#5J`7ik*!_<w;NBlAwdu$ zyD)GZfBX#*%H307=hpgZPYFV3mR<Rfmd)M;B>}xQ*=1<#WqWT=p!SSfb)N3|`U+%~ zz<uWcBaqe@3xg2Z6mC;+ykb~K33SBqDob_>y19;3t2OwTb0$*Ij9x&$X_c{UHTw>e zg<l_l2UEjxaM$=Bd;_etoSfkzi{4G9RrY9qXB-u_cImbBy1u&YH0~T1)M@-qSF#~^ z*}QUbqjNHKzOqCSvQ*MvHjMdACmcl5y(pSsDxG0{rnJXDvLMfVy42dRYo<y6JGhfw z$bS=q--)9XQK+Q5ur>8cG!S|KTKpiA{V<9TWU+!49f4*tF`y?)u>m}i_b5|X4e4Hv zbks>UaRNem>-fMgb6dZSI)RTndYN+-6gYl-MpvE>OxVt%EiFQfrQr9|4O1P#iYr>? zJ{Fr*<BY-&koGR$zINPLv-Z?}U5cJOPP!L0F*y>sTwJU-=c3LO>8t|G)uPEOA;IZ0 z<I{nP;@tBa@G)QedHxT{+&S6g_XhO`{b|!gxmEc}_mbCSskrbbLZFEIUb*TzB>`uk z+XFb{zhm))yF}EGIM{@i+ZEBPk?zJbfee}KYGtnZ5Ze2~bIt|!&po`@O;_OhO%nA# zMy2Wz)6s8M-%lLB)*dS3#WYg>?UAb|<(L``*#XI_SWKe;uIwHP9~-3V=sc;~aR8q; zdHge3PtWRj*A8+PpLS3?a%fR=lB~XXkNCcKy)I&HBLvfUO^SaXE$>>Yi%(%rTw7u5 zHA6SUY$8sEylx59!P&I*S+-<UA#>vd#{+Mq^DaLW+7?kju|QO1o-K0O-@YV3iIxBi zmzvkf>RPbaCL~#IhDQd)(I8U~RV7*Dan&okvsPi&3X1rD`U@^=%$0X9nHiZO&)0y2 zj@}?AwH&wEwR_lVt!>ZV;=WSwB_b|7_q%TnE?kyk_wLm{zx(!06<wUss#;Razd9pY zNG%5ZX&|q~=qdAY8a$so3pba1O5p%}?B1z^VDIP|bd(96>~fqLy6dQPplG>GuRES| zB|@2m`EJv=s)O@|ed!EjWFlB;S}UM1v*L;L`eki3%UqNpG+beqmsiQw_nd$id;+nf zrNnr(rL*t)F@i{T==}gw&+x*nht)^&7Y^qnVXGKQcbfz*;>t%a&^LGHMQ_VfO;DGl z5JBWBrpNk0_?>dj?-Mz-iNk|+aH5+fuv7w6;|i4Cykkuar<NqhbP~vX5Cso@RLp1G zF-q_0fFu=jgH!f{S9lyZ=NhR!QNJHc-VR_(#5RE&$Apk48aC4(bUz}lD)+z?+HVN( z)@^17O`AmL2Xm+k{0w8%W8lc+59D`Ab<^4GvKfELbcfi}FTkE6DeA4*ZRz^X{I_S; z6MR9foRFd7@mQL}tz+i??Zrd|AK?H-2u(XZPikOac2u!|bydW{%>%JZXElVI1S{w< zlcqJdxr#{T>;WIfIMN_F<iyDgmmAOt*_*j<ZZ}-#6n++fdV~0)QB;^C+jfy4brI;3 zd;h|`ZI6(p^qy2{qnKIA=GFCOW7m^Lh{MPCMYw_eEnnKZh1deh1l27@e3=q7_Hsu< z1kplU4UID3+W~Z{?R%9%!f*s@x_e|ThQa3%@MOSvd2mrZRyAT~I7})nJr2_w?TCO( zb}$@q49idM=&_~u&yrwfJ^#T}`RH8K-`Agih%#Xy24J#m=PUsOFK$2FUCe^W(<Aod ztqSPrgdRg7qOQ||M1N2d27788y0WR+zZq4%$ymKJzWfasUrNlra8$M99~7rx&jwpL z`$g=PIa$HB*G*+FX9O-%NR`jgM@&TfDrm5h(qhT$3|J)!e_&$8HzSjvj;Z>PX6=6_ zficf6=4yKUSIk0@(LC@{f@UX{d8Pd(bUs`&NejHXeV<{7-Ea{TR6~?Rkq9C3FELmq zpF704|9$t~Rq3O&U;awXgx4@ug9a-rvokXNyEwMCjb|xj8ZuIR=W^2DQ1b*iqc*LL zPuBy@_q}s~AlK$tyA=BywC*vs7)e3!d+%t4DHYw@$SKW$2(LT{kuHs7F;IW+!+d4X z)-=nj=)q*KgG<`oZ&WVPx?KWZZ3;I{&8ex|u1@eT0=*myID1y^;5AG$C5CaKPizd( zGtPCX47&MU6ATX+<5EJ&R_u@wX;~E3^;?+P{L&;(cD-sNd=uTeWr{h<Y)svmh`*;r zK;X#u$oCep1|M`Gy@y|<Q5X+EPE#)|%^qW8`A$1h1_ZYwj)2m6h$NVPrxfik%85Nn zhKc@D|L6BZh}nG$c{46E*gXp+HZbey4pG2gc^CJ8$QpwN^rVCDh^#{#?v0}k*bMfa z7WmgT_qa>n%^cKJXV3M7#)$Xb+P!xdUedawSF5%%WrbOqk3<#KKRV?yv=jKMbCRh2 z#cfh@eN@n^dBs#Ct)xb%R79~@^>*4f&?F0sL}?mCWzCo6Va!48@#+3cuJo#he^S)_ z{(2quzjtuIXyY@R^&)$aL%N9K)?A<0KUPDeqXHUkc+<+=dq=}O7Fa0*gNapf2V3AR zbk12-8b-k$gevSU{q$0YAx3Sw!+UU)uwQ$xJ%)p<mQwXcRYKK*FjY*(BKYw5Zs<YZ zsX}WJ8FN}hy~Cb!3+ONi>K{>6Iz9wq(RG5WKoxDw`a_(53aHaN0fV?D*1X;!cmyG= zKIgB-POKIY(m!^Cn-<{2QFbM1Uih(=2}=0|2s*>h*+pu0&xTjZ8HQ{tABJAve0VwY zvQp2H8GX6T&8Hm`Cw9=T$L3C1miI0u{3%r+?(B)yHGtPxu5evD;`Y?v(3+#cJm`N~ zS)ZUnIjQveGmSqn;ur8tmKni~CeBO~G|ig`B#5*Q!LMLH4zudVU!QjXF<?J?t@?KJ z<*0hJ`7L<Hq%jFKxJg;YzRCC@y8T-ay79DwRwvQx0C3+xJ>sdrwcOdb0hB1Xy`Utz zW{I3~z<fXx6)fobgN^FDmNN2VslXRMgnn8c3?FqlpVPjUn>^gn9{1dAy-!~3-7|Kc zuwbuU-LDYHCkOv5*MaD09E0Q9R$Z6FH)w=ssp%+krVhxIJdsRIAOXVxgK^yW^^cEH zSr!>+d+_nWTe>uIwaP8@{uyQ6pS8QK<3Kyq$T)Mw`nr9W8V45Z_9!g23NE_5@a2h6 z8WJ|A5w7OwYn%37dTD5HyQpa4df7mqR(28RQ_y@3Fidt%yAZ-2MV9i63B|LRFs**% z#7ExB$c0HGFYc&pKbAIvu)YJLSa%2j-)WBep73>reSFSOGdzbU8e0`>fK9i@AhPJq zyn`&snHEtz@mV9RHGcdj_e>L)H>rlt-(fv!4ROl#qdOBdY^^uVF*k>Wb;AM9*QyV` z;I1kx-+(Z~iTN9rI9aZ$@lfuLUq2+gwhN3NiLU#m-nsrl_D(0#EE*}%tY1jlz<6r6 z^6YiA%0inl^Bh+fr|R6QBl@wViDG8&*CAHe<!`jc9Blo-u}8|5Mz1)W?tN*tg3h_@ z&93?4f%W)bijZHk9n>lIVfNNS44|q0lEje5`qN0vLmqgE$Lalk13#JDJqrb*KfUpX z)~u>(MVNy|fYxtdcT!1{*k>5Gtu!axI9QIW#+onX%Z@_En%%UMYCo@FD*+&=N>W;* zgrp_dEc>e5YnGgH3RJO&KKy+Oy=620Q}39e<z<GDS*C<*#|y9yZ_%uLgI6AFNXM$* zl06S3C}S<4VDOoLd(~4h|9bh2dcgq+O@*?KiX=E!{%~SlW6{E{O&!?#g}06hD*AI3 zj@QI6=sMW&cfX|_iDeuKUb~{l`+fxrb8~I;cC)a}pIxXHVl7rus+BT!g16X$YD*!f zK+;5&ZI-p5nY7Jz+gk|bv6kgXEs?k9Z;=$5KO7G@Tjv|%UT&7XAKEd$6l-Zi-3yk+ z_!JpS%0q5i9HA}nf`!h5*G{DBh`B-kpq2(e-c~1t8P#O`2CXC4C5cFPJP;;tk8Owv zeG~tyqupAc8d}xA%sS|ol!wT@V=|Q2tO;UnY6$aE7ye_f&0&H5Oh`w11pjQOfZTGp zbi<?Pn^^XzzY;@v78|kO<)J#uQLopAucn-byqwV`b*#xvR)^Uop?Dp~g5l~?5xmx% z4)=(1ina9{q;DgaTHGUh6C5<s=s`Xnk<S6N^>XgDeAZ#vrqC+^;cim2OU+*ihXS_0 zbI-D@pfM(5mR<5y9bjhse8Ixof!h~RBi`g%2R{L(UIJq<#VbS$AcJt{!ByDRyh~C> zJd8me{@t<CD^i!g>=Pdh$eytt%%koiD?i+RA2oYXbF<qI2zXu6sNVv~0v7pGMZq`t zs}crV&=lP}=4hULJ9zm46Xj7+>4G=}2*ZL=CFnaN2}#?l0ka3Mrhw||ZefhH+M9)E zb+ktpbZ<VPAayLBri2s3-5aG0u#dDW40txRw#{yD#COXBB)(>YU?wRPTryQ)K2B4r zyI$YpPY9JZoT-ts9Dui3`PF__cpHP?%SBLRMdSXN>?WT46&ccNH+kVxAipOhC$h<< zmZljBSP)YI5YUi#e^Arjn60WRVr!h77osE8_b$8xy!<SAP5*($p9&L2Z`;+Ud#%fe z4xeXyL0v<)<p}t*&kv&SUMymvl=v)7RLRVXkm}3e8;Kj&A~;6L7JD=yHL=9)-=yEQ zEJ>IHPU^uiMHeH$P6=l@DGYKB*WG5~F5>)nvInN8Lw>z(X07il1ti;;=T|_wE%bL8 z=N~ixDh!ML8wG8a_JWJBtW~{XI=<zrj%5EA;NM*hYg_cuIA`s;+Q9fyX+d$9b0}DD z&qI4`PU*K$5^mm0<P3Mnk~1@)H;IUaHmQkys0Cgl|6sk#mA8%=lH_O2l9qgkEay-* z&p88I_+hXMi|P`;;h+f|S+Kvqxq9k5Z^r~C!hA9FbPw?LdGCU<AxB*`qq4LlRp;e* zl}}Hh!^YBOiTMtY;2|6T#Ap_D#5($wMLV3J$3Qmh$BaEf`D2>yLHfKl$BIxc?Lqn* zXt>NcVSU8Fx>TxCLLTBgAj(spPpoLviL=`6SvJ@SF--kSb0c`x``j-k^=Js_nNG^h zTSrqOVzXS3Ls9pHdS*lI=mkLzlfk3yspQ^}-6{)`?}?%|{<tdSp(pZI6clMqHM>a! zkO}X?^qTMW4bp9g5D1+3rnpN`p8k#Pc7&Uql^6(sj`BQ<t};;QyFr0AHj0F4#eicD zLo1X!ta>Lp@sDoPN(`C1%((K+Lu~`a1wIRp13sSJV&i^XCmpF!feZN!ha$@sn7H9C z=e(yA4-}wq#W{(Zf@*7a+<pZ6oe8O^BgT<@<DKsb5<7UigCFrsPN)rm!sQ@IMk-Yb zn&vK^0bgdRHs0h{f>MIdKz}GMKBwW9-Gz!~sg(fXh7jvw%wI(=_|v!`8L+8|a+*;n z{lE#<4LM^#4TrqB<x_g<c6Mft&ic?;)X%V7#dym2^}reXi`g>Vil&T1g6$^93&gs& zxv~U*K~yDb@mVh?B0_iyVxj4LTMNxX6QB=dKHou&uwuAg8=n=L0_Ob?Qt@I^u(L~h zkV~Ou^S%EMglJNygMoI3(i+1iX<K3n_d%ERr>RFak7b1_YVQE?f}<dlt2SsM<zW); zpNMtcEL$|pj2!WnALs+U6V7E5GRgU}C)Z|ce^|y}ue^goX4MaKXaJ>d*U~3A)!ELP zo|2&PHL4~!Isr5x=7Dqq;ZG{e7Be19g3aLNYh|H$LGOH%suc0a!h%7&1u+?h<z-X) zbR%#JYvmYW&C05frCt8d@ttZq%Kni@tL<h%T4k;j+QXjtr;M!mx^!1bw_iOvk-7=v z!<d?;%PFf=JFH)7x6B>=hM{&!FJrEGL#J#Vgl69PDK~-jw}V-Oe~=L!bCXJq&}Tu1 zKM;Y|h~FQ2K|);CfC0lZ(`?kI6_OP^g%k8jL<XEslHgxW#3bS@l+slbjD53gR(?E_ zS@5zlUhrbmNR7H}*_{Dok)h%_=)q$+N$Jse!aXw&S{5ZB4#@3>prr`pJ)<!hTfIwS z?ZNN|xI{62#x~Oa@EEEv{HNXqI0@UTwd~{V$IJ?vd#&9E@iqj8VqvoCmAe7CN3EEB z!OvL(_vt(}q~kibP!96W@uUM%luCFMNyH+%6GGgprnVjnsdfe?91W2D`I;5dP@ATQ zI@NeiK302S>=Oz`59Ayw6D0Bk)<4{<voIi*CC+UfQgH4*n{jKhy#2n189n7xPG7<; zKo=1lU3)7Gi=W6vNU|fw=BJl^e3}u#(Z}J#dtMQ0G}(s)I^014?$u?`SGU11;z8cX zlHDa$e`IqQo%Wg1)GBSWE<VLulshL<<v{~%sUv@ezHK6-aqu7FA$(2+K_(wk(>QmT z#sUP#i%*DsOgW0nB+K8%NIz^#BH}Ae;v&F1IwUSNzi1p^s&c`2)qv8NM3`uplQBWz zzL+lKn$kXx3;LXXzG;WA8I#|s6GC|5rdB?KtUa5atL$h4^57h1iXb&=hbWR8AXI{c zMi;711!{w9&c1ot@|WMoW9s2tTEh>}sqp6}u0IRg0-JTz5Am0JUIk<e^P=BFFYq2N z6qNzeGNwK{%qoW|88!f^_7q*9ud|F!@OVw|a?(nBR>1zHmBGBu2TpFYO~V}=GP|ZH zt5oX&i<iXN3}GHKB0K#El6=O_vR`UxIE9de>y7?I_SxsIb3Ze`{Ry2ZMQ8bax@YA* z(w;UUjawenLL2E0B6VH`4M;TgQGI!SV={_P=(cTDEb#dn{Nn*BoXKRRV{@^&3cy}Q zcuVpPBIWk_HrvJ(REx-_^w+3DCDt$xC~^h%t}~MJ???|)S0%*cRYpHJ`eB}OAA_gf zWzJWQn?C_o0fE?T#F|{>FDjnmJ?cy$B%+dFrRl%KvL73bU?g8UxNC)o5BKx*<p#Sw z^}VR_&jC}=<pyZ7hx2i^PkO6}R_to2cD_UmoQ(EKL}73H6;#<3tG2P5{o!~bCeUf! z{`&IW#C$;DQ33Cv*#e1Ad4o$*do(#4s!ojO>He3Zn1XfRpMSu$N+6Tr7LcI1^rJ$* zGHiZBnsQ@#tGsgK9Ppp5&3xYaldl8LINYBL+cTg*`^hZlj762JFrp%;)vz9FK~4`k z9PCs2Ym*-5wkgL|HXBVg_Z$iNXMtJx&j9Q%(4$fX#QL+TO_s{vM`Z%*R|AZ&B&R0d zhemT{TS8zuDmu_ydBIhKo|&3g-pfL=CLil;a*M_)X{N-`1u0dMI#LgmbcLPIpVIp9 z+Jf6>FYU?$<W8#gu~<N@KYV{vx4d_PBGGJ<<&Z5Y{n>^Ggr{owNM4;E7~$e`a`aP1 z)X#^LC#D$)*0Q9sd#Ad>)%v{K+aac`k=E-P7?Yly%Z*hEGdQ6sB-jtyj?lS@VCp=6 zL$>-pFVoAN8HpUg9=t~kn()*Rwm`}oz6(s)rV0fVC|+6}e@-lX#HuO!0R4D8+zwg} zG+%;Hw(^3;_V&82>LXm{dm#1M)<3wp#_#4$ZmeXC$g=2voYux&>7f|rs$<~GGSqAs za*`rWL^v*74;Zne&wlXq&!I3hwKJA7*eLNa9MNN@wMNzY7iLUR;PO^9K2jUANV*Q) zF@yF6&rdB7>~rI`>*1SzgEEv=*0m$#qX!QFVtVf!XJyRQK)U}xGq(o60Ega-Ya?XJ zHv5tG9$?W=#T)RZ;+GrTVa<JzVv$c5(0G=`U1qCf7NlWHcODEE85iBNwNuZV+5A~# z*To$s7JZrXn$V|?7b1`Xoh?N#<Ec6N9fT?J2!|SjMD!#JjAVimSo8VG1yT!&Y2D^) z1EuO5sLuKGd!G*ODfY9va~_71!=s(gR0LUCWfL&~iO0+t^iHK29@E)JqY()m^)iY+ zF~M~5#ZN};$1(EVDPd2&$;wLVxWDt<<|HK=ED+jr;~~n_m(OY*<FnX(zrxU$L>x=z zF`%1)@WUdCSa_=&A@TEr!%D$dBKus8siGy0WKM9mqwKm|D^dfMhVnGs;dJs&+c|+B zXG@kPMB1|4D;7%t+GA{ef{5k`#_j`Q|IAO+Al2+y!BYCY4k@I2Q62$2DBDJIcRK-F zHEJR6ux)fYDXMk=ou(McWs_!2UQ`csbD?&Yqf5jkw94$jHnRJxyxdFZ#HOFf*m>ea zDnBDAc1W?&KMZ7rv6?^Rh#sr35yK3}aLnv(I1T));>O0z&6hL{$T7)f7k{kvGrqJH z&S4pZ<(RtD=&vZni!w}>P19jWSaRc{iJ;hB4mrZtaF$y<C@z-CkCeOhqT0ZutnN$9 z1M786vo&ZFISd3zoXizGG!c7N4~Q)F`LQXOq$IM;b)IWCc?v{)1zq9R%LrK7>!Y$d zx^;DQL!{kfM7H1Zv&dIR#L>F!FwCQFC^RT9=DUQpGehq^x_!fyOIzC)yBrVyIa=Yd z7Fy07i_mVK)c6492id?|NT1kCtfb+>KK%wP3JI417n1^f*?{=K7ym-%!|R;MqrDsg z^)hUL`z0eB=$W^lHYw54B32rWwS!QPXLx#}|Cv&<VChbD7!@X_=zKM)6((@gjWk_b z6~W?aGOr@R?yi&Gf-kR8ggWPST^t*>tnE&5dg<SWTET-sv>)4Oqg_44Fv%p5Hu=4) zN(x%PKnkMVE~>__EW>v52+@yHKF-@7Cf?H}M!o(aYJes6lTuCik>Gmei`I(Erq4Gj z&;&0!G?mGr2|C9>a9U)mfqsJwgeEu@${sMuX|aMv27}oai$%l0JHz2KiJw8w8<l=& zfu^+wD85-<6wJXSYEDDy*En3H#SA{Hd%?jDi9cys%IvUX)51{hZ6E=$Mb}E^<XcGH zQ9WNub(#(b5A%8Y-l&X^6ql*1zDD*sw|pxLVjSNIs@2NwAAw{eqVoHlTk`w}qH4*0 z*BZdBWxw@k@!g$1n2$zp9n(3)B5tHS&h=}Mp)NjeLTj*!P89EF>;gx%EOs8J&cAF1 z?;8{2faH(DJ&o!42DH!ax;vS4i9~DwA3MkyoZWDm;sZEQwR=b>Z^(6WQet=Mo5T)# z3CC5{1xB%OR#pz;{k#yLV_tyW_0yI@C%mOTQ)`WR*LP|1iwg9>pKKsYAGjrbd=e-p zRd0l*zp9{7j;@waJdnC9KRZSo`;m<7wbIN?V5tnTC2%|4weM99B@|L%^(LQ+FS&^% z&I23=NqrPQj+PG-!e3cyDXmf<NuWF5mFz8k2_v+{C>vi2u<aE#4n^OBH_g^B>sL%m zRSA82+l}X2?<XTJ+YC}ZBaiZhP+tGDRel(5>fi%HZaMM<Obsx*csn?N-+qbRL)@_` zQUImjUt2a!GH~o?PG}gQx{K!(5UcV@Z9mqZ*{7k}<aI92M!Lb@U86e?!bW|hw9ooL zlhPK-bVjmV0&>Zr2||Ab9%R%dWU$YK>k{Fe`WxvA<{m9DA@j#ZdSIek&686N_eZ_h z+$7o2U$c-;s>z%OhJu1X*``0lWahTMMM{-9aDL?S?~OmH-gFU6{$dVUc8O1sIw%U= z-`VluJr=&YOr&xEJ-Fq(<r8w!KdyC>lIw400HLB`0~qL)Uu_Xxgj^*y&8iwBVu0n9 zp2RFDv9!m0LJOUS+5GZXarr{Ye=vGG5c>{5T$NLYvCP^T^I?IN@ifZaxgRTZi%4O1 zZj(LRApjWZkLuo(6bW&1C(wLlcG7y4NvdP0<~#6vGAmbbd6~uv?f?hKb6Pf|hrkcu zo$LwG=mUj)`}!)to6Wv?f1vLb^U`a4Vvi%Jqj<w7M61ycz#j418n`RRf7&pWdcS^Y z22&PVrq0x|Wv<B8x{W-pv{_5|n9JVZTfO2z@w#z_Dkv!S&*lylvB1O_FCUVNMfxZC z@+2$jr2|k>w;qmNeHg~m>Qh>Drg-h~&Q;9529{AY4Mgp1Ns;t!^zW$2qeB!<#K9+} zDA?_SH^k=~7ICY!Whh1!34y0Dq6Aa7r1r7^Ey}oLXQy8dKL1iwnjqfDeTH`vt%}p= zArEHSPJWt^ic^%Zpu&BK+kll@x~-#Hv<ZH|%3UzOq_Ay;L@UB?-3i~4<Zq&VuBH6o zyQA}W?GBl?Yc>fBqny5kx107c7A#d3>FB+ZncqHmc0J#kS0461rH@%S4ewc!C?os@ z*2qDR{PA7ZyLBE-HpSqJASFCblpXH`oRF?hOj#tVcCaa0vBjc}>P*xU8*J{^MO6Uc zzOhsJ()RR#L$6<t0Nd~7UQFA%kgA<UCsEmA3?}0GKD+KpsgeDdbteVXs}{w8>Bg0s zYZAs5M_ILbL|&6mxqN;f^lR`&gx$rDabm*GsOBXWEUt>*O<6(lUr5Geao#O_ezVyz zU^zFTJp+OF?i##sw&wf`s97JHdC4AnBxKaz8{2B5hhXH|C2qIh^F)HQd?B=Zg@|~c zUVOpL00j4HNw^1Z8*y<VCH}jS8t_5#xX}^2r5rr&qf~lHgxFt8C6GiAVtgdsXV_ya zaNMeHk-<toiF-Z*f+)wlM{PwwT#IE%u5P@*!X3A4rm>wT;}XT}xx>9AI3{$6@uZ#Y zlVO3E{L29B5H;wAtY+Z{jS)LsQ%VtzrWR^f(z+|WfR#+fOFAm0p#ysI5QR1ntCN}a zL%mMm=-oXk1^X6%I}llMn%AN~FK8(xxM$=C(KT;KK=zV4h~E7O;O^^kx8bpRV_L3u zKsVELmD@l`D3^E8#7(4>q4NAu;3QR(c-(f9s_a@1?=`n!X<G)!kZ?iUy}Z&N0INxp z^i5eJe81cqpIoLzQ7bFXfM=Zo3GFYf!)2XfiySL8(_X+VTrV$kQngCPhejIFn7Ad! zhXIS-x+1PuXWa)Ec==2F1GhRXR5;+yEO1>0^}VQHAa;W7-pVqpLb4+B0=agbyxT!9 zy>cj&kr>=V8znftWLOC;i4c<41c_!T!ZqZkn{6@x>%l@I!QK6;fJ%T>#0VxpB)00; z{Xk}Lx1tvvST805F^{XpBo`-`4u-&3Gm&PS%*%~QgVG_xeXeB+vBbi(KUZKzwGeKI z@WH;>X-wbxh00Vs_3s<JoRR~!!wbeWt>m$mNB1AKAEk__z$Pa~Iv!aA^S4svV(T)^ zHEi?@WnEe8-mT!krmVY8BC#ZArB~lZFH%LAaZH$*9!mTCd;-zr*|}`>Vcd`FilV<L zwIr-z1MAc^IbZeY_TiO+B2CV!<xH-FwAkhV+tJ>Q=*KGE7fC~(kc3s;Lnw%cpdJ;Z zm1QiXDp0kAGv`#hG0P(-fLo-U{NwZ#|DLV%klFw5kVT!GFa7d#wNL>ZJ4CbQ;))%4 zjWZ0eUn6ZF$jPtk8Y1pNF)JfQ6tg1LZeoQyUWeUs7f}h^;oQ4~(ig973S|o36zVCV z@{!pA|MkA!p6z6|pPn}Ad;~#8;6nCLGLEEgdItC4iYoYZZ^_}%WSZ!D)n6+*>*GCw z-7c<80egu{$T^{8RIJyftBuXSRHn$JD`znLXuH>O;h<pn;d+Lo5aURe_s?H41VLmk z*TcEM%oMHmyT+EkllU;j2j3`uX;On!xXB*=^M8+`JgyZ47{)NA^iRbBEa{B$Q}SSu z$JNp92jtm&j;+S>@aKR$?kT^XF8A5MC70jf*)z@~>vslIszoL^YCf7rh7a-Ql|&A# zA|6i!2YP)6FP{Ub&pjXP1Oi7yCi%+cWJQG7MhwZK8Yqda(_-H5Ms$!(7!3GCRC0L^ zlb=Hwwy?DaY{a`R%UOBj6iCzBqw84ja!)?T15=bCX51b=hJOKZ3;X8&Z`2Gs$Nxah z2)eph*gH{B(yLgy*qHviD!Uq4nHszN8wvm8)42SblQC2=)gW-Ubg>|?@N_VBaxyg| za4<BsHZ(V-q*rjVH*qyKb)s-EG5cpm%Sgw<K*z{TNiS{c>2B|2;!Hsa^<Pi2w6_!a z$D|>k5aD8CU}RxnW%`%iz{JeJM$N!P&cHza&ra6f<o{)&;$-OHU~2LYaARoWYzjrM zpdzY4C+2EnV`OM&_YZtSp<-d_Oz^M$mp?QFYNk%k|6WbNOvlK=$jZsYM$1IU^1t2u zXZ~+#GL~+p1pj<uq8BkWvNW`#B(Qccbg^(YH6(ER@4MOP80i=&|B-YE{+rjs^gm*# z@-Hd`^zuel$}YB0^l}7j9RK0)I61ozurmH1U=INkD+}9y7(M?#l%89yZ6|DYB;RxO z1KZhMB*qS4)jE~Q##D;FN|VjWu{B`XSW-KRxHKHj#(qC}U||H|D5hIkQ~frno59k> z^yOH*nHZ4j3_~e~=@1qg2E&D_jOQT8P{_#;vngsaoMj8B`4&bQsIp#MiOHD%)!2Ck z!@+KG98uPaScxuS5rky1>asekgk=#eM2ot5XZ0Q>TC_#<=p{st72P5Uu}Y#QL2$L@ z6)&>kdhh$?&fGh5@3-@u`OiEb&YYRwnKRGxr|Pg300=<dEI`@w{EM#sN)gm<Zvv}I za6d4bDy1-bpj;6nuuV--D@<dT2Lg|;p}}O`4pfM#TH#^I2S)v3)u8-5n}(B2Z8oP8 z3%jLGbjha<G2^Ezv=i6We*puYCTfn_DE4Xjlt=SX^9t8tqqbEC%lj$<h*YUAO*AY; zUE^YOP83U&b#ovOh;Gg8H=sMwjyF)~uhf*!1-rO(01B@kKGr1yWKm{zQ}dvWuT72M z0SYTxMl+gwmK(N(nzwXsmc=DRkUcsFeuP$CZ~Qvn!V!u5)z{}h#taT*Nr#bSoy0~h zr#d-?$OZbKqQaJU8mDh?DcX~m*OVlk=-1M|#5gFpRDB>F@ImcY!(@Vpda}vIA*RN& z%o*``sf>JlG#*~cJ6MR%!)x*y@#Y5Ce|Tyz6546ewPbQ3dH-2m#N={dcH<UC*B(3O zF70jZbJ*gWGyG(IZuNU+h?~)3`yHpJ3n^od-CFIBvH@G}5LZ{vmcp^zdjCbAqK#)u zj&B8Jd+)oYwxoXH7z<%Kb4Li8f8y<!!x9>Ox44?WHR%s_RGTxy9Z1d#MK4Yg7-&el z1muU)vC|eV;z2>M#pEKtQ4$*ssntrlBUu|)QO2xUG|x&nEdOz}_#cRTh2vO1Bcot3 z(++w0S?){Rxb?-^{o2CYvX7XVUNQ#!gA^bQUmdIEt!wkR8@-w~kIi@;a)gE&s_YND z>auCi42K07qxf*eW>oXi1~64JHpCtP!H9q$=;9dLq}sfdl$ZAwQqgYnCyxSa=nY8r zpLDHeAtA|lMMXPO{YANh`NT^eO`&B#m&q!N57SPV+KSVYIC=28ov0Q6pccG~wW-zd z?q0ahtD|z%*vtMiJCJmAPR!Z!e(0=;7fFU%aF?}k;ESl-X@lN2vg*AI3w!wmx@v_( zj`QO3Pbbnx8c**s&fsnge4uNg)_^RV@3x+c;P+Tl=)q5b6Z{cPVL@ElVDpQ6sd;=% zl#H+Ous3LSiIzK~=(~QZ&q1iUHvWAH*l==2Y8}D(afSv&Z>WYlg}Y|9`@PN|3qsBW z0mD5F9|fAtYE(n`SYzsdY!s*Tv>p{XH-Bl=W(sVZIV*eD>XTMkYwKD(+B&7uWXOM* zkw+&BhVjjSx4C$%7C*4>ga9?kRb--X#uJpj++A}{Y5vJ9-x9C7X&0KPZw^dh9Lg}U zz{KBbFE|+azM$7#)}wvuca)gMB|yB}Zs=K^lfKnf{^UMH(wJ7|>JhZT$FiCIflOIU zf2J#}8<nRR_+87^glAlbT*&dowVIdCPKY-5;@9j<=lt^><a#JXB<=XDXwyWA09Xg6 zv+%;Y9$B3;Q}z1=1$OEWxhmw56XzmQ$#ksC0qO8o(wfKotNFC}#>7vm+QoLfc(6{a zbU2SmVXQ`?ul6m9MM*?eUl<LuaWmb%c=W(M^`X#t0VIn@h{g2HgG?4|NbWka$X$5; z7hPy|^h1>S{I~<!uJq4lM<bmLll(JJXF;f8TH%y|KAN3BQfJq-c1I-EAT(IH#|(ME z5!&+x#b33^;7v1b5*2!c_Zj*;yqOxQWuD6}uZ)<f7c^+zGcJ)VMQ%FuxNPG!lj2^t zxC)?g6D9>x95p1(R1bBFg*EX#Y!LG!|Ev*cyIQ0MoN3w_oUfreq|`Xk<6>0+^5tuv zxAYd_^|LD6*)sdtX{E<PC}=mYcsiGSDCJmmK|I=gLx_+M316^G+boj{nt3nMC&p?0 z9Z&${9*$XwI?1_%CzIUL6ZX0}8g<|$TY9aSo_urU@I%_q<D=T0Ox1iih&(!V@z709 zw$S<`+JyeJuDv(>8c*KYD~nk9gp|6&=o@|vr?e5nqa=l5V!rj!eZ>ul@DH0k-{^YR zA@4Ri{z%3&7fL4QN8A=LN~;8U8V8?~Zc;cUh^BHWO#tw}KwhztRe{+eykCKoJ^MV$ z%VD7E0X@ppQ)t9^F?pf{82XLXLTiZ_u`2D3E16}?*>LOWS)fR`T)D!3dihZ&&+y=* zR;_fx`B8wh)vmIZaTZ@^ovR99jH0x5sOoXK(O%?84*s42uP>haaFj#~I*+;pWQ8Ze z6gEXqbxQn`-pj5vo$VyM;Hq;8{1Jl@Ki*LcdUFL&uC8^Jdywx`V5NMgc6PjDPp@5y z4X<jp5@)UriSAHYz6(;apdi)h%b5PW4LxPOgp8Js`4j{{uU?vZI#qu$RcVqmiNt{; zw&mPK4A;SuEe&#u8E#E1{vQ@sIg?yW2x%ghF%dtCcMt@+H^1`5-oa!qE{JTl;VbV8 zL^Zwu0!qFw+F)WtcIEJu)&Simke1Lp#W{V@+8Vs90Ide(ii3z~5T|dPHGJlKTc%>r z=}91)(<k{d5MDpuesM<mt=M{Cayx<H*<>MC)+#VWKNfq87hBRa)s9+2b!8v4u+5h0 zOp8##88Uw|{mu)`5)yK<J2B*1Tj_u6bxO&GCfnnARI|MJEEwB7a?x*_beSYrN5RKp z$r{({e)DLfx3d&jyyG9ArET62D2NHiNnmFJaK(9&J}*zUuy!&<2dn^xx47_L9D901 z$HC&~S1NZ`$`4yoJ$V9FI6^|6^^Oh6@M;o<TVB-<mlGqEI0Ns<(=eP)5|U5Q+Qt67 zJL9NxE8k5P++^*Ojyn3f-AZHO<9eWL-FmUjtU_QS{UE8*c7P?Gr_Xh8sMzN7e)n9* zgmFQ@wiR2AkADFBpGwra+0TYo##>&yU{~8yRt_QC{HqXLH7Bu(kn9kCxr{^at*BIX z1aL0?*l>pzeAHH#O!Pm~r*2r#ZpZIbLeN#aDe#J>w&q#fgRE{Rdpl{Y`AHs}UNHHb zFD%DWO^q8eA73vwmKlRI8hY4GguhDuIL><f@KA&^Zo=@`L#QRoaG3|;AT+Bd)C=O> zZBM`6fYVWbEYOkbkdE-g-r{dmFbg496ua;37q5I%A!teWhE>}d0$y>jm!-<!k?wJf zFx@T_O*lq|Et{&HoAmDQ@PzTD{XVMm%1tGGImRq_Y~5#{l-U!0x8F_QH3b<OVLMJn z{&v*5<euVwqjp{#d6CCCeM#fS_Lu|Jvfn<#u)RumUN)G1F>90SthC$g_{k;aEnCDn zj9U~VdXG-%p7vMYKzVqm(nw-s*X@e&7R;Z;JL-B>>tz!{7;`005%dMdyh&$#q5u=l zmQ9H8_N%?PM!c}+`7e<E?|zVf1E!gwgCkH>+r!==2y7t+hKW4^iW<3K9Ihgus43V2 z3chOitDK>yryp2G<_b^^|B^d;g8xPQe;w4p7V<DLDGf;}4QX{5X%%Tnn3_0LMnz3R zLsbSUb;aW<P(|?nmR#NPw@2k)*!(xt{vY0xcRr0FqivbuzWGL=sQbC?Q7CK%J2SI^ z0n>QNt$E4*)L5XKN`T1H<4F3csMGKQLBT*R4<G*R$rtiicN5+_{Ss_J>CsS1Fu)}! zTH$lTb$M05fESPf6m_q#A8-Rqz3Ii^4Wr~vMIJ4?&}t1xT?f;ddeO;v(NMvlalK0( zH;z#8Wn<QFHE7W&=!T+Y12C+5kl#}ITK<$cbB;%+JI1<m2Kt-SJtI}%`Q#t{AS)Y+ vCL*;_9yaXbB{vbWN5*Nx?DC(*^7XUz@e8_|i-1rlOk74B$j^_^*8u(#1hM}x diff --git a/homer_navigation/src/homer_navigation_node.cpp b/homer_navigation/src/homer_navigation_node.cpp deleted file mode 100644 index 5897946e..00000000 --- a/homer_navigation/src/homer_navigation_node.cpp +++ /dev/null @@ -1,1069 +0,0 @@ - -#include <vector> -#include <iostream> -#include <sstream> -#include <cmath> - -#include <stdio.h> -#include <stdlib.h> -#include <time.h> - -#include <ros/package.h> - -#include "homer_navigation/homer_navigation_node.h" - -//messages -#include <std_msgs/Empty.h> -#include <homer_mapnav_msgs/TargetUnreachable.h> -#include <homer_mapnav_msgs/GetPointsOfInterest.h> -#include <homer_mapnav_msgs/ModifyMap.h> -#include <nav_msgs/Path.h> -#include <std_msgs/Int8.h> -#include <tools/tools.h> -#include <tools/loadRosConfig.h> - -//nav_libs -#include "Explorer/Explorer.h" -#include "SpeedControl/SpeedControl.h" - -using namespace std; - - -HomerNavigationNode::HomerNavigationNode() -{ - ros::NodeHandle nh; - - srand(time(NULL));// Initialize random numbers - - //subscribers - map_sub_ = nh.subscribe<nav_msgs::OccupancyGrid>("/map", 1, &HomerNavigationNode::mapCallback, this); - pose_sub_ = nh.subscribe<geometry_msgs::PoseStamped>("/pose", 1, &HomerNavigationNode::poseCallback, this); - laser_data_sub_ = nh.subscribe<sensor_msgs::LaserScan>("/scan", 1, &HomerNavigationNode::laserDataCallback, this); - laser_back_data_sub_ = nh.subscribe<sensor_msgs::LaserScan>("/back_scan", 1, &HomerNavigationNode::backLaserCallback, this); - start_navigation_sub_ = nh.subscribe<homer_mapnav_msgs::StartNavigation>("/homer_navigation/start_navigation", 1, &HomerNavigationNode::startNavigationCallback, this); - stop_navigation_sub_ = nh.subscribe<homer_mapnav_msgs::StopNavigation>("/homer_navigation/stop_navigation", 1, &HomerNavigationNode::stopNavigationCallback, this); - navigate_to_poi_sub_ = nh.subscribe<homer_mapnav_msgs::NavigateToPOI>("/homer_navigation/navigate_to_POI", 1, &HomerNavigationNode::navigateToPOICallback, this); - unknown_threshold_sub_ = nh.subscribe<std_msgs::Int8>("/homer_navigation/unknown_threshold", 1, &HomerNavigationNode::unknownThresholdCallback, this); - refresh_param_sub_ = nh.subscribe<std_msgs::Empty>("/homer_navigation/refresh_params", 1, &HomerNavigationNode::refreshParamsCallback, this); - - cmd_vel_pub_ = nh.advertise<geometry_msgs::Twist>("/robot_platform/cmd_vel", 1); - target_reached_pub_ = nh.advertise<std_msgs::Empty>("/homer_navigation/target_reached", 1); - target_unreachable_pub_ = nh.advertise<homer_mapnav_msgs::TargetUnreachable>("/homer_navigation/target_unreachable", 1); - path_pub_ = nh.advertise<nav_msgs::Path>("/homer_navigation/path", 1); - get_POIs_client_ = nh.serviceClient<homer_mapnav_msgs::GetPointsOfInterest>("/map_manager/get_pois"); - - - m_move_base_simple_goal_sub_ = nh.subscribe<geometry_msgs::PoseStamped>("/move_base_simple/goal", 1, &HomerNavigationNode::moveBaseSimpleGoalCallback, this); // for RVIZ usage - - - - m_MapTypeMachine.setName( "HomerNavigation Node" ); - ADD_MACHINE_STATE( m_MapTypeMachine, SLAM_MAP ); - ADD_MACHINE_STATE( m_MapTypeMachine, NAVIGATION_MAP ); - m_MapTypeMachine.setState( SLAM_MAP ); - - m_MainMachine.setName( "HomerNavigation Main" ); - ADD_MACHINE_STATE( m_MainMachine, IDLE ); - ADD_MACHINE_STATE( m_MainMachine, AWAITING_EXPLORATION_MAP ); - ADD_MACHINE_STATE( m_MainMachine, AWAITING_PATHPLANNING_MAP ); - ADD_MACHINE_STATE( m_MainMachine, FOLLOWING_PATH ); - ADD_MACHINE_STATE( m_MainMachine, AVOIDING_COLLISION ); - ADD_MACHINE_STATE( m_MainMachine, FINAL_TURN ); - ADD_MACHINE_STATE( m_MainMachine, TARGET_REACHED ); - - m_avoided_collision = false; - - init(); - m_act_speed = 0; - m_act_angle = 0; -} - -void HomerNavigationNode::loadParameters() -{ - SpeedControl::loadDimensions(); - - //Explorer constructor - loadConfigValue("/homer_navigation/safe_path_weight", m_SafePathWeight); - loadConfigValue("/homer_mapping/resolution", resolution_); - loadConfigValue("/homer_navigation/allowed_obstacle_distance/min", m_AllowedObstacleDistance.first); - loadConfigValue("/homer_navigation/allowed_obstacle_distance/max", m_AllowedObstacleDistance.second); - m_AllowedObstacleDistance.first /= resolution_; - m_AllowedObstacleDistance.second/= resolution_; - loadConfigValue("/homer_navigation/safe_obstacle_distance/min", m_SafeObstacleDistance.first); - loadConfigValue("/homer_navigation/safe_obstacle_distance/max", m_SafeObstacleDistance.second); - m_SafeObstacleDistance.first /= resolution_; - m_SafeObstacleDistance.second /= resolution_; - loadConfigValue("/homer_navigation/frontier_safeness_factor", m_FrontierSafenessFactor); - - //Explorer - loadConfigValue("/homer_navigation/waypoint_sampling_threshold", waypoint_sampling_threshold_); - - //check path - loadConfigValue("/homer_navigation/check_path", check_path_); - loadConfigValue("/homer_navigation/check_path_max_errors", check_path_max_errors_); - loadConfigValue("/homer_navigation/check_path_max_distance", check_path_max_distance_); - - //collision - loadConfigValue("/homer_navigation/collision_distance", collision_distance_); - loadConfigValue("/homer_navigation/collision_distance_near_target", collision_distance_near_target_); - - //moveRobot config values - loadConfigValue("/homer_navigation/backward_distance", backward_distance_); - loadConfigValue("/homer_navigation/max_trans_vel", m_MaxTransVel); - loadConfigValue("/homer_navigation/max_rot_vel", m_MaxRotVel); - loadConfigValue("/homer_navigation/speed_control/last_speedfactor_count", m_SpeedFactorMeanFilterSize); - loadConfigValue("/homer_navigation/speed_control/min_move_speedfactor", m_MinMoveSpeedFactor); - loadConfigValue("/homer_navigation/speed_control/min_turn_speedfactor_moving", m_MinTurnSpeedFactorMoving); - loadConfigValue("/homer_navigation/speed_control/min_turn_speedfactor_standing", m_MinTurnSpeedFactorStanding); - loadConfigValue("/homer_navigation/turn_threshold_angle", turn_threshold_angle_); - - //cmd_vel config values - loadConfigValue("/homer_navigation/use_cmd_vel", m_use_cmd_vel_); - loadConfigValue("/homer_navigation/min_turn_angle", m_min_turn_angle); - loadConfigValue("/homer_navigation/max_turn_speed", m_max_turn_speed); - loadConfigValue("/homer_navigation/max_move_speed", m_max_move_speed); - loadConfigValue("/homer_navigation/max_drive_angle", m_max_drive_angle); - -} - - -void HomerNavigationNode::init() -{ - last_map_timestamp_ = ros::Time(0); - - loadParameters(); - - robot_pose_.position.x = 0.0; - robot_pose_.position.y = 0.0; - robot_pose_.position.z = 0.0; - robot_pose_.orientation = tf::createQuaternionMsgFromYaw(0.0); - - last_laser_time_ = ros::Time::now(); - - explorer_ = new Explorer ( m_AllowedObstacleDistance.first, m_AllowedObstacleDistance.second, - m_SafeObstacleDistance.first, m_SafeObstacleDistance.second, - m_SafePathWeight, m_FrontierSafenessFactor ); - - m_MainMachine.setState ( IDLE ); -} - -HomerNavigationNode::~HomerNavigationNode() -{ - if ( explorer_ ) - { - delete explorer_; - } - if(last_map_data_) - { - delete last_map_data_; - } -} - -void HomerNavigationNode::sendStopRobot() -{ - m_act_speed = 0; - m_act_angle = 0; - geometry_msgs::Twist cmd_vel_msg; - cmd_vel_msg.linear.x = 0; - cmd_vel_msg.linear.y = 0; - cmd_vel_msg.linear.z = 0; - cmd_vel_msg.angular.x = 0; - cmd_vel_msg.angular.y = 0; - cmd_vel_msg.angular.z = 0; - cmd_vel_pub_.publish(cmd_vel_msg); -} - -void HomerNavigationNode::idleProcess() -{ - if ( m_MainMachine.state() == FOLLOWING_PATH ) - { - if ( (ros::Time::now() - last_laser_time_) > ros::Duration(2.0) ) - { - ROS_ERROR_STREAM( "Laser data timeout!\n"); - sendTargetUnreachableMsg(homer_mapnav_msgs::TargetUnreachable::LASER_TIMEOUT); - } - } -} - - -void HomerNavigationNode::calculatePath() -{ - float desired_distance_2 = desired_distance_ - 0.05; - if ( desired_distance_2 < resolution_ ) - { - desired_distance_2 = resolution_; - } - explorer_->setStart ( map_tools::toMapCoords( robot_pose_.position, origin_, resolution_) ); - - if ( map_tools::distance( map_tools::fromMapCoords( target_approx_, origin_, resolution_ ), target_point_ ) <= desired_distance_ ) - { - ROS_INFO_STREAM( "There is a way to the target circle. Planning direct path." ); - explorer_->setTarget ( map_tools::toMapCoords( target_point_, origin_, resolution_ ), desired_distance_2 / resolution_ ); - } - else - { - ROS_INFO_STREAM( "The target area is not reachable. Trying to go as close as possible." ); - explorer_->setTarget ( target_approx_, 0 ); - } - - bool success; - pixel_path_ = explorer_->getPath( success ); - if ( !success ) - { - ROS_WARN_STREAM("No path found for navigation, reporting as unreachable." ); - sendTargetUnreachableMsg(homer_mapnav_msgs::TargetUnreachable::NO_PATH_FOUND); - } - else - { - ROS_INFO_STREAM("homer_navigation::calculatePath - Path Size: " << pixel_path_.size()); - std::vector<Eigen::Vector2i> waypoint_pixels = explorer_->sampleWaypointsFromPath ( pixel_path_, waypoint_sampling_threshold_ ); - waypoints_.clear(); - for(std::vector<Eigen::Vector2i>::iterator it = waypoint_pixels.begin(); it != waypoint_pixels.end(); ++it) - { - geometry_msgs::PoseStamped poseStamped; - poseStamped.pose.position = map_tools::fromMapCoords(*it, origin_, resolution_); - poseStamped.pose.orientation.x = 0.0; - poseStamped.pose.orientation.y = 0.0; - poseStamped.pose.orientation.z = 0.0; - poseStamped.pose.orientation.w = 1.0; - waypoints_.push_back(poseStamped); - } - - ROS_INFO_STREAM("homer_navigation::calculatePath - Path Size: " << waypoints_.size()); - - sendPathData(); - //make sure no timeout occurs after long calculation time - last_laser_time_ = ros::Time::now(); - } -} - - -void HomerNavigationNode::startExploration() -{ - ROS_INFO_STREAM( "Starting exploration." ); -/* - m_Explorer->resetExploration(); - m_Explorer->setOccupancyMap ( gridSize, gridSize, mapData, m_ExploredRegion ); - m_Explorer->setFrontierSafenessFactor( m_FrontierSafenessFactor ); - m_Explorer->setStart ( m_CoordinateConverter->worldToMap ( m_RobotPose ) ); - - bool success; - m_PixelPath= m_Explorer->getExplorationTransformPath( success ); - - if ( success ) { - m_Target = m_CoordinateConverter->mapToWorld( m_PixelPath.back() ); - m_TargetApprox = m_PixelPath.back(); - } - - vector<Pixel> waypointPixels = m_Explorer->sampleWaypointsFromPath ( m_PixelPath, m_WaypointSamplingThreshold ); - m_Waypoints = m_CoordinateConverter->mapToWorld ( waypointPixels ); -*/ - - if ( pixel_path_.size() == 0 ) - { - ROS_WARN_STREAM("No path found for exploration, sending NoTargetM." ); - //sendMessage ( new NoTargetM() ); - m_MainMachine.setState( IDLE ); - } - else - { - m_MainMachine.setState ( FOLLOWING_PATH ); - sendPathData(); - } - //make sure no timeout occurs after long calculation time - last_laser_time_ = ros::Time::now(); -} - - -void HomerNavigationNode::startNavigation() -{ - ROS_INFO_STREAM("Starting navigation to " << target_point_.x << "," << target_point_.y); - - if ( distanceTo(target_point_) < desired_distance_ ) - { - ROS_INFO_STREAM( "Will not (re-)plan path: Target position already reached." ); - targetPositionReached(); - return; - } - ROS_INFO_STREAM( "Distance to target still too large (" << distanceTo( target_point_ ) << "m; requested: " << desired_distance_ << "m)" ); - - ROS_DEBUG_STREAM("homer_navigation_node::startNavigation: target point " << target_point_.x << " " << target_point_.y); - Eigen::Vector2i new_target = map_tools::toMapCoords(target_point_, origin_, resolution_); - ROS_DEBUG_STREAM("homer_navigation_node::startNavigation: target cell " << new_target); - Eigen::Vector2i new_target_approx; - - switch ( m_MapTypeMachine.state() ) - { - case SLAM_MAP: - { - ROS_INFO_STREAM( "Resetting occupancy map." ); - - if(fast_path_planning_) - { - maskMap(); - } - explorer_->setOccupancyMap(width_, width_, origin_, &(*last_map_data_)[0]); - explorer_->setStart(map_tools::toMapCoords(robot_pose_.position, origin_, resolution_)); - new_target_approx = explorer_->getNearestAccessibleTarget(new_target); - break; - } - case NAVIGATION_MAP: - ROS_INFO_STREAM( "Updating obstacles in externally assigned navigation map." ); - explorer_->updateObstacles( width_, width_, origin_, &(*last_map_data_)[0] ); - explorer_->setStart(map_tools::toMapCoords(robot_pose_.position, origin_, resolution_)); - new_target_approx = new_target; - break; - } - - geometry_msgs::Point new_target_approx_world = map_tools::fromMapCoords(new_target_approx, origin_, resolution_); - ROS_INFO_STREAM("start Navigation: Approx target: " << new_target_approx_world); - - bool new_approx_is_better = ( map_tools::distance( robot_pose_.position, target_point_ ) - map_tools::distance( new_target_approx_world, target_point_ ) ) > 0.2; - bool new_approx_reaches_target = ( map_tools::distance(new_target_approx_world, target_point_ ) < desired_distance_ ); - m_path_reaches_target = new_approx_reaches_target; - if ( !new_approx_is_better && !new_approx_reaches_target ) - { - ROS_WARN_STREAM( "No better way to target found, turning and then reporting as unreachable." - << endl << "Distance to target: " << distanceTo( target_point_ ) << "m; requested: " << desired_distance_ << "m" ); - m_MainMachine.setState( FINAL_TURN ); - } - else - { - target_approx_ = new_target_approx; - m_MainMachine.setState ( FOLLOWING_PATH ); - calculatePath(); - } - } - -void HomerNavigationNode::sendPathData() -{ - geometry_msgs::PoseStamped pose_stamped; - pose_stamped.pose = robot_pose_; - pose_stamped.header.frame_id = "/map"; - pose_stamped.header.stamp = ros::Time::now(); - - nav_msgs::Path msg; - msg.poses = waypoints_; - if(waypoints_.size() > 0) - msg.poses.insert(msg.poses.begin(), pose_stamped); - path_pub_.publish(msg); - } - -void HomerNavigationNode::sendTargetReachedMsg() { - sendStopRobot(); - m_MainMachine.setState( IDLE ); - std_msgs::Empty reached_msg; - target_reached_pub_.publish(reached_msg); - waypoints_.clear(); - nav_msgs::Path empty_path_msg; - empty_path_msg.poses = waypoints_; - path_pub_.publish(empty_path_msg); - ROS_INFO_STREAM("TargetReachedMsg"); -} - -void HomerNavigationNode::sendTargetUnreachableMsg( int8_t reason ) { - sendStopRobot(); - m_MainMachine.setState( IDLE ); - homer_mapnav_msgs::TargetUnreachable unreachable_msg; - unreachable_msg.reason = reason; - target_unreachable_pub_.publish(unreachable_msg); - waypoints_.clear(); - nav_msgs::Path empty_path_msg; - empty_path_msg.poses = waypoints_; - path_pub_.publish(empty_path_msg); - ROS_INFO_STREAM("TargetUnreachableMsg"); -} - -void HomerNavigationNode::targetPositionReached() -{ - //we're as close s we can get, target reached - ROS_INFO_STREAM( "Target position reached. Distance to target: " << distanceTo( target_point_ ) << "m. Desired distance:" << desired_distance_ << "m" ); - sendStopRobot(); - // usleep( 30000 ); - waypoints_.clear(); - sendPathData(); - m_MainMachine.setState( FINAL_TURN ); - ROS_INFO_STREAM("Turning to look-at point"); -} - - -void HomerNavigationNode::checkPath() -{ - invalid_path_count_=0; - for ( unsigned i=0; i<pixel_path_.size(); i++ ) - { - geometry_msgs::Point p = map_tools::fromMapCoords(pixel_path_.at(i), origin_, resolution_); - if ( distanceTo(p) > check_path_max_distance_ ) - { - continue; - } - if (map_tools::findValue( last_map_data_, width_, height_, pixel_path_[i].x(), pixel_path_[i].y(), 90, m_AllowedObstacleDistance.first ) ) - { - invalid_path_count_++; - ROS_WARN_STREAM("Obstacle detected in current path " << invalid_path_count_ << " of " << check_path_max_errors_ << " times."); - - if ( invalid_path_count_ >= check_path_max_errors_ ) - { - ROS_WARN_STREAM( "Replanning path." ); - currentPathFinished(); - } - return; - } - } -} - -void HomerNavigationNode::handleCollision () -{ - if ( m_MainMachine.state()== FOLLOWING_PATH ) - { - sendStopRobot(); - if( distanceTo( target_point_) < collision_distance_near_target_ ) - { - ROS_INFO_STREAM("Collision detected near target. Switch to final turn."); - targetPositionReached(); - } - else - { - m_MainMachine.setState( AVOIDING_COLLISION ); - ROS_WARN_STREAM( "Collision detected while following path!" ); - } - } -} - -float HomerNavigationNode::calcSpeedFactor() -{ - float speedFactor = SpeedControl::getSpeedFactor(laser_points_, m_MinMoveSpeedFactor, 1.0 ); - - m_LastSpeedFactors.push_back( speedFactor ); - if ( m_LastSpeedFactors.size() > m_SpeedFactorMeanFilterSize ) { m_LastSpeedFactors.pop_front(); } - - float speedFactorMean = mean( m_LastSpeedFactors ); - - return speedFactorMean; -} - - -void HomerNavigationNode::performNextMove() -{ - float maxMoveDistance = SpeedControl::getMaxMoveDistance ( laser_points_ ); - float speedFactor = calcSpeedFactor(); - - switch ( m_MainMachine.state() ) - { - case FOLLOWING_PATH: - { - if ( distanceTo( target_point_ ) < desired_distance_ ) - { - ROS_INFO_STREAM( "Desired distance to target was reached." ); - targetPositionReached(); - return; - } - - float waypointRadiusLaser = 0.125 * maxMoveDistance; - - Eigen::Vector2i waypointPixel = map_tools::toMapCoords(waypoints_[0].pose.position, origin_, resolution_); - float obstacleDistanceMap = explorer_->getObstacleTransform()->getValue( waypointPixel.x(), waypointPixel.y() ); - float waypointRadiusMap = 0.125 * obstacleDistanceMap * resolution_; - - float waypointRadius = waypointRadiusLaser + waypointRadiusMap; - if ( ( waypointRadius < resolution_ ) || ( waypoints_.size() == 1 ) ) - { - waypointRadius = resolution_; - } - - //if we have accidentaly skipped waypoints, recalculate path - float minDistance=FLT_MAX; - unsigned nearestWaypoint=0; - for ( unsigned i=0; i<waypoints_.size(); i++ ) - { - if ( distanceTo( waypoints_[i].pose.position ) < minDistance ) { - nearestWaypoint = i; - minDistance = distanceTo( waypoints_[i].pose.position ); - } - } - if ( nearestWaypoint != 0 ) - { - ROS_WARN_STREAM("Waypoints skipped. Recalculating path!"); - calculatePath(); - if ( m_MainMachine.state() != FOLLOWING_PATH ) { break; } - } - - ROS_DEBUG_STREAM("NextMove DEBUG VALUES: maxMoveDistance="<< maxMoveDistance <<"\n" - << "\tWaypointRadiusLaser=" << waypointRadiusLaser << "\n\t" - << "obstacleDistanceMap=" << obstacleDistanceMap << "\n\t" - << ""); - - //check if current waypoint has been reached - if ( (waypoints_.size() != 0) && ( distanceTo( waypoints_[0].pose.position ) < waypointRadius ) ) - { - waypoints_.erase ( waypoints_.begin() ); - ROS_DEBUG_STREAM("homer_navigation::performNextMove(): Current waypoint has been reached! Still " << waypoints_.size() << " to reach!"); - } - - sendPathData(); - - ROS_ERROR_STREAM("waypointRadius: " << waypointRadius); - //last wayoint reached - if ( waypoints_.size() == 0 ) - { - ROS_INFO_STREAM("Last waypoint reached"); - currentPathFinished(); - return; - } - - geometry_msgs::Point currentWaypoint = waypoints_[0].pose.position; - - double distanceToWaypoint = distanceTo ( currentWaypoint ); - double angleToWaypoint = angleToPointDeg ( currentWaypoint ); - - ROS_DEBUG_STREAM("homer_navigation::performNextMove(): Distance to waypoint: "<<distanceToWaypoint<<" Angle to waypoint: "<< (angleToWaypoint) << " Waypoint: " << currentWaypoint << "Robot Pose: " << robot_pose_.position << " Robot orientation " << tf::getYaw(robot_pose_.orientation)) ; - - ostringstream stream; - stream.precision(2); - - if (!m_use_cmd_vel_) - { - ROS_ERROR_STREAM("Not supported"); - } - //move to next waypoint if heading in right direction - else // else use cmd_vel - { - if (angleToWaypoint < -180) - { - angleToWaypoint += 360; - } - - //linear speed calculation - double speed = distanceToWaypoint; - if (speed < 0 ) - { - speed = max(speed,-m_max_move_speed); - } - else - { - speed = min(speed,m_max_move_speed); - } - if(m_avoided_collision) - { - if( std::abs(angleToWaypoint) < 10) - { - m_avoided_collision = false; - } - else - { - speed = 0; - } - } - //linear speed calculation end - //angular speed calculation - double angle = angleToWaypoint*3.14/180.0; - if (abs(angle) < m_min_turn_angle) - { - angle = 0.0; - } - else - { - if (abs(angle) > m_max_drive_angle) - { - speed = 0.0; - } - if (angle < 0 ) - { - angle = max(angle,-m_max_turn_speed); - } - else - { - angle = min(angle,m_max_turn_speed); - } - if (distanceToWaypoint < 1.0) - { - angle *= distanceToWaypoint; - } - // min speed for angles because under 0.35 the machine is really really slow - if (speed < 0.07) - { - if ( angle < 0 ) - { - angle = min(angle,-0.45); - } - else - { - angle = max(angle,0.45); - } - } - } - //angular speed calculation end - - m_act_speed = speed; - m_act_angle = angle; - geometry_msgs::Twist cmd_vel_msg; - cmd_vel_msg.linear.x = speed; - cmd_vel_msg.angular.z = angle; - cmd_vel_pub_.publish(cmd_vel_msg); - - stream << "Driving & turning" << endl; - stream << "linear: " << speed << " angular: " << angle << endl; - stream << "distanceToWaypoint:" << distanceToWaypoint << "angleToWaypoint: " << angleToWaypoint << endl; - } - ROS_INFO_STREAM( stream.str() ); - break; - } - - case AVOIDING_COLLISION: - { - if( distanceTo( target_point_) < collision_distance_near_target_ ) - { - ROS_INFO_STREAM("Collision detected near target. Switch to final turn."); - targetPositionReached(); - } - else if ( maxMoveDistance <= collision_distance_ ) - { - ostringstream stream; - stream << "Maximum driving distance too short (" << maxMoveDistance << "m)! Moving back."; - ROS_WARN_STREAM( stream.str() ); - if (!m_use_cmd_vel_) - { - ROS_ERROR_STREAM("Not supported"); - } - else // cmd_vel - { - geometry_msgs::Twist cmd_vel_msg; - if(HomerNavigationNode::obstacleBackwardDistance() > 0.4) - { - cmd_vel_msg.linear.x = -0.3; - } - else - { - cmd_vel_msg.angular.z = -0.45; - } - cmd_vel_pub_.publish(cmd_vel_msg); - } - } - else - { - m_avoided_collision = true; - ROS_WARN_STREAM( "Collision avoided. Updating path." ); - currentPathFinished(); - } - break; - } - case FINAL_TURN: - { - if ( skip_final_turn_ ) - { - ROS_INFO_STREAM("Final turn skipped. Target reached."); - if( m_path_reaches_target ) - { - sendTargetReachedMsg(); - } - else - { - sendTargetUnreachableMsg(homer_mapnav_msgs::TargetUnreachable::NO_PATH_FOUND); - } - break; - } - - double turnAngle = minTurnAngle( tf::getYaw(robot_pose_.orientation), target_orientation_ ); - ROS_INFO_STREAM("homer_navigation::PerformNextMove:: Final Turn. Robot orientation: " << rad2Deg(tf::getYaw(robot_pose_.orientation)) << ". Target orientation: " << rad2Deg(target_orientation_) ); - ROS_DEBUG_STREAM ( "homer_navigation::PerformNextMove:: turnAngle: " << rad2Deg(turnAngle)); - if (m_use_cmd_vel_ ) // final turn with cmd_vel - { - if (turnAngle< 0 ) - { - turnAngle= max(turnAngle,-m_max_turn_speed); - } - else - { - turnAngle = min(turnAngle,m_max_turn_speed); - } - - if (abs(turnAngle) < m_min_turn_angle) - { - ROS_INFO_STREAM(":::::::TARGET REACHED BECAUSE lower "<<m_min_turn_angle); - if( m_path_reaches_target ) - { - sendTargetReachedMsg(); - } - else - { - sendTargetUnreachableMsg(homer_mapnav_msgs::TargetUnreachable::NO_PATH_FOUND); - } - } - else - { - geometry_msgs::Twist cmd_vel_msg; - cmd_vel_msg.angular.z = turnAngle; - cmd_vel_pub_.publish(cmd_vel_msg); - } - } - break; - } - - case AWAITING_EXPLORATION_MAP: - case AWAITING_PATHPLANNING_MAP: - { - //make sure that the robot doesn't move - ROS_INFO_STREAM("Awaiting pathplanning map"); - sendStopRobot(); - break; - } - case IDLE: - break; - } -} - -void HomerNavigationNode::currentPathFinished() // also used for replanning -{ - ROS_INFO_STREAM( "Current path was finished, initiating recalculation."); - waypoints_.clear(); - sendStopRobot(); - m_MainMachine.setState( AWAITING_PATHPLANNING_MAP ); - -} - -// returns angle to target point in degrees(!) -int HomerNavigationNode::angleToPointDeg ( geometry_msgs::Point target ) -{ - double cx = robot_pose_.position.x; - double cy = robot_pose_.position.y; - int targetAngle = rad2Deg( atan2 ( target.y - cy, target.x - cx ) ); - int currentAngle = rad2Deg( tf::getYaw(robot_pose_.orientation) ); - - int angleDiff = targetAngle - currentAngle; - angleDiff = (angleDiff + 180) % 360 - 180; - return angleDiff; -} - - -double HomerNavigationNode::distanceTo ( geometry_msgs::Point target ) -{ - double cx = robot_pose_.position.x; - double cy = robot_pose_.position.y; - double distance_to_target_2 = ( cx - target.x ) * ( cx - target.x ) + ( cy - target.y ) * ( cy - target.y ); - return sqrt ( distance_to_target_2 ); -} - -float HomerNavigationNode::obstacleBackwardDistance() -{ - float min_y = -0.27; - float max_y = 0.27; - - float back_distance = 4; - - for(float depth = -0.3 ; depth > -1.0; depth -= 0.01) - { - for(float y = min_y ; y <= max_y ; y += 0.1) - { - geometry_msgs::Point base_link_point; - base_link_point.x = depth; - base_link_point.y = y; - geometry_msgs::Point map_point = map_tools::transformPoint(base_link_point, transform_listener_ ,"/base_link", "/map"); - int i = map_tools::map_index(map_point, origin_ ,width_,resolution_); - if(last_map_data_->at(i) > 90) - { - if(back_distance > HomerNavigationNode::distanceTo(map_point)) - { - back_distance = HomerNavigationNode::distanceTo(map_point); - } - } - } - if(back_distance != 4) - { - break; - } - } - ROS_ERROR_STREAM("Back Distance: "<< back_distance); - return back_distance; -} - -void HomerNavigationNode::actualizeStatusInfo() -{ - ostringstream stream; - stream << m_MapTypeMachine.stateString() << '\n' - << m_MainMachine.stateString(); - ROS_DEBUG_STREAM( stream.str() ); -} - -void HomerNavigationNode::maskMap() -{ - //generate bounding box - ROS_INFO_STREAM("Calculating Bounding box for fast planning"); - Eigen::Vector2i pose_pixel = map_tools::toMapCoords( robot_pose_.position, origin_, resolution_); - Eigen::Vector2i target_pixel = map_tools::toMapCoords( target_point_, origin_, resolution_); - Eigen::Vector2i safe_pixel_distance(m_AllowedObstacleDistance.first * 4, - m_AllowedObstacleDistance.first * 4); - Eigen::AlignedBox2i planning_box; - planning_box.extend(pose_pixel); - planning_box.extend(target_pixel); - ROS_INFO_STREAM("Bounding Box: (" << planning_box.min() << " " << planning_box.max()); - Eigen::AlignedBox2i safe_planning_box(planning_box.min() - safe_pixel_distance, planning_box.max() + safe_pixel_distance); - ROS_INFO_STREAM("safe Bounding Box: (" << safe_planning_box.min() << " " << safe_planning_box.max()); - ROS_INFO_STREAM("min in m: " <<map_tools::fromMapCoords(safe_planning_box.min(), origin_, resolution_)); - ROS_INFO_STREAM("max in m: "<<map_tools::fromMapCoords(safe_planning_box.max(), origin_, resolution_)); - for(size_t x = 0; x < width_; x++) - { - for(size_t y = 0; y < width_; y++) - { - if(!safe_planning_box.contains(Eigen::Vector2i(x, y))) - { - last_map_data_->at(y * width_ + x) = -1; - - } - } - } -} - -//convenience math functions -float HomerNavigationNode::minTurnAngle( float angle1, float angle2 ) -{ - angle1 *= 180.0/M_PI; - angle2 *= 180.0/M_PI; - - int diff= angle2 - angle1; - diff = (diff + 180) % 360 - 180; - - float ret = static_cast<double>(diff) * M_PI/180.0; - return ret; -} - -template<class ContainerT> -double HomerNavigationNode::mean ( const ContainerT& values ) -{ - typename ContainerT::const_iterator it; - it = values.begin(); - double sum = 0; - while ( it != values.end() ) - { - sum += *it; - it++; - } - return sum / double ( values.size() ); -} - -void HomerNavigationNode::refreshParamsCallback(const std_msgs::Empty::ConstPtr& msg) -{ - ROS_INFO_STREAM("Refreshing Parameters"); - loadParameters(); -} - -void HomerNavigationNode::mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg) -{ - if(msg->info.height != msg->info.width) - { - ROS_ERROR_STREAM("Incoming Map not quadratic. No map update!"); - return; - } - if(msg->header.stamp != last_map_timestamp_) - { - last_map_timestamp_ = msg->header.stamp; - last_map_data_ = new std::vector<int8_t>(msg->data); - origin_ = msg->info.origin; - width_ = msg->info.width; - height_ = msg->info.height; - resolution_ = msg->info.resolution; - - Eigen::Vector2i map_point; - if(m_laser_points_map.size() > 0) - { - for(int i = 0; i < m_laser_points_map.size(); i++) - { - geometry_msgs::Point& point = m_laser_points_map[i]; - map_point = map_tools::toMapCoords(point, origin_, resolution_); - int k = map_point.y() * width_ + map_point.x(); - if(k < 0 || k > width_*height_) - { - continue; - } - last_map_data_->at(k) = homer_mapnav_msgs::ModifyMap::BLOCKED; - } - } - if(m_back_laser.size() > 0 ) - { - for(int i = 0; i < m_back_laser.size(); i++) - { - geometry_msgs::Point& point = m_back_laser[i]; - map_point = map_tools::toMapCoords(point, origin_, resolution_); - int k = map_point.y() * width_ + map_point.x(); - if(k < 0 || k > width_*height_) - { - continue; - } - last_map_data_->at(k) = homer_mapnav_msgs::ModifyMap::BLOCKED; - } - } - - switch ( m_MainMachine.state() ) - { - case AWAITING_EXPLORATION_MAP: - if ( m_MapTypeMachine.state() == SLAM_MAP ) - { - startExploration(); - } - break; - - case AWAITING_PATHPLANNING_MAP: - startNavigation(); - break; - case FOLLOWING_PATH: - { - if ( check_path_) - { - checkPath(); - } - - break; - } - default: - break; - } - } -} - -void HomerNavigationNode::poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) -{ - robot_pose_ = msg->pose; - performNextMove(); -} - -void HomerNavigationNode::laserDataCallback(const sensor_msgs::LaserScan::ConstPtr& msg) -{ - float frontal_obstacle_distance; - bool collision_detected; - - last_laser_time_ = ros::Time::now(); - laser_points_ = map_tools::laser_ranges_to_points(msg->ranges, msg->angle_min, msg->angle_increment, msg->range_min, msg->range_max, transform_listener_, msg->header.frame_id, "/base_link"); - m_laser_points_map = map_tools::laser_ranges_to_points( msg->ranges, msg->angle_min, msg->angle_increment, msg->range_min, msg->range_max, transform_listener_, msg->header.frame_id, "/map"); - - if(m_act_speed == 0) - { - return; - } - frontal_obstacle_distance = SpeedControl::getMaxMoveDistance ( laser_points_ ); - collision_detected = frontal_obstacle_distance <= collision_distance_; - if(collision_detected) - { - handleCollision(); - } -} - -void HomerNavigationNode::backLaserCallback(const sensor_msgs::LaserScan::ConstPtr& msg) -{ - m_back_laser = map_tools::laser_ranges_to_points( msg->ranges, msg->angle_min, msg->angle_increment, msg->range_min, msg->range_max, transform_listener_, msg->header.frame_id, "/map"); -} - -void HomerNavigationNode::startNavigationCallback(const homer_mapnav_msgs::StartNavigation::ConstPtr& msg) -{ - ROS_INFO_STREAM("Start navigating to (" << msg->goal.position.x << ", " << msg->goal.position.y << ")"); - if (m_MainMachine.state() != IDLE) { - ROS_WARN_STREAM( "Aborting current operation and starting navigation.\n"); - } - - m_MapTypeMachine.setState(SLAM_MAP); - - target_point_ = msg->goal.position; - target_orientation_ = tf::getYaw(msg->goal.orientation); - desired_distance_ = msg->distance_to_target < 0.1 ? 0.1 : msg->distance_to_target; - skip_final_turn_ = msg->skip_final_turn; - fast_path_planning_ = msg->fast_planning; - - m_LastSpeedFactors.clear(); - - ROS_INFO_STREAM("Navigating to target " << target_point_.x << ", " << target_point_.y - << "\nTarget orientation: " << target_orientation_ - << "Desired distance to target: " << desired_distance_); - - m_MainMachine.setState( AWAITING_PATHPLANNING_MAP ); -} - - -void HomerNavigationNode::moveBaseSimpleGoalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) -{ - m_avoided_collision = false; - target_point_ = msg->pose.position; - target_orientation_ = tf::getYaw(msg->pose.orientation); - desired_distance_ = 0.1;// msg->distance_to_target < 0.1 ? 0.1 : msg->distance_to_target; - skip_final_turn_ = false; - fast_path_planning_ = false; - - ROS_INFO_STREAM("Navigating to target via Move Base Simple x: " << target_point_.x << ", y: " << target_point_.y - << "\nTarget orientation: " << target_orientation_ - << "Desired distance to target: " << desired_distance_ ); - - m_MainMachine.setState( AWAITING_PATHPLANNING_MAP ); -} - -void HomerNavigationNode::navigateToPOICallback(const homer_mapnav_msgs::NavigateToPOI::ConstPtr &msg) -{ - m_avoided_collision = false; - std::string name = msg->poi_name; - homer_mapnav_msgs::GetPointsOfInterest srv; - get_POIs_client_.call(srv); - std::vector<homer_mapnav_msgs::PointOfInterest>::iterator it; - for(it = srv.response.poi_list.pois.begin(); it != srv.response.poi_list.pois.end(); ++it) - { - if(it->name == name) - { - ROS_INFO_STREAM("Start navigating to (" << it->pose.position.x << ", " << it->pose.position.y << ")"); - if (m_MainMachine.state() != IDLE) { - ROS_WARN_STREAM( "Aborting current operation and starting navigation.\n"); - } - - m_MapTypeMachine.setState(SLAM_MAP); - - sendStopRobot(); - - target_point_ = it->pose.position; - target_orientation_ = tf::getYaw(it->pose.orientation); - desired_distance_ = msg->distance_to_target < 0.1 ? 0.1 : msg->distance_to_target; - skip_final_turn_ = msg->skip_final_turn; - - - m_LastSpeedFactors.clear(); - - ROS_INFO_STREAM("Navigating to target " << target_point_.x << ", " << target_point_.y - << "\nTarget orientation: " << target_orientation_ - << "Desired distance to target: " << desired_distance_); - - m_MainMachine.setState( AWAITING_PATHPLANNING_MAP ); - return; - } - } - ROS_ERROR_STREAM("No point of interest with name '" << msg->poi_name << "' found in current poi list"); -} - -void HomerNavigationNode::stopNavigationCallback(const homer_mapnav_msgs::StopNavigation::ConstPtr& msg) -{ - ROS_INFO_STREAM("Stopping navigation." ); - // stop exploring - m_MainMachine.setState( IDLE ); - m_avoided_collision = false; - sendStopRobot(); - - waypoints_.clear(); - nav_msgs::Path empty_path_msg; - empty_path_msg.poses = waypoints_; - path_pub_.publish(empty_path_msg); -} - -void HomerNavigationNode::unknownThresholdCallback(const std_msgs::Int8::ConstPtr &msg) -{ - explorer_->setUnknownThreshold(static_cast<int>(msg->data)); -} - -int main(int argc, char **argv) -{ - ros::init(argc, argv, "homer_navigation"); - - HomerNavigationNode node; - - ros::Rate rate(12); - - while(ros::ok()) - { - ros::spinOnce(); - node.idleProcess(); - rate.sleep(); - } - - return 0; -} diff --git a/homer_map_manager/images/rosgraph.png b/images/rosgraph.png similarity index 100% rename from homer_map_manager/images/rosgraph.png rename to images/rosgraph.png diff --git a/homer_map_manager/images/rosgraph.svg b/images/rosgraph.svg similarity index 100% rename from homer_map_manager/images/rosgraph.svg rename to images/rosgraph.svg diff --git a/homer_map_manager/mainpage.dox b/mainpage.dox similarity index 100% rename from homer_map_manager/mainpage.dox rename to mainpage.dox diff --git a/homer_map_manager/manifest.xml b/manifest.xml similarity index 100% rename from homer_map_manager/manifest.xml rename to manifest.xml diff --git a/homer_map_manager/package.xml b/package.xml similarity index 100% rename from homer_map_manager/package.xml rename to package.xml diff --git a/homer_map_manager/readme.pdf b/readme.pdf similarity index 100% rename from homer_map_manager/readme.pdf rename to readme.pdf diff --git a/homer_map_manager/src/Managers/CMakeLists.txt b/src/Managers/CMakeLists.txt similarity index 100% rename from homer_map_manager/src/Managers/CMakeLists.txt rename to src/Managers/CMakeLists.txt diff --git a/homer_map_manager/src/Managers/MapManager.cpp b/src/Managers/MapManager.cpp similarity index 100% rename from homer_map_manager/src/Managers/MapManager.cpp rename to src/Managers/MapManager.cpp diff --git a/homer_map_manager/src/Managers/MapManager.h b/src/Managers/MapManager.h similarity index 100% rename from homer_map_manager/src/Managers/MapManager.h rename to src/Managers/MapManager.h diff --git a/homer_map_manager/src/Managers/MaskingManager.cpp b/src/Managers/MaskingManager.cpp similarity index 100% rename from homer_map_manager/src/Managers/MaskingManager.cpp rename to src/Managers/MaskingManager.cpp diff --git a/homer_map_manager/src/Managers/MaskingManager.h b/src/Managers/MaskingManager.h similarity index 100% rename from homer_map_manager/src/Managers/MaskingManager.h rename to src/Managers/MaskingManager.h diff --git a/homer_map_manager/src/Managers/PoiManager.cpp b/src/Managers/PoiManager.cpp similarity index 100% rename from homer_map_manager/src/Managers/PoiManager.cpp rename to src/Managers/PoiManager.cpp diff --git a/homer_map_manager/src/Managers/PoiManager.h b/src/Managers/PoiManager.h similarity index 100% rename from homer_map_manager/src/Managers/PoiManager.h rename to src/Managers/PoiManager.h diff --git a/homer_map_manager/src/Managers/RoiManager.cpp b/src/Managers/RoiManager.cpp similarity index 100% rename from homer_map_manager/src/Managers/RoiManager.cpp rename to src/Managers/RoiManager.cpp diff --git a/homer_map_manager/src/Managers/RoiManager.h b/src/Managers/RoiManager.h similarity index 100% rename from homer_map_manager/src/Managers/RoiManager.h rename to src/Managers/RoiManager.h diff --git a/homer_map_manager/src/MapIO/CMakeLists.txt b/src/MapIO/CMakeLists.txt similarity index 100% rename from homer_map_manager/src/MapIO/CMakeLists.txt rename to src/MapIO/CMakeLists.txt diff --git a/homer_map_manager/src/MapIO/image_loader.cpp b/src/MapIO/image_loader.cpp similarity index 100% rename from homer_map_manager/src/MapIO/image_loader.cpp rename to src/MapIO/image_loader.cpp diff --git a/homer_map_manager/src/MapIO/image_loader.h b/src/MapIO/image_loader.h similarity index 100% rename from homer_map_manager/src/MapIO/image_loader.h rename to src/MapIO/image_loader.h diff --git a/homer_map_manager/src/MapIO/map_loader.cpp b/src/MapIO/map_loader.cpp similarity index 100% rename from homer_map_manager/src/MapIO/map_loader.cpp rename to src/MapIO/map_loader.cpp diff --git a/homer_map_manager/src/MapIO/map_loader.h b/src/MapIO/map_loader.h similarity index 100% rename from homer_map_manager/src/MapIO/map_loader.h rename to src/MapIO/map_loader.h diff --git a/homer_map_manager/src/MapIO/map_saver.cpp b/src/MapIO/map_saver.cpp similarity index 100% rename from homer_map_manager/src/MapIO/map_saver.cpp rename to src/MapIO/map_saver.cpp diff --git a/homer_map_manager/src/MapIO/map_saver.h b/src/MapIO/map_saver.h similarity index 100% rename from homer_map_manager/src/MapIO/map_saver.h rename to src/MapIO/map_saver.h diff --git a/homer_map_manager/src/Workers/PointOfInterest/CMakeLists.txt b/src/Workers/PointOfInterest/CMakeLists.txt similarity index 100% rename from homer_map_manager/src/Workers/PointOfInterest/CMakeLists.txt rename to src/Workers/PointOfInterest/CMakeLists.txt diff --git a/homer_map_manager/src/Workers/PointOfInterest/PointOfInterest.h b/src/Workers/PointOfInterest/PointOfInterest.h similarity index 100% rename from homer_map_manager/src/Workers/PointOfInterest/PointOfInterest.h rename to src/Workers/PointOfInterest/PointOfInterest.h diff --git a/homer_map_manager/src/main.cpp b/src/main.cpp similarity index 100% rename from homer_map_manager/src/main.cpp rename to src/main.cpp diff --git a/homer_map_manager/src/map_manager_node.cpp b/src/map_manager_node.cpp similarity index 100% rename from homer_map_manager/src/map_manager_node.cpp rename to src/map_manager_node.cpp diff --git a/homer_map_manager/src/map_manager_node.h b/src/map_manager_node.h similarity index 100% rename from homer_map_manager/src/map_manager_node.h rename to src/map_manager_node.h diff --git a/tracks.yaml b/tracks.yaml deleted file mode 100644 index 297aea0d..00000000 --- a/tracks.yaml +++ /dev/null @@ -1,23 +0,0 @@ -tracks: - indigo: - actions: - - bloom-export-upstream :{vcs_local_uri} :{vcs_type} --tag :{release_tag} --display-uri - :{vcs_uri} --name :{name} --output-dir :{archive_dir_path} - - git-bloom-import-upstream :{archive_path} :{patches} --release-version :{version} - --replace - - git-bloom-generate -y rosrelease :{ros_distro} --source upstream -i :{release_inc} - - git-bloom-generate -y rosdebian --prefix release/:{ros_distro} :{ros_distro} - -i :{release_inc} - - git-bloom-generate -y rosrpm --prefix release/:{ros_distro} :{ros_distro} -i - :{release_inc} - devel_branch: null - last_version: 1.0.5 - name: upstream - patches: null - release_inc: '0' - release_repo_url: null - release_tag: :{version} - ros_distro: indigo - vcs_type: git - vcs_uri: https://gitlab.uni-koblenz.de/robbie/homer_mapnav.git - version: :{auto} -- GitLab