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 #include <algorithm>
00019 #include <mutex>
00020 #include <ostream>
00021 #include <string>
00022 #include <vector>
00023 #include <gazebo/common/Assert.hh>
00024 #include <gazebo/common/Console.hh>
00025 #include <gazebo/common/Events.hh>
00026 #include <gazebo/math/Pose.hh>
00027 #include <gazebo/msgs/gz_string.pb.h>
00028 #include <gazebo/physics/Link.hh>
00029 #include <gazebo/physics/PhysicsTypes.hh>
00030 #include <gazebo/physics/World.hh>
00031 #include <gazebo/transport/transport.hh>
00032 #include <ignition/math/Matrix4.hh>
00033 #include <sdf/sdf.hh>
00034
00035 #include "osrf_gear/PopulationPlugin.hh"
00036
00037 namespace gazebo
00038 {
00041 struct PopulationPluginPrivate
00042 {
00044 public: physics::WorldPtr world;
00045
00047 public: sdf::ElementPtr sdf;
00048
00050 public: class Object
00051 {
00055 public: bool operator<(const Object &_obj) const
00056 {
00057 return this->time < _obj.time;
00058 }
00059
00064 public: friend std::ostream &operator<<(std::ostream &_out,
00065 const Object &_obj)
00066 {
00067 _out << _obj.type << std::endl;
00068 _out << " Time: [" << _obj.time << "]" << std::endl;
00069 _out << " Pose: [" << _obj.pose << "]" << std::endl;
00070 return _out;
00071 }
00072
00074 public: double time;
00075
00077 public: std::string type;
00078
00080 public: math::Pose pose;
00081 };
00082
00084 public: std::vector<Object> objects;
00085
00088 public: std::vector<Object> initialObjects;
00089
00091 public: event::ConnectionPtr connection;
00092
00094 public: common::Time startTime;
00095
00098 public: bool loopForever = false;
00099
00101 public: physics::EntityPtr frame;
00102
00104 public: transport::NodePtr node;
00105
00107 public: transport::SubscriberPtr activationSub;
00108
00110 public: bool enabled = false;
00111
00113 public: std::mutex mutex;
00114
00116 public: common::Time elapsedWhenPaused;
00117 };
00118 }
00119
00120 using namespace gazebo;
00121
00122 GZ_REGISTER_WORLD_PLUGIN(PopulationPlugin)
00123
00124
00125 PopulationPlugin::PopulationPlugin()
00126 : dataPtr(new PopulationPluginPrivate)
00127 {
00128 }
00129
00131 PopulationPlugin::~PopulationPlugin()
00132 {
00133 }
00134
00136 void PopulationPlugin::Load(physics::WorldPtr _world, sdf::ElementPtr _sdf)
00137 {
00138 GZ_ASSERT(_world, "PopulationPlugin world pointer is NULL");
00139 GZ_ASSERT(_sdf, "PopulationPlugin sdf pointer is NULL");
00140 this->dataPtr->world = _world;
00141 this->dataPtr->sdf = _sdf;
00142
00143
00144 if (_sdf->HasElement("loop_forever"))
00145 {
00146 sdf::ElementPtr loopElem = _sdf->GetElement("loop_forever");
00147 this->dataPtr->loopForever = loopElem->Get<bool>();
00148 }
00149
00150 if (_sdf->HasElement("frame"))
00151 {
00152 std::string frameName = _sdf->Get<std::string>("frame");
00153 this->dataPtr->frame = this->dataPtr->world->GetEntity(frameName);
00154 if (!this->dataPtr->frame) {
00155 gzthrow(std::string("The frame '") + frameName + "' does not exist");
00156 }
00157 if (!this->dataPtr->frame->HasType(physics::Base::LINK) &&
00158 !this->dataPtr->frame->HasType(physics::Base::MODEL))
00159 {
00160 gzthrow("'frame' tag must list the name of a link or model");
00161 }
00162 }
00163
00164 if (!_sdf->HasElement("object_sequence"))
00165 {
00166 gzerr << "PopulationPlugin: Unable to find <object_sequence> element\n";
00167 return;
00168 }
00169
00170 sdf::ElementPtr sequence = _sdf->GetElement("object_sequence");
00171
00172 sdf::ElementPtr objectElem = NULL;
00173 if (sequence->HasElement("object"))
00174 {
00175 objectElem = sequence->GetElement("object");
00176 }
00177
00178 while (objectElem)
00179 {
00180
00181 if (!objectElem->HasElement("time"))
00182 {
00183 gzerr << "PopulationPlugin: Unable to find <time> in object\n";
00184 objectElem = objectElem->GetNextElement("object");
00185 continue;
00186 }
00187 sdf::ElementPtr timeElement = objectElem->GetElement("time");
00188 double time = timeElement->Get<double>();
00189
00190
00191 if (!objectElem->HasElement("type"))
00192 {
00193 gzerr << "PopulationPlugin: Unable to find <type> in object.\n";
00194 objectElem = objectElem->GetNextElement("object");
00195 continue;
00196 }
00197 sdf::ElementPtr typeElement = objectElem->GetElement("type");
00198 std::string type = typeElement->Get<std::string>();
00199
00200
00201 math::Pose pose;
00202 if (objectElem->HasElement("pose"))
00203 {
00204 sdf::ElementPtr poseElement = objectElem->GetElement("pose");
00205 pose = poseElement->Get<math::Pose>();
00206 }
00207
00208
00209 PopulationPluginPrivate::Object obj = {time, type, pose};
00210 this->dataPtr->initialObjects.push_back(obj);
00211
00212 objectElem = objectElem->GetNextElement("object");
00213 }
00214 std::sort(this->dataPtr->initialObjects.begin(),
00215 this->dataPtr->initialObjects.end());
00216
00217
00218
00219 if (_sdf->HasElement("activation_topic"))
00220 {
00221
00222 this->dataPtr->node = transport::NodePtr(new transport::Node());
00223 this->dataPtr->node->Init();
00224
00225
00226 this->dataPtr->activationSub = this->dataPtr->node->Subscribe(
00227 _sdf->Get<std::string>("activation_topic"),
00228 &PopulationPlugin::OnActivation, this);
00229 }
00230 else
00231 this->Restart();
00232
00233 this->dataPtr->connection = event::Events::ConnectWorldUpdateEnd(
00234 boost::bind(&PopulationPlugin::OnUpdate, this));
00235 }
00236
00238 void PopulationPlugin::Pause()
00239 {
00240 if (!this->dataPtr->enabled)
00241 return;
00242
00243 this->dataPtr->enabled = false;
00244 this->dataPtr->elapsedWhenPaused =
00245 this->dataPtr->world->GetSimTime() - this->dataPtr->startTime;
00246
00247 gzmsg << "Object population paused" << std::endl;
00248 }
00249
00251 void PopulationPlugin::Resume()
00252 {
00253 if (this->dataPtr->enabled)
00254 return;
00255
00256 this->dataPtr->enabled = true;
00257 this->dataPtr->startTime = this->dataPtr->world->GetSimTime() -
00258 this->dataPtr->elapsedWhenPaused;
00259
00260 gzmsg << "Object population resumed" << std::endl;
00261 }
00262
00264 void PopulationPlugin::Restart()
00265 {
00266 this->dataPtr->enabled = true;
00267 this->dataPtr->startTime = this->dataPtr->world->GetSimTime();
00268 this->dataPtr->objects = this->dataPtr->initialObjects;
00269
00270 gzmsg << "Object population restarted" << std::endl;
00271 }
00272
00274 void PopulationPlugin::OnUpdate()
00275 {
00276 std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00277
00278 this->Publish();
00279
00280 if (!this->dataPtr->enabled)
00281 return;
00282
00283 if (this->dataPtr->objects.empty())
00284 {
00285 if (this->dataPtr->loopForever)
00286 this->Restart();
00287 else
00288 return;
00289 }
00290
00291
00292 auto elapsed = this->dataPtr->world->GetSimTime() - this->dataPtr->startTime;
00293 if (elapsed.Double() >= this->dataPtr->objects.front().time)
00294 {
00295 auto obj = this->dataPtr->objects.front();
00296 if (this->dataPtr->frame)
00297 {
00298 auto framePose = this->dataPtr->frame->GetWorldPose().Ign();
00299 ignition::math::Matrix4d transMat(framePose);
00300 ignition::math::Matrix4d pose_local(obj.pose.Ign());
00301 obj.pose = (transMat * pose_local).Pose();
00302 }
00303 std::string modelName = this->GetHandle() + "|" + obj.type;
00304
00305 std::ostringstream newModelStr;
00306 newModelStr <<
00307 "<sdf version='" << SDF_VERSION << "'>\n"
00308 " <include>\n"
00309 " <pose>" << obj.pose << "</pose>\n"
00310 " <name>" << modelName << "</name>\n"
00311 " <uri>model://" << obj.type << "</uri>\n"
00312 " </include>\n"
00313 "</sdf>\n";
00314
00315 gzdbg << "Object spawned: " << modelName << std::endl;
00316 this->dataPtr->world->InsertModelString(newModelStr.str());
00317 this->dataPtr->objects.erase(this->dataPtr->objects.begin());
00318 }
00319 }
00320
00322 void PopulationPlugin::OnActivation(ConstGzStringPtr &_msg)
00323 {
00324 std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00325
00326 if (_msg->data() == "restart")
00327 this->Restart();
00328 else if (_msg->data() == "pause")
00329 this->Pause();
00330 else if (_msg->data() == "resume")
00331 this->Resume();
00332 else
00333 gzerr << "Unknown activation command [" << _msg->data() << "]" << std::endl;
00334 }
00335
00337 bool PopulationPlugin::Enabled() const
00338 {
00339 return this->dataPtr->enabled;
00340 }
00341
00343 void PopulationPlugin::Publish() const
00344 {
00345 }