PopulationPlugin.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 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 <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   // Read the SDF parameters
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     // Parse the time.
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     // Parse the object type.
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     // Parse the object pose (optional).
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     // Add the object to the collection.
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   // Listen on the activation topic, if present. This topic is used for
00218   // manual activation.
00219   if (_sdf->HasElement("activation_topic"))
00220   {
00221     // Create and initialize the node.
00222     this->dataPtr->node = transport::NodePtr(new transport::Node());
00223     this->dataPtr->node->Init();
00224 
00225     // Subscribe to the activation topic.
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   // Check whether spawn a new object from the list.
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 }


osrf_gear
Author(s):
autogenerated on Mon Sep 5 2016 03:41:33