ProximityRayPlugin.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2016 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #include <functional>
18 #include <cstdio>
19 
20 #include <boost/algorithm/string/replace.hpp>
21 #include <gazebo/physics/physics.hh>
22 #include <gazebo/transport/Node.hh>
23 #include <gazebo/transport/Publisher.hh>
24 #include "ProximityRayPlugin.hh"
25 
26 using namespace gazebo;
27 
28 // Register this plugin with the simulator
29 GZ_REGISTER_SENSOR_PLUGIN(ProximityRayPlugin)
30 
33 {
34 }
35 
38 {
39  this->newLaserScansConnection.reset();
40 
41  this->parentSensor.reset();
42  this->world.reset();
43 }
44 
46 std::string ProximityRayPlugin::Topic(std::string topicName) const
47 {
48  std::string globalTopicName = "~/";
49  globalTopicName += this->parentSensor->Name() + "/" + this->GetHandle() + "/" + topicName;
50  boost::replace_all(globalTopicName, "::", "/");
51 
52  return globalTopicName;
53 }
54 
56 void ProximityRayPlugin::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
57 {
58  // Get the name of the parent sensor
59  this->parentSensor =
60  std::dynamic_pointer_cast<sensors::RaySensor>(_parent);
61 
62  if (!this->parentSensor)
63  gzthrow("ProximityRayPlugin requires a Ray Sensor as its parent");
64 
65  std::string worldName = this->parentSensor->WorldName();
66  this->world = physics::get_world(worldName);
67  this->node = transport::NodePtr(new transport::Node());
68  this->node->Init(worldName);
69 
70  if (_sdf->HasElement("time_delay"))
71  {
72  double time_delay = _sdf->Get<double>("time_delay");
73  this->parentSensor->SetUpdateRate(1.0/time_delay);
74  gzdbg << "Setting update rate of parent sensor to " << 1.0/time_delay << " Hz\n";
75  }
76  else {
77  gzdbg << "Using update rate of parent sensor: " << this->parentSensor->UpdateRate() << " Hz\n";
78  }
79 
80  if (_sdf->HasElement("output_state_topic"))
81  {
82  this->stateTopic = _sdf->Get<std::string>("output_state_topic");
83  }
84  else {
85  this->stateTopic = this->Topic("sensor_state");
86  }
87 
88  this->statePub =
89  this->node->Advertise<msgs::Header>(this->stateTopic, 50);
90 
91  if (_sdf->HasElement("output_change_topic"))
92  {
93  this->stateChangeTopic = _sdf->Get<std::string>("output_change_topic");
94  }
95  else {
96  this->stateChangeTopic = this->Topic("state_change");
97  }
98 
99  this->stateChangePub =
100  this->node->Advertise<msgs::Header>(this->stateChangeTopic, 50);
101 
102  // TODO: override sensor's range values
103  /*
104  if (_sdf->HasElement("sensing_range_min"))
105  {
106  this->sensingRangeMin = _sdf->Get<double>("sensing_range_min");
107  }
108  else {
109  this->sensingRangeMin = this->parentSensor->RangeMin();
110  }
111  gzdbg << "Using mininimum sensing range of: " << this->sensingRangeMin << " m\n";
112 
113  if (_sdf->HasElement("sensing_range_max"))
114  {
115  this->sensingRangeMax = _sdf->Get<double>("sensing_range_max");
116  }
117  else {
118  this->sensingRangeMax = this->parentSensor->RangeMax();
119  }
120  gzdbg << "Using maximum sensing range of: " << this->sensingRangeMax << " m\n";
121  */
122 
123  this->useLinkFrame = true;
124  if (_sdf->HasElement("use_link_frame"))
125  {
126  this->useLinkFrame = _sdf->Get<bool>("use_link_frame");
127  }
128  if (this->useLinkFrame)
129  {
130  std::string linkName = this->parentSensor->ParentName();
131  this->link = boost::dynamic_pointer_cast<physics::Link>(this->world->GetEntity(linkName));
132  }
133 
134  this->objectDetected = false;
136  this->parentSensor->LaserShape()->ConnectNewLaserScans(
137  std::bind(&ProximityRayPlugin::OnNewLaserScans, this));
138 }
139 
142 {
143  bool stateChanged = this->ProcessScan();
144 
145  // Fill message
146  std::lock_guard<std::mutex> lock(this->mutex);
147  msgs::Set(this->stateMsg.mutable_stamp(), this->world->GetSimTime());
148  this->stateMsg.set_index(this->objectDetected);
149 
150  // Publish sensor state message
151  if (this->statePub && this->statePub->HasConnections()) {
152  this->statePub->Publish(this->stateMsg);
153  }
154 
155  if (stateChanged)
156  {
157  // Publish state state change message
158  if (this->stateChangePub && this->stateChangePub->HasConnections()) {
159  this->stateChangePub->Publish(this->stateMsg);
160  }
161  }
162 }
163 
166 {
167  bool stateChanged = false;
168  // Prevent new scans from arriving while we're processing this one
169  this->parentSensor->SetActive(false);
170 
171  this->sensingRangeMax = this->parentSensor->RangeMax();
172  this->sensingRangeMin = this->parentSensor->RangeMin();
173  std::vector<double> ranges;
174  this->parentSensor->Ranges(ranges);
175 
176  bool objectDetected = false;
177 
178  for (unsigned int i = 0; i<ranges.size(); i++){
179  double range = ranges[i];
180  // TODO: determine detections in cylindrical shape not spherical
181  if (range < this->sensingRangeMax and range > this->sensingRangeMin) {
182  objectDetected = true;
183  break;
184  }
185  }
186 
187  if (objectDetected) {
188  if (!this->objectDetected) {
189  gzdbg << "Object detected\n";
190  stateChanged = true;
191  }
192  this->objectDetected = true;
193  }
194  else
195  {
196  if (this->objectDetected) {
197  gzdbg << "Object no longer detected\n";
198  stateChanged = true;
199  }
200  this->objectDetected = false;
201  }
202 
203  if (this->useLinkFrame)
204  {
205  // TODO: deal with sensors oriented differently
206  auto sensorPose = this->parentSensor->Pose();
207  this->sensingRangeMin += sensorPose.Pos().X();
208  this->sensingRangeMax += sensorPose.Pos().X();
209  }
210 
211  this->parentSensor->SetActive(true); // this seems to happen automatically, not sure if a bug
212 
213  return stateChanged;
214 }
event::ConnectionPtr newLaserScansConnection
The connection tied to ProximityRayPlugin::OnNewLaserScans()
physics::WorldPtr world
Pointer to world.
bool useLinkFrame
Convert sensor ranges to parent link frame?
virtual bool ProcessScan()
Process the scan data and update state.
virtual void OnNewLaserScans()
Update callback.
void Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
Load the plugin.
physics::LinkPtr link
Pointer to parent link.
transport::NodePtr node
Pointer to this node for publishing.
A Ray Sensor Plugin which makes it act as a proximity sensor.
msgs::Header stateMsg
State message.
double sensingRangeMin
Minimum sensing range in meters.
bool objectDetected
Sensor detection state.
std::mutex mutex
Mutex to protect interruptionMsg.
sensors::RaySensorPtr parentSensor
The parent sensor.
std::string Topic(std::string topicName) const
Generate a scoped topic name from a local one.
std::string stateTopic
Topic name for state message.
transport::PublisherPtr stateChangePub
Publisher for the sensor state change.
virtual ~ProximityRayPlugin()
Destructor.
double sensingRangeMax
Maximum sensing range in meters.
transport::PublisherPtr statePub
Publisher for the sensor state.
std::string stateChangeTopic
Topic name for state change message.


osrf_gear
Author(s):
autogenerated on Wed Sep 7 2016 03:48:12