Пример #1
0
void SlamNode::initialize(const sensor_msgs::LaserScan& initScan)
{
  double xOffFactor           = 0.0;
  double yOffFactor           = 0.0;
  double yawOffset            = 0.0;
  double minRange             = 0.0;
  double maxRange             = 0.0;
  double lowReflectivityRange = 0.0;
  double footPrintWidth       = 0.0;
  double footPrintHeight      = 0.0;
  double footPrintXoffset     = 0.0;
  bool   icpSac               = false;

  ros::NodeHandle prvNh("~");
  prvNh.param<double>("x_off_factor",           xOffFactor, 0.2);
  prvNh.param<double>("y_off_factor",           yOffFactor, 0.5);
  prvNh.param<double>("yaw_offset",             yawOffset, 0.0);
  prvNh.param<double>("min_range",              minRange, 0.01);
  prvNh.param<double>("low_reflectivity_range", lowReflectivityRange, 2.0);
  prvNh.param<double>("footprint_width" ,       footPrintWidth, 0.1);
  prvNh.param<double>("footprint_height",       footPrintHeight, 0.1);
  prvNh.param<double>("footprint_x_offset",     footPrintXoffset, 0.28);
  prvNh.param<bool>  ("use_icpsac",             icpSac, true);

  _sensor=new obvious::SensorPolar2D(initScan.ranges.size(), initScan.angle_increment, initScan.angle_min, _maxRange, minRange, lowReflectivityRange);
  _sensor->setRealMeasurementData(initScan.ranges, 1.0);

  const double phi        = yawOffset;
  const double gridWidth  = _grid->getCellsX() * _grid->getCellSize();
  const double gridHeight = _grid->getCellsY() * _grid->getCellSize();
  const obfloat startX    = static_cast<obfloat>(gridWidth  * xOffFactor);
  const obfloat startY    = static_cast<obfloat>(gridHeight * yOffFactor);

  double tf[9] = {cos(phi), -sin(phi), gridWidth * xOffFactor,
                  sin(phi),  cos(phi), gridHeight * yOffFactor,
                  0,         0,                        1};
  obvious::Matrix Tinit(3, 3);
  Tinit.setData(tf);
  _sensor->transform(&Tinit);

  _threadMapping = new ThreadMapping(_grid);
  const obfloat t[2] = {startX + footPrintXoffset, startY};
  if(!_grid->freeFootprint(t, footPrintWidth, footPrintHeight))
    std::cout << __PRETTY_FUNCTION__ << " warning! Footprint could not be freed!\n";
  _threadMapping->initPush(_sensor);

  _threadLocalizer   = new ThreadLocalization(_grid, _threadMapping, _nh, xOffFactor, yOffFactor, icpSac);
  _threadGrid        = new ThreadGrid(_grid, _nh, xOffFactor, yOffFactor);
  _initialized       = true;
}
Пример #2
0
SlamNode::SlamNode(void)
{
  omp_set_num_threads(8);
  ros::NodeHandle prvNh("~");
  std::string strVar;
  int octaveFactor        = 0;
  double cellsize         = 0.0;
  double dVar             = 0;
  int iVar                = 0;
  double truncationRadius = 0.0;
  prvNh.param        ("laser_topic",         strVar, std::string("simon/scan"));
  prvNh.param<int>   ("cell_octave_factor",  octaveFactor, 10);
  prvNh.param<double>("cellsize",            cellsize, 0.01);
  prvNh.param<int>   ("truncation_radius",   iVar, 3);
  truncationRadius = static_cast<double>(iVar);
  prvNh.param<double>("max_range",           _maxRange, 30.0);
  prvNh.param<double>("occ_grid_time_interval", _gridPublishInterval, 2.0);
  prvNh.param<double>("loop_rate",           _loopRate, 100.0);

  _laserSubs = _nh.subscribe(strVar, 1, &SlamNode::laserScanCallBack, this);

  unsigned int uiVar = static_cast<unsigned int>(octaveFactor);
  if((uiVar > 15) || (uiVar < 5))
  {
    std::cout << __PRETTY_FUNCTION__ << " error! Unknown / Invalid cell_octave_factor -> set to default!" << std::endl;
    uiVar = 10;
  }
  _initialized = false;
  _grid        = new obvious::TsdGrid(cellsize, obvious::LAYOUT_32x32, static_cast<obvious::EnumTsdGridLayout>(uiVar));
  _grid->setMaxTruncation(truncationRadius * cellsize);

  unsigned int cellsPerSide = std::pow(2, uiVar);
  std::cout << __PRETTY_FUNCTION__ << " creating representation with " << cellsPerSide << "x" << cellsPerSide;
  double sideLength = static_cast<double>(cellsPerSide) * cellsize;
  std::cout << " cells, representing "<< sideLength << "x" << sideLength << "m^2" << std::endl;

  _sensor          = NULL;
  _threadLocalizer = NULL;
  _threadMapping   = NULL;
  _threadGrid      = NULL;
}
Пример #3
0
ThreadGrid::ThreadGrid(obvious::TsdGrid* grid, ros::NodeHandle* const nh, const double xOffset, const double yOffset):
        ThreadSLAM(*grid),
        _occGrid(new nav_msgs::OccupancyGrid),
        _occGridContent(new char[grid->getCellsX() * grid->getCellsY()]),
        _gridCoords(new double[grid->getCellsX() * grid->getCellsY()]),
        _width(grid->getCellsX()),
        _height(grid->getCellsY()),
        _cellSize(grid->getCellSize())

