roslaser2d.h
Go to the documentation of this file.
00001 // Copyright (c) 2009-2010 Rosen Diankov
00002 // 
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //     http://www.apache.org/licenses/LICENSE-2.0
00007 // 
00008 // Unless required by applicable law or agreed to in writing, software
00009 // distributed under the License is distributed on an "AS IS" BASIS,
00010 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00011 // See the License for the specific language governing permissions and
00012 // limitations under the License.
00013 //
00014 // \author Rosen Diankov
00015 #ifndef OPENRAVE_ROSBASELASER_H
00016 #define OPENRAVE_ROSBASELASER_H
00017 
00018 #include "plugindefs.h"
00019 
00020 #include <sensor_msgs/LaserScan.h>
00021 
00023 class ROSLaser2D : public SensorBase
00024 {
00025  protected:
00026     class BaseLaser2DXMLReader : public BaseXMLReader
00027     {
00028     public:
00029     BaseLaser2DXMLReader(boost::shared_ptr<ROSLaser2D> psensor) : _psensor(psensor) {}
00030         virtual ~BaseLaser2DXMLReader() {}
00031 
00032         virtual ProcessElement startElement(const std::string& name, const std::list<std::pair<std::string,std::string> >& atts)
00033         {
00034             if( !!_pcurreader ) {
00035                 if( _pcurreader->startElement(name,atts) == PE_Support )
00036                     return PE_Support;
00037                 return PE_Ignore;
00038             }
00039 
00040             ss.str("");
00041             return (name != "sensor" && name != "scantopic" && name != "show" && name != "color") ? PE_Support : PE_Pass;
00042         }
00043 
00044         virtual bool endElement(const std::string& name)
00045         {    
00046             if( !!_pcurreader ) {
00047                 if( _pcurreader->endElement(name) )
00048                     _pcurreader.reset();
00049                 return false;
00050             }
00051             else if( name == "sensor" )
00052                 return true;
00053             else if( name == "scantopic" )
00054                 ss >> _psensor->scantopic;
00055             else if( name == "show" )
00056                 ss >> _psensor->_bRenderData;
00057             else if( name == "color" ) {
00058                 ss >> _psensor->_vColor.x >> _psensor->_vColor.y >> _psensor->_vColor.z;
00059                 // ok if not everything specified
00060                 if( !ss )
00061                     ss.clear();
00062             }
00063             else
00064                 RAVELOG_WARNA(str(boost::format("bad tag: %s")%name));
00065 
00066             if( !ss )
00067                 RAVELOG_WARNA(str(boost::format("error parsing %s\n")%name));
00068 
00069             return false;
00070         }
00071 
00072         virtual void characters(const std::string& ch)
00073         {
00074             if( !!_pcurreader )
00075                 _pcurreader->characters(ch);
00076             else {
00077                 ss.clear();
00078                 ss << ch;
00079             }
00080         }
00081 
00082     protected:
00083         boost::shared_ptr<ROSLaser2D> _psensor;
00084         BaseXMLReaderPtr _pcurreader;
00085         stringstream ss;
00086     };
00087 
00088 public:
00089     static BaseXMLReaderPtr CreateXMLReader(InterfaceBasePtr ptr, const std::list<std::pair<std::string,std::string> >& atts)
00090     {
00091         return BaseXMLReaderPtr(new BaseLaser2DXMLReader(boost::dynamic_pointer_cast<ROSLaser2D>(ptr)));
00092     }
00093 
00094     ROSLaser2D(EnvironmentBasePtr penv) : SensorBase(penv)
00095     {
00096         __description = ":Interface Author: Rosen Diankov\n\nConnects to a ROS LaserScan message that receives laser data in real-time and provides that information to the OpenRAVE environment";
00097         _pgeom.reset(new LaserGeomData());
00098         _pdata.reset(new LaserSensorData());
00099 
00100         _bDestroyThread = true;
00101         _bRenderData = false;
00102         _bRenderGeometry = true;
00103         _bPower = true;
00104         _bUpdatePlot = true;
00105         scantopic = "/scan";
00106         _vColor = RaveVector<float>(0.5f,0.5f,1,1);
00107         _pgeom->min_angle[0] = _pgeom->min_angle[1] = 0;
00108         _pgeom->max_angle[0] = _pgeom->max_angle[1] = 0;
00109         _pgeom->resolution[0] = _pgeom->resolution[1] = 0;
00110         _pgeom->max_range = 0;
00111     }
00112     virtual ~ROSLaser2D()
00113     {
00114         _Reset();
00115     }
00116     
00117     virtual int Configure(ConfigureCommand command, bool blocking)
00118     {
00119         switch(command) {
00120         case CC_PowerOn:
00121             _bPower = true;
00122             return _bPower;
00123         case CC_PowerOff:
00124             _bPower = false;
00125             _Reset();
00126             return _bPower;
00127         case CC_PowerCheck:
00128             return _bPower;
00129         case CC_RenderDataOn:
00130             _bRenderData = true;
00131             _Reset();
00132             startsubscriptions();
00133             return _bRenderData;
00134         case CC_RenderDataOff: {
00135             boost::mutex::scoped_lock lock(_mutexdata);
00136             _listGraphicsHandles.clear();
00137             _bRenderData = false;
00138             return _bRenderData;
00139         }
00140         case CC_RenderDataCheck:
00141             return _bRenderData;
00142         case CC_RenderGeometryOn:
00143             _bRenderGeometry = true;
00144             _RenderGeometry();
00145             return _bRenderData;
00146         case CC_RenderGeometryOff: {
00147             boost::mutex::scoped_lock lock(_mutexdata);
00148             _graphgeometry.reset();
00149             _bRenderGeometry = false;
00150             return _bRenderData;
00151         }
00152         case CC_RenderGeometryCheck:
00153             return _bRenderGeometry;
00154         }
00155         throw openrave_exception(str(boost::format("SensorBase::Configure: unknown command 0x%x")%command));
00156     }
00157 
00158     virtual void startsubscriptions()
00159     {
00160         int argc=0;
00161         ros::init(argc,NULL,"openrave", ros::init_options::NoSigintHandler|ros::init_options::AnonymousName);
00162 
00163         if( ros::master::check() ) {
00164             _node.reset(new ros::NodeHandle());
00165             _submstate = _node->subscribe(scantopic, 10, &ROSLaser2D::newscan_cb, this);
00166 
00167             _bDestroyThread = false;
00168             _threadsensor = boost::thread(boost::bind(&ROSLaser2D::_SensorThread, this));
00169         }
00170         else
00171             RAVELOG_WARNA("failed to detect ROS master");
00172     }
00173 
00174     virtual bool SimulationStep(dReal fTimeElapsed)
00175     {
00176         if( _bUpdatePlot ) {
00177             _RenderGeometry();
00178         }
00179 
00180         return true;
00181     }
00182 
00183     virtual SensorGeometryPtr GetSensorGeometry(SensorType type)
00184     {
00185         if( type == ST_Invalid || type == ST_Laser ) {
00186             LaserGeomData* pgeom = new LaserGeomData();
00187             *pgeom = *_pgeom;
00188             return SensorGeometryPtr(pgeom);
00189         }
00190         return SensorGeometryPtr();
00191     }
00192 
00193     virtual SensorDataPtr CreateSensorData(SensorType type)
00194     {
00195         if( type == ST_Invalid || type == ST_Laser ) {
00196             return SensorDataPtr(new LaserSensorData());
00197         }
00198         return SensorDataPtr();
00199     }
00200 
00201     virtual bool GetSensorData(SensorDataPtr psensordata)
00202     {
00203         if( psensordata->GetType() == ST_Laser ) {
00204             boost::mutex::scoped_lock lock(_mutexdata);
00205             *boost::dynamic_pointer_cast<LaserSensorData>(psensordata) = *_pdata;
00206             return true;
00207         }
00208         return false;
00209     }
00210 
00211     virtual bool Supports(SensorType type) { return type == ST_Laser; }
00212 
00213     virtual bool SendCommand(std::ostream& os, std::istream& is)
00214     {
00215         string cmd;
00216         is >> cmd;
00217         if( !is )
00218             throw openrave_exception("no command",ORE_InvalidArguments);
00219         std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower);
00220 
00221         if( cmd == "show" || cmd == "render" ) {
00222             is >> _bRenderData;
00223         }
00224         else if( cmd == "power") {
00225             is >> _bPower;
00226             if( _bPower && !_node ) {
00227                 startsubscriptions();
00228             }
00229             else if( !_bPower && !!_node ) {
00230                 _submstate.shutdown();
00231                 _node.reset();
00232                 boost::mutex::scoped_lock lock(_mutexdata);
00233                 _listGraphicsHandles.resize(0);
00234             }
00235         }
00236 
00237         return !!is;
00238     }
00239 
00240     virtual void SetTransform(const Transform& trans)
00241     {
00242         _trans = trans;
00243         _bUpdatePlot = true;
00244     }
00245 
00246     virtual Transform GetTransform() { return _trans; }
00247 
00248  protected:
00249 
00250     virtual void _Reset()
00251     {
00252         boost::mutex::scoped_lock lock(_mutexdata);
00253 
00254         _listGraphicsHandles.clear();
00255         _graphgeometry.reset();
00256 
00257         _bUpdatePlot = true;
00258         _pdata->positions.clear();
00259         _pdata->ranges.clear();
00260         _pdata->intensity.clear();
00261 
00262         _bDestroyThread = true;
00263         _submstate.shutdown();
00264         _node.reset();
00265         _threadsensor.join();
00266     }
00267 
00268     virtual void _RenderGeometry()
00269     {
00270         if( !_bRenderGeometry ) {
00271             return;
00272         }
00273         Transform t = GetLaserPlaneTransform();
00274         if( _pgeom->max_angle[0] > _pgeom->min_angle[0] ) {
00275             if( !_graphgeometry ) {
00276                 int N = 10;
00277                 vector<RaveVector<float> > viconpoints;
00278                 vector<int> viconindices;
00279                 viconpoints.resize(N+2);
00280                 viconindices.resize(3*N);
00281                 viconpoints[0] = t.trans;
00282                 Transform trot;
00283 
00284                 for(int i = 0; i <= N; ++i) {
00285                     dReal fang = _pgeom->min_angle[0] + (_pgeom->max_angle[0]-_pgeom->min_angle[0])*(float)i/(float)N;
00286                     trot.rot = quatFromAxisAngle(Vector(0,0,1), fang);
00287                     viconpoints[i+1] = trot.rotate(Vector(0.05f,0,0));
00288 
00289                     if( i < N ) {
00290                         viconindices[3*i+0] = 0;
00291                         viconindices[3*i+1] = i+1;
00292                         viconindices[3*i+2] = i+2;
00293                     }
00294                 }
00295 
00296                 RaveVector<float> vcolor = _vColor*0.5f;
00297                 vcolor.w = 0.7f;
00298                 _graphgeometry = GetEnv()->drawtrimesh(&viconpoints[0][0], sizeof(viconpoints[0]), &viconindices[0], N, vcolor);
00299             }
00300             if( !!_graphgeometry ) {
00301                 _graphgeometry->SetTransform(t);
00302             }
00303         }
00304     }
00305     virtual Transform GetLaserPlaneTransform() { return _trans; }
00306     virtual void newscan_cb(const sensor_msgs::LaserScanConstPtr& msg)
00307     {
00308         boost::mutex::scoped_lock lock(_mutexdata);
00309         _pgeom->min_angle[0] = msg->angle_min;
00310         _pgeom->max_angle[0] = msg->angle_max;
00311         _pgeom->resolution[0] = msg->angle_increment;
00312         _pgeom->max_range = msg->range_max;
00313 
00314         Transform t = _trans;
00315         _pdata->positions.resize(msg->ranges.size());
00316         _pdata->ranges.resize(msg->ranges.size());
00317         _pdata->intensity.resize(msg->intensities.size());
00318     
00319         float ang = msg->angle_min;
00320         for(size_t i = 0; i < msg->ranges.size(); ++i, ang += msg->angle_increment) {
00321             _pdata->positions[i] = _trans.trans;
00322             float range = max(msg->range_min,min(msg->range_max,msg->ranges[i]));
00323             Vector v(range*cosf(ang),range*sinf(ang),0);
00324             _pdata->ranges[i] = t.rotate(v);
00325         }
00326 
00327         for(int i = 0; i < (int)_pdata->intensity.size(); ++i) {
00328             _pdata->intensity[i] = msg->intensities[i];
00329         }
00330         if( _bRenderData && msg->ranges.size() > 0 ) {
00331 
00332             // If can render, check if some time passed before last update
00333             list<GraphHandlePtr> listhandles;
00334             int N = 0;
00335             vector<RaveVector<float> > vpoints;
00336             vector<int> vindices;
00337 
00338             {
00339                 // Lock the data mutex and fill the arrays used for rendering
00340                 N = (int)_pdata->ranges.size();
00341                 vpoints.resize(N+1);
00342                 ang = msg->angle_min;
00343                 for(int i = 0; i < N; ++i, ang += msg->angle_increment) {
00344                     float range = max(msg->range_min,min(msg->range_max,msg->ranges[i]));
00345                     vpoints[i] = t * Vector(range*cosf(ang),range*sinf(ang),0);
00346                 }
00347                 vpoints[N] = t.trans;
00348             }
00349 
00350             // render the transparent fan
00351             vindices.resize(3*(N-1));
00352             
00353             for(int i = 0; i < N-1; ++i) {
00354                 vindices[3*i+0] = i;
00355                 vindices[3*i+1] = i+1;
00356                 vindices[3*i+2] = N;
00357             }
00358 
00359             _vColor.w = 1;
00360             // Render points at each measurement, and a triangle fan for the entire free surface of the laser
00361             listhandles.push_back(GetEnv()->plot3(&vpoints[0].x, N, sizeof(vpoints[0]), 5.0f, _vColor));
00362             
00363             _vColor.w = 0.2f;
00364             listhandles.push_back(GetEnv()->drawtrimesh(&vpoints[0][0], sizeof(vpoints[0]), &vindices[0], N-1, _vColor));
00365             
00366             _listGraphicsHandles.swap(listhandles);
00367         }
00368         else { // destroy graphs
00369             _listGraphicsHandles.clear();
00370         }
00371     }
00372 
00373     void _SensorThread()
00374     {
00375         while(!_bDestroyThread) {
00376             ros::spinOnce();
00377             usleep(1000); // query every 1ms
00378         }
00379     }
00380 
00381     boost::shared_ptr<ros::NodeHandle> _node;
00382     ros::Subscriber _submstate;
00383 
00384     boost::shared_ptr<LaserGeomData> _pgeom;
00385     boost::shared_ptr<LaserSensorData> _pdata;
00386 
00387     // more geom stuff
00388     string scantopic;
00389     RaveVector<float> _vColor;
00390     
00391     Transform _trans;
00392     list<GraphHandlePtr> _listGraphicsHandles;
00393     GraphHandlePtr _graphgeometry;
00394 
00395     boost::mutex _mutexdata;
00396     boost::thread _threadsensor;
00397     bool _bDestroyThread;
00398 
00399     bool _bRenderData, _bRenderGeometry, _bPower;
00400     bool _bUpdatePlot;
00401 
00402     friend class BaseLaser2DXMLReader;
00403 };
00404 
00405 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


openrave_sensors
Author(s): Rosen Diankov (rosen.diankov@gmail.com)
autogenerated on Sat Mar 23 2013 18:07:40