00001 /* 00002 * Copyright 2016 Open Source Robotics Foundation 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 * 00016 */ 00017 00018 #include "ROSProximityRayPlugin.hh" 00019 00020 #include <string> 00021 00022 using namespace gazebo; 00023 // Register this plugin with the simulator 00024 GZ_REGISTER_SENSOR_PLUGIN(ROSProximityRayPlugin) 00025 00026 00027 // Constructor 00028 ROSProximityRayPlugin::ROSProximityRayPlugin() 00029 { 00030 } 00031 00033 // Destructor 00034 ROSProximityRayPlugin::~ROSProximityRayPlugin() 00035 { 00036 this->rosnode->shutdown(); 00037 } 00038 00039 void ROSProximityRayPlugin::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf) 00040 { 00041 // Make sure the ROS node for Gazebo has already been initialized 00042 if (!ros::isInitialized()) 00043 { 00044 ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. " 00045 << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)"); 00046 return; 00047 } 00048 00049 ProximityRayPlugin::Load(_parent, _sdf); 00050 00051 // Read ROS-specific sdf tags 00052 this->robotNamespace = ""; 00053 if (_sdf->HasElement("robotNamespace")) 00054 { 00055 this->robotNamespace = _sdf->GetElement("robotNamespace")->Get<std::string>() + "/"; 00056 } 00057 00058 // Over-ride topics from the ProximityRayPlugin which may contain ~s 00059 this->stateTopic = _parent->Name(); 00060 if (_sdf->HasElement("output_state_topic")) 00061 { 00062 this->stateTopic = _sdf->Get<std::string>("output_state_topic"); 00063 } 00064 00065 this->stateChangeTopic = _parent->Name() + "_change"; 00066 if (_sdf->HasElement("output_change_topic")) 00067 { 00068 this->stateChangeTopic = _sdf->Get<std::string>("output_change_topic"); 00069 } 00070 00071 this->frameId = _parent->Name() + "_frame"; 00072 if (_sdf->HasElement("frame_id")) 00073 { 00074 this->frameId = _sdf->Get<std::string>("frame_id"); 00075 } 00076 this->state_msg.header.frame_id = this->frameId; 00077 00078 this->rosnode = new ros::NodeHandle(this->robotNamespace); 00079 00080 // Initialize the publishers 00081 this->statePub = this->rosnode->advertise<osrf_gear::Proximity>( 00082 this->stateTopic, 1, true); 00083 this->stateChangePub = this->rosnode->advertise<osrf_gear::Proximity>( 00084 this->stateChangeTopic, 1, true); 00085 00086 // Callback for laser scans 00087 this->newLaserScansConnection = 00088 this->parentSensor->LaserShape()->ConnectNewLaserScans( 00089 std::bind(&ROSProximityRayPlugin::OnNewLaserScans, this)); 00090 00091 } 00092 00094 // Update the controller 00095 void ROSProximityRayPlugin::OnNewLaserScans() 00096 { 00097 auto now = this->world->GetSimTime(); 00098 bool stateChanged = this->ProcessScan(); 00099 this->state_msg.header.stamp.sec = now.sec; 00100 this->state_msg.header.stamp.nsec = now.nsec; 00101 this->state_msg.object_detected = this->objectDetected; 00102 this->state_msg.min_range = this->sensingRangeMin; 00103 this->state_msg.max_range = this->sensingRangeMax; 00104 this->statePub.publish(this->state_msg); 00105 if (stateChanged) 00106 { 00107 gzdbg << this->parentSensor->Name() << ": change in sensor state\n"; 00108 this->stateChangePub.publish(this->state_msg); 00109 } 00110 } 00111