Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #include <range_gazebo_plugin/gazebo_ros_sonar.h>
00036 #include <gazebo/common/Event.hh>
00037 #include <gazebo/physics/physics.h>
00038 
00039 using namespace gazebo;
00040 
00041 GazeboRosSonar::GazeboRosSonar()
00042 {
00043 }
00044 
00045 GazeboRosSonar::~GazeboRosSonar()
00046 {
00047     sensor_->SetActive(false);
00048     event::Events::DisconnectWorldUpdateStart(updateConnection);
00049     node_handle_->shutdown();
00050     delete node_handle_;
00051 }
00052 
00053 void GazeboRosSonar::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
00054 {
00055     ROS_DEBUG("Starting range gazebo plugin");
00056 
00057     
00058     sensor_ = boost::shared_dynamic_cast<sensors::RaySensor>(_parent);
00059     if (!sensor_)
00060     {
00061         gzthrow("GazeboRosSonar requires a Ray Sensor as its parent");
00062         return;
00063     }
00064 
00065     
00066     std::string worldName = sensor_->GetWorldName();
00067     parent_ = gazebo::physics::get_world(worldName);
00068 
00069     this->namespace_ = "";
00070     if (_sdf->HasElement("robotNamespace"))
00071         this->namespace_ = _sdf->GetElement("robotNamespace")->GetValueString();
00072 
00073     if (!_sdf->HasElement("topicName"))
00074     {
00075         ROS_WARN("Range plugin missing <topicName>, defaults to sonar");
00076         this->topic_name_ = "sonar";
00077     }
00078     else
00079         this->topic_name_ = _sdf->GetElement("topicName")->GetValueString();
00080 
00081     if (!_sdf->HasElement("frameId"))
00082     {
00083         ROS_WARN("Range plugin missing <frameId>, defaults to sonar_base_link");
00084         this->frame_id_ = "sonar_base_link";
00085     }
00086     else
00087         this->frame_id_ = _sdf->GetElement("frameId")->GetValueString();
00088 
00089     if (!_sdf->HasElement("radiation"))
00090     {
00091         ROS_WARN("Range plugin missing <radiation>, defaults to ultrasound");
00092         this->radiation_ = "ultrasound";
00093 
00094     }
00095     else
00096         this->radiation_ = _sdf->GetElement("radiation")->GetValueString();
00097 
00098     if (!_sdf->HasElement("fov"))
00099     {
00100         ROS_WARN("Range plugin missing <fov>, defaults to 0.05");
00101         this->fov_ = 0.05;
00102     }
00103     else
00104         this->fov_ = _sdf->GetElement("fov")->GetValueDouble();
00105 
00106     if (!_sdf->HasElement("gaussianNoise"))
00107     {
00108         ROS_WARN("Range plugin missing <gaussianNoise>, defaults to 0.0");
00109         this->gaussian_noise_ = 0.0;
00110     }
00111     else
00112         this->gaussian_noise_ = _sdf->GetElement("gaussianNoise")->GetValueDouble();
00113 
00114     ROS_DEBUG("Loaded with values:   robotNamespace = %s, topicName = %s, frameId = %s, radiation = %s, fov = %f, noise = %f",
00115              this->namespace_.c_str(), this->topic_name_.c_str(),this->frame_id_.c_str(),this->radiation_.c_str(),
00116              this->fov_, this->gaussian_noise_);
00117 
00118     node_handle_ = new ros::NodeHandle(this->namespace_);
00119 
00120     range_.header.frame_id = frame_id_;
00121     if (radiation_==std::string("ultrasound"))
00122         range_.radiation_type = sensor_msgs::Range::ULTRASOUND;
00123     else
00124         range_.radiation_type = sensor_msgs::Range::INFRARED;
00125 
00126     range_.field_of_view = fov_;
00127     range_.max_range = sensor_->GetRangeMax();
00128     range_.min_range = sensor_->GetRangeMin();
00129 
00130 
00131     node_handle_ = new ros::NodeHandle(namespace_);
00132     publisher_ = node_handle_->advertise<sensor_msgs::Range>(topic_name_, 1);
00133 
00134     updateConnection = sensor_->GetLaserShape()->ConnectNewLaserScans(boost::bind(&GazeboRosSonar::Update, this));
00135 
00136     
00137     sensor_->SetActive(true);
00138 
00139     ROS_DEBUG("%s is active!",frame_id_.c_str());
00140 }
00141 
00142 
00144 
00145 double GazeboRosSonar::GaussianKernel(double mu,double sigma)
00146 {
00147     
00148     double U = (double)rand()/(double)RAND_MAX;             
00149     double V = (double)rand()/(double)RAND_MAX;             
00150     double X = sqrt(-2.0 * ::log(U)) * cos( 2.0*M_PI * V);
00151 
00152     
00153     X = sigma * X + mu;
00154     return X;
00155 }
00156 
00157 void GazeboRosSonar::Update()
00158 {
00159     
00160     if (!sensor_->IsActive())
00161         sensor_->SetActive(true);
00162 
00163     range_.header.stamp.sec  = (parent_->GetSimTime()).sec;
00164     range_.header.stamp.nsec = (parent_->GetSimTime()).nsec;
00165 
00166     
00167     range_.range = std::numeric_limits<sensor_msgs::Range::_range_type>::max();
00168 
00169     int num_ranges = sensor_->GetLaserShape()->GetSampleCount() * sensor_->GetLaserShape()->GetVerticalSampleCount();
00170 
00171     for(int i = 0; i < num_ranges; ++i) {
00172         double ray = sensor_->GetLaserShape()->GetRange(i);
00173         if (ray < range_.range) range_.range = ray;
00174     }
00175 
00176     
00177     if (range_.range < range_.max_range)
00178         range_.range = std::min(range_.range + this->GaussianKernel(0,gaussian_noise_), sensor_->GetRangeMax());
00179 
00180     publisher_.publish(range_);
00181 
00182 }
00183 
00184 GZ_REGISTER_SENSOR_PLUGIN(GazeboRosSonar)
00185