00001
00002
00003
00004
00005
00006
00007
00008 #include "SlamNode.h"
00009 #include "ThreadMapping.h"
00010 #include "ThreadGrid.h"
00011 #include "ThreadLocalize.h"
00012
00013 #include "obcore/math/mathbase.h"
00014
00015
00016 namespace ohm_tsd_slam
00017 {
00018 SlamNode::SlamNode(void)
00019 {
00020 ros::NodeHandle prvNh("~");
00021 int iVar = 0;
00022 double gridPublishInterval = 0.0;
00023 double loopRateVar = 0.0;
00024 double truncationRadius = 0.0;
00025 double cellSize = 0.0;
00026 unsigned int octaveFactor = 0;
00027 double xOffset = 0.0;
00028 double yOffset = 0.0;
00029 std::string topicLaser;
00030 prvNh.param<int>("robot_nbr", iVar, 1);
00031 unsigned int robotNbr = static_cast<unsigned int>(iVar);
00032 prvNh.param<double>("x_off_factor", _xOffFactor, 0.5);
00033 prvNh.param<double>("y_off_factor", _yOffFactor, 0.5);
00034 prvNh.param<double>("x_offset", xOffset, 0.0);
00035 prvNh.param<double>("y_offset", yOffset, 0.0);
00036
00037
00038 prvNh.param<int>("map_size", iVar, 10);
00039 octaveFactor = static_cast<unsigned int>(iVar);
00040 prvNh.param<double>("cellsize", cellSize, 0.025);
00041 prvNh.param<int>("truncation_radius", iVar, 3);
00042 truncationRadius = static_cast<double>(iVar);
00043 prvNh.param<double>("occ_grid_time_interval", gridPublishInterval, 2.0);
00044 prvNh.param<double>("loop_rate", loopRateVar, 40.0);
00045 prvNh.param<std::string>("laser_topic", topicLaser, "scan");
00046
00047 _loopRate = new ros::Rate(loopRateVar);
00048 _gridInterval = new ros::Duration(gridPublishInterval);
00049
00050 if(octaveFactor > 15)
00051 {
00052 ROS_ERROR_STREAM("Error! Unknown map size -> set to default!" << std::endl);
00053 octaveFactor = 10;
00054 }
00055
00056 _grid = new obvious::TsdGrid(cellSize, obvious::LAYOUT_32x32, static_cast<obvious::EnumTsdGridLayout>(octaveFactor));
00057 _grid->setMaxTruncation(truncationRadius * cellSize);
00058 unsigned int cellsPerSide = pow(2, octaveFactor);
00059 double sideLength = static_cast<double>(cellsPerSide) * cellSize;
00060 ROS_INFO_STREAM("Creating representation with " << cellsPerSide << "x" << cellsPerSide << "cells, representating " <<
00061 sideLength << "x" << sideLength << "m^2" << std::endl);
00062
00063 _threadMapping = new ThreadMapping(_grid);
00064 _threadGrid = new ThreadGrid(_grid, &_nh, xOffset, yOffset);
00065
00066 ThreadLocalize* threadLocalize = NULL;
00067 ros::Subscriber subs;
00068 std::string nameSpace;
00069
00070
00071 if(robotNbr == 1)
00072 {
00073 nameSpace = "";
00074 threadLocalize = new ThreadLocalize(_grid,_threadMapping, &_nh, nameSpace, xOffset, yOffset);
00075 subs = _nh.subscribe(topicLaser, 1, &ThreadLocalize::laserCallBack, threadLocalize);
00076 _subsLaser.push_back(subs);
00077 _localizers.push_back(threadLocalize);
00078 ROS_INFO_STREAM("Single SLAM started" << std::endl);
00079 }
00080 else
00081 {
00082 for(unsigned int i = 0; i < robotNbr; i++)
00083 {
00084 std::stringstream sstream;
00085 sstream << "robot";
00086 sstream << i << "/namespace";
00087 std::string dummy = sstream.str();
00088 prvNh.param(dummy, nameSpace, std::string("default_ns"));
00089 threadLocalize = new ThreadLocalize(_grid,_threadMapping, &_nh, nameSpace, xOffset, yOffset);
00090 subs = _nh.subscribe(nameSpace + "/" + topicLaser, 1, &ThreadLocalize::laserCallBack, threadLocalize);
00091 _subsLaser.push_back(subs);
00092 _localizers.push_back(threadLocalize);
00093 ROS_INFO_STREAM("started for thread for " << nameSpace << std::endl);
00094 }
00095 ROS_INFO_STREAM("Multi SLAM started!");
00096 }
00097 }
00098
00099 SlamNode::~SlamNode()
00100 {
00101
00102 for(std::vector<ThreadLocalize*>::iterator iter = _localizers.begin(); iter < _localizers.end(); iter++)
00103 {
00104 (*iter)->terminateThread();
00105 while((*iter)->alive(THREAD_TERM_MS))
00106 usleep(THREAD_TERM_MS);
00107 delete *iter;
00108 }
00109 delete _loopRate;
00110 delete _gridInterval;
00111
00112 _threadGrid->terminateThread();
00113 while(_threadGrid->alive(THREAD_TERM_MS))
00114 usleep(THREAD_TERM_MS);
00115 delete _threadGrid;
00116 _threadMapping->terminateThread();
00117 while(_threadMapping->alive(THREAD_TERM_MS))
00118 usleep(THREAD_TERM_MS);
00119 delete _threadMapping;
00120 delete _grid;
00121 }
00122
00123 void SlamNode::timedGridPub(void)
00124 {
00125 static ros::Time lastMap = ros::Time::now();
00126 ros::Time curTime = ros::Time::now();
00127 if((curTime - lastMap).toSec() > _gridInterval->toSec())
00128 {
00129 _threadGrid->unblock();
00130 lastMap = ros::Time::now();
00131 }
00132 }
00133
00134 void SlamNode::run(void)
00135 {
00136 ROS_INFO_STREAM("Waiting for first laser scan to initialize node...\n");
00137 while(ros::ok())
00138 {
00139 ros::spinOnce();
00140 this->timedGridPub();
00141 _loopRate->sleep();
00142 }
00143 }
00144
00145 }