Skip to content
Snippets Groups Projects
OccupancyMap.h 11.68 KiB
#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