{
  for(unsigned int i = 0; i < _grid.getCellsX() * _grid.getCellsY(); ++i)
    _occGridContent[i] = -1;

  _occGrid->info.resolution           = static_cast<double>(_grid.getCellSize());
  _occGrid->info.width                = _grid.getCellsX();
  _occGrid->info.height               = _grid.getCellsY();
  _occGrid->info.origin.orientation.w = 0.0;
  _occGrid->info.origin.orientation.x = 0.0;
  _occGrid->info.origin.orientation.y = 0.0;
  _occGrid->info.origin.orientation.z = 0.0;
  _occGrid->info.origin.position.x    = 0.0 - (_grid.getCellsX() * _grid.getCellSize() * 0.5 + xOffset);
  _occGrid->info.origin.position.y    = 0.0 - (_grid.getCellsY() * _grid.getCellSize() * 0.5 + yOffset);
  _occGrid->info.origin.position.z    = 0.0;
  _occGrid->data.resize(_grid.getCellsX() * _grid.getCellsY());

  ros::NodeHandle prvNh("~");
  std::string mapTopic;
  std::string getMapTopic;
  int intVar         = 0;

  prvNh.param("map_topic", mapTopic, std::string("map"));
  prvNh.param("get_map_topic", getMapTopic, std::string("map"));
  prvNh.param<int>("object_inflation_factor", intVar, 2);
  prvNh.param<bool>("use_object_inflation", _objectInflation, false);  //toDo: exchange with if inflation > 0

  _gridPub          = nh->advertise<nav_msgs::OccupancyGrid>(mapTopic, 1);
  _getMapServ       = nh->advertiseService(getMapTopic, &ThreadGrid::getMapServCallBack, this);
  _objInflateFactor = static_cast<unsigned int>(intVar);
}
Пример #4
0
SlamNode::SlamNode(void)
{
  ros::NodeHandle prvNh("~");
  int iVar                   = 0;
  double gridPublishInterval = 0.0;
  double loopRateVar         = 0.0;
  double truncationRadius    = 0.0;
  double cellSize            = 0.0;
  unsigned int octaveFactor  = 0;
  double xOffset = 0.0;
  double yOffset = 0.0;
  std::string topicLaser;
  prvNh.param<int>("robot_nbr", iVar, 1);
  unsigned int robotNbr = static_cast<unsigned int>(iVar);
  prvNh.param<double>("x_off_factor", _xOffFactor, 0.5);
  prvNh.param<double>("y_off_factor", _yOffFactor, 0.5);
  prvNh.param<double>("x_offset", xOffset, 0.0);
  prvNh.param<double>("y_offset", yOffset, 0.0);


  prvNh.param<int>("map_size", iVar, 10);
  octaveFactor = static_cast<unsigned int>(iVar);
  prvNh.param<double>("cellsize", cellSize, 0.025);
  prvNh.param<int>("truncation_radius", iVar, 3);
  truncationRadius = static_cast<double>(iVar);
  prvNh.param<double>("occ_grid_time_interval", gridPublishInterval, 2.0);
  prvNh.param<double>("loop_rate", loopRateVar, 40.0);
  prvNh.param<std::string>("laser_topic", topicLaser, "scan");

  _loopRate = new ros::Rate(loopRateVar);
  _gridInterval = new ros::Duration(gridPublishInterval);

  if(octaveFactor > 15)
  {
    ROS_ERROR_STREAM("Error! Unknown map size -> set to default!" << std::endl);
    octaveFactor = 10;
  }
  //instanciate representation
  _grid = new obvious::TsdGrid(cellSize, obvious::LAYOUT_32x32, static_cast<obvious::EnumTsdGridLayout>(octaveFactor));  //obvious::LAYOUT_8192x8192
  _grid->setMaxTruncation(truncationRadius * cellSize);
  unsigned int cellsPerSide = pow(2, octaveFactor);
  double sideLength = static_cast<double>(cellsPerSide) * cellSize;
  ROS_INFO_STREAM("Creating representation with " << cellsPerSide << "x" << cellsPerSide << "cells, representating " <<
                  sideLength << "x" << sideLength << "m^2" << std::endl);
  //instanciate mapping threads
  _threadMapping = new ThreadMapping(_grid);
  _threadGrid    = new ThreadGrid(_grid, &_nh, xOffset, yOffset);

  ThreadLocalize* threadLocalize = NULL;
  ros::Subscriber subs;
  std::string nameSpace = "";

  //instanciate localization threads
  if(robotNbr == 1)  //single slam
  {
    threadLocalize = new ThreadLocalize(_grid, _threadMapping, &_nh, nameSpace, xOffset, yOffset);
    subs = _nh.subscribe(topicLaser, 1, &ThreadLocalize::laserCallBack, threadLocalize);
    _subsLaser.push_back(subs);
    _localizers.push_back(threadLocalize);
    ROS_INFO_STREAM("Single SLAM started" << std::endl);
  }
  else
  {
    for(unsigned int i = 0; i < robotNbr; i++)   //multi slam
    {
      std::stringstream sstream;
      sstream << "robot";
      sstream << i << "/namespace";
      std::string dummy = sstream.str();
      prvNh.param(dummy, nameSpace, std::string("default_ns"));
      threadLocalize = new ThreadLocalize(_grid, _threadMapping, &_nh, nameSpace, xOffset, yOffset);
      subs = _nh.subscribe(nameSpace + "/" + topicLaser, 1, &ThreadLocalize::laserCallBack, threadLocalize);
      _subsLaser.push_back(subs);
      _localizers.push_back(threadLocalize);
      ROS_INFO_STREAM("started for thread for " << nameSpace << std::endl);
    }
    ROS_INFO_STREAM("Multi SLAM started!");
  }
}
Пример #5
0
void ThreadLocalize::init(const sensor_msgs::LaserScan& scan)
{
  double localXoffset			= 0.0;
  double localYoffset			= 0.0;
  double localYawOffset			= 0.0;
  double maxRange				= 0.0;
  double minRange				= 0.0;
  double lowReflectivityRange	= 0.0;
  double footPrintWidth			= 0.0;
  double footPrintHeight		= 0.0;
  double footPrintXoffset		= 0.0;
  //std::string frameSensorMount;

  ros::NodeHandle prvNh("~");

  prvNh.param<double>(_nameSpace + "local_offset_x",localXoffset, 0.0);
  prvNh.param<double>(_nameSpace + "local_offset_y", localYoffset, 0.0);
  prvNh.param<double>(_nameSpace + "local_offset_yaw", localYawOffset, 0.0);
  prvNh.param<double>(_nameSpace + "max_range", maxRange, 30.0);
  prvNh.param<double>(_nameSpace + "min_range", minRange, 0.001);
  prvNh.param<double>(_nameSpace + "low_reflectivity_range", lowReflectivityRange, 2.0);
  prvNh.param<double>(_nameSpace + "footprint_width", footPrintWidth, 1.0);
  prvNh.param<double>(_nameSpace + "footprint_height", footPrintHeight, 1.0);
  prvNh.param<double>(_nameSpace + "footprint_x_offset", footPrintXoffset, 0.28);
  //prvNh.param<std::string>(_nameSpace + "frame_sensor_mount", frameSensorMount, "base_link");

//  if(!_tfListener.waitForTransform(scan.header.frame_id, frameSensorMount, ros::Time::now(), ros::Duration(0.5)))
//  {
//    std::cout << __PRETTY_FUNCTION__ << "looking up sensor mount frame failed " << std::endl;
//    _tfFrameSensorMount.setOrigin(tf::Vector3(0.0, 0.0, 0.0));
//    _tfFrameSensorMount.setRotation(tf::Quaternion(0.0, 0.0, 0.0, 1.0));
//  }
//  else
//  {
//    try
//    {
//      _tfListener.lookupTransform(scan.header.frame_id, frameSensorMount, ros::Time(0), _tfFrameSensorMount);
//    }
//    catch(tf::TransformException& ex)
//    {
//      std::cout << __PRETTY_FUNCTION__ << "looking up sensor mount frame failed " << ex.what() << std::endl;
//      _tfFrameSensorMount.setOrigin(tf::Vector3(0.0, 0.0, 0.0));
//      _tfFrameSensorMount.setRotation(tf::Quaternion(0.0, 0.0, 0.0, 1.0));
//    }
//  }

  const double phi		= localYawOffset;
  const double startX	= _gridWidth * 0.5 + _xOffset + localXoffset;
  const double startY	= _gridHeight * 0.5 + _yOffset + localYoffset;
  double tf[9] 			= {std::cos(phi), 	-std::sin(phi), 	startX,
                       std::sin(phi), 	 std::cos(phi),		startY,
                                   0,				         0,				1};
//  obvious::Matrix Tbla(3, 3);
//  Tbla = this->tfToObviouslyMatrix3x3(_tfFrameSensorMount);
  //Tbla.invert();
//  std::cout << __PRETTY_FUNCTION__ << " inverted\n";
//  Tbla.print();
  //std::cout << std::endl;



  obvious::Matrix Tinit(3,3);
  Tinit.setData(tf);
//  Tinit =  Tbla * Tinit;

  //std::cout << __PRETTY_FUNCTION__ << "Tinit = \n " << Tinit << std::endl;

  double inc 			= scan.angle_increment;
  double angle_min		= scan.angle_min;
  vector<float> ranges 	= scan.ranges;

  if(scan.angle_increment < 0.0 && scan.angle_min > 0)
  {
    _reverseScan 	= true;
    inc			= -inc;
    angle_min		= -angle_min;
    std::reverse(ranges.begin(), ranges.end());
  }
  _sensor = new obvious::SensorPolar2D(ranges.size(), inc, angle_min, maxRange, minRange, lowReflectivityRange);
  _sensor->setRealMeasurementData(ranges, 1.0);

  _sensor->setStandardMask();
  _sensor->transform(&Tinit);
  obfloat t[2] = {startX + footPrintXoffset, startY};
  if(!_grid.freeFootprint(t, footPrintWidth, footPrintHeight))
    ROS_ERROR_STREAM("Localizer (" << _nameSpace << ") warning! Footprint could not be freed! \n");
  if(!_mapper.initialized())
    _mapper.initPush(_sensor);
  _initialized = true;
  //_sensor->transform()
  this->unblock();			//Method from ThreadSLAM to set a thread from sleep mode to run mode
}
Пример #6
0
ThreadLocalize::ThreadLocalize(obvious::TsdGrid* grid, ThreadMapping* mapper, ros::NodeHandle* nh, std::string nameSpace,
    const double xOffset, const double yOffset):
										    ThreadSLAM(*grid),
										    _nh(nh),
										    _mapper(*mapper),
										    _sensor(NULL),		///todo nullptr?
										    _initialized(false),
										    _gridWidth(grid->getCellsX() * grid->getCellSize()),
										    _gridHeight(grid->getCellsY() * grid->getCellSize()),
										    _gridOffSetX(-1.0 * (grid->getCellsX() * grid->getCellSize() * 0.5 + xOffset)),
										    _gridOffSetY(-1.0 * (grid->getCellsY() * grid->getCellSize() * 0.5 + yOffset)),
										    _xOffset(xOffset),
										    _yOffset(yOffset),
										    _nameSpace(nameSpace),
										    _stampLaser(ros::Time::now())
{
  // ThreadLocalize* threadLocalize = NULL;		///todo wofür hab ich das hier eig. variable wird nicht benutzt?

  double distFilterMax  		= 0.0;
  double distFilterMin			= 0.0;
  int icpIterations				= 0;
  std::string poseTopic;
  double durationWaitForOdom	= 0.0;
  ///RandomMatcher options
  int trials					= 0;
  int sizeControlSet			= 0;
  double epsThresh				= 0.0;
  double zhit					= 0.0;
  double zphi					= 0.0;
  double zshort					= 0.0;
  double zmax					= 0.0;
  double zrand					= 0.0;
  double percentagePointsInC	= 0.0;
  double rangemax				= 0.0;
  double sigphi					= 0.0;
  double sighit					= 0.0;
  double lamshort				= 0.0;
  double maxAngleDiff			= 0.0;
  double maxAnglePenalty		= 0.0;
  int paramInt					= 0;
  int iVar 						= 0;

  /*** Read parameters from ros parameter server. Use namespace if provided. Multirobot use. ***/
  _nameSpace = nameSpace;
  std::string::iterator it = _nameSpace.end() - 1;		//stores last symbol of nameSpace
  if(*it != '/' && _nameSpace.size()>0)
    _nameSpace += "/";
  //pose
  poseTopic = _nameSpace + poseTopic;

  ros::NodeHandle prvNh("~");
  //ICP Options
  prvNh.param<double>(_nameSpace + "dist_filter_max", distFilterMax, DIST_FILT_MAX);
  prvNh.param<double>(_nameSpace + "dist_filter_min", distFilterMin, DIST_FILT_MIN);
  prvNh.param<int>(_nameSpace + "icp_iterations", icpIterations, ICP_ITERATIONS);

  prvNh.param(_nameSpace + "pose_topic", poseTopic, std::string("default_ns/pose"));
  prvNh.param("tf_base_frame", _tfBaseFrameId, std::string("/map"));
  prvNh.param(_nameSpace + "tf_child_frame", _tfChildFrameId, std::string("default_ns/laser"));
  // prvNh.param("tf_odom_frame", _tfOdomFrameId, std::string("wheelodom"));
  prvNh.param("tf_footprint_frame", _tfFootprintFrameId, std::string("base_footprint"));
  prvNh.param<double>("reg_trs_max", _trnsMax, TRNS_THRESH);
  prvNh.param<double>("reg_sin_rot_max", _rotMax, ROT_THRESH);
  prvNh.param<double>("max_velocity_lin", _trnsVelocityMax, TRNS_VEL_MAX);
  prvNh.param<double>("max_velocity_rot", _rotVelocityMax, ROT_VEL_MAX);
  prvNh.param<bool>("ude_odom_rescue", _useOdomRescue, false);
  prvNh.param<double>("wait_for_odom_tf", durationWaitForOdom, 1.0);
  prvNh.param<double>("laser_min_range", _lasMinRange, 0.0);
  prvNh.param<int>("trials", trials, 100);
  prvNh.param<int>("sizeControlSet", sizeControlSet, 140);
  prvNh.param<double>("epsThresh", epsThresh, 0.15);
  prvNh.param<double>("zhit", zhit, 0.45);
  prvNh.param<double>("zphi", zphi, 0);
  prvNh.param<double>("zshort", zshort, 0.25);
  prvNh.param<double>("zmax", zmax, 0.05);
  prvNh.param<double>("zrand", zrand, 0.25);
  prvNh.param<double>("percentagePointsInC", percentagePointsInC, 0.9);
  prvNh.param<double>("rangemax", rangemax, 20);
  prvNh.param<double>("sigphi", sigphi, M_PI / 180.0 * 3);
  prvNh.param<double>("sighit", sighit, 0.2);
  prvNh.param<double>("lamshort", lamshort, 0.08);
  prvNh.param<double>("maxAngleDiff", maxAngleDiff, 3.0);
  prvNh.param<double>("maxAnglePenalty", maxAnglePenalty, 0.5);
  //ransac options
  prvNh.param<int>(nameSpace + "ransac_trials", paramInt, RANSAC_TRIALS);						///todo WARUM HIER nameSpace und nicht _nameSpace wie unten
  _ranTrials = static_cast<unsigned int>(paramInt);
  prvNh.param<double>(nameSpace + "ransac_eps_thresh", _ranEpsThresh, RANSAC_EPS_THRESH);
  prvNh.param<int>(nameSpace + "ransac_ctrlset_size", paramInt, RANSAC_CTRL_SET_SIZE);
  _ranSizeCtrlSet = static_cast<unsigned int>(paramInt);
  prvNh.param<double>(_nameSpace + "ransac_phi_max", _ranPhiMax, 30.0);

  prvNh.param<int>(_nameSpace + "registration_mode", iVar, ICP);

  _regMode = static_cast<EnumRegModes>(iVar);

  //Align laserscans
  switch(_regMode)
  {
  case ICP:
    //no instance needed
    break;
  case EXP:
    _RandomNormalMatcher 	= new obvious::RandomNormalMatching(trials, epsThresh, sizeControlSet);
    break;
  case PDF:
    _PDFMatcher 			= new obvious::PDFMatching(trials, epsThresh, sizeControlSet, zhit, zphi, zshort, zmax, zrand, percentagePointsInC, rangemax,
        sigphi, sighit, lamshort, maxAngleDiff, maxAnglePenalty);
    break;
  case TSD:
    _TSD_PDFMatcher 		= new obvious::TSD_PDFMatching(_grid, trials, epsThresh, sizeControlSet, zrand);
    break;
  default:
    ROS_ERROR_STREAM("Unknown registration mode " << _regMode << " use default = ICP." << std::endl);
  }

  //_odomAnalyzer 		= NULL;			///todo nullptr? unten auch?
  _waitForOdomTf 		= ros::Duration(durationWaitForOdom);
  _odomTfIsValid 		= false;
  _regMode 				= static_cast<EnumRegModes>(iVar);
  _modelCoords			= NULL;
  _modelNormals			= NULL;
  _maskM				= NULL;
  _rayCaster			= NULL;			///todo wofür wird der genullt? wird gleich hier unten initialisiert
  _scene				= NULL;
  _maskS				= NULL;
  _lastPose				= new obvious::Matrix(3, 3);
  _rayCaster			= new obvious::RayCastPolar2D();
  _assigner				= new obvious::FlannPairAssignment(2);
  _filterDist			= new obvious::DistanceFilter(distFilterMax, distFilterMin, icpIterations - 10);
  _filterReciprocal		= new obvious::ReciprocalFilter();
  _estimator 			= new obvious::ClosedFormEstimator2D();


  //configure ICP
  _filterBounds 		= new obvious::OutOfBoundsFilter2D(grid->getMinX(), grid->getMaxX(), grid->getMinY(), grid->getMaxY());
  _assigner->addPreFilter(_filterBounds);
  _assigner->addPostFilter(_filterDist);
  _assigner->addPostFilter(_filterReciprocal);
  _icp					= new obvious::Icp(_assigner, _estimator);
  _icp->setMaxRMS(0.0);
  _icp->setMaxIterations(icpIterations);
  _icp->setConvergenceCounter(icpIterations);

  _posePub						= _nh->advertise<geometry_msgs::PoseStamped>(poseTopic, 1);
  _poseStamped.header.frame_id	= _tfBaseFrameId;
  _tf.frame_id_					= _tfBaseFrameId;
  _tf.child_frame_id_			= _nameSpace + _tfChildFrameId;

  _reverseScan					= false;
  //_odomAnalyzer = new OdometryAnalyzer(_grid);
}