loopback_controller_manager.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 
00031 #include <math.h>
00032 #include <unistd.h>
00033 #include <set>
00034 
00035 #include <boost/thread.hpp>
00036 
00037 #include "pr2_hardware_interface/hardware_interface.h"
00038 #include "pr2_controller_manager/controller_manager.h"
00039 #include "pr2_mechanism_model/robot.h"
00040 #include "tinyxml.h"
00041 
00042 #include <XmlRpcValue.h>
00043 #include <XmlRpcException.h>
00044 
00045 #include <ros/ros.h>
00046 
00047 #include <urdf/model.h>
00048 
00049 class LoopbackControllerManager
00050 {
00051 public:
00052   LoopbackControllerManager();
00053   virtual ~LoopbackControllerManager();
00054 
00055   // Inherited from gazebo::Controller
00056   void init();
00057   void update();
00058   void fini();
00059 
00060   void run();
00061 private:
00062 
00063   pr2_hardware_interface::HardwareInterface hw_;
00064   pr2_controller_manager::ControllerManager *cm_;
00065 
00066   pr2_mechanism_model::RobotState *state_;
00067 
00068   void readUrdf();
00069 
00070   ros::NodeHandle* rosnode_; 
00071   ros::Subscriber desired_angles_sub_;
00072 
00073   void ControllerManagerROSThread();
00074   void jointCallback(const sensor_msgs::JointState::ConstPtr &joints);
00075   boost::thread* ros_spinner_thread_;
00076   boost::mutex lock;
00077 
00078   double dt_; 
00079   double damping_; 
00080   double mass_; 
00081 
00082   void simulateJoints();
00083 };
00084 
00085 
00086 using namespace std;
00087 using namespace XmlRpc;
00088 
00089 
00090 LoopbackControllerManager::LoopbackControllerManager()
00091   : hw_(), state_(NULL), dt_(0.0)
00092 {
00093 }
00094 
00095 
00096 LoopbackControllerManager::~LoopbackControllerManager()
00097 {
00098   delete cm_; 
00099   delete rosnode_;
00100   delete ros_spinner_thread_;
00101 }
00102 
00103 void LoopbackControllerManager::jointCallback(const sensor_msgs::JointState::ConstPtr &joints)
00104 {
00105   boost::mutex::scoped_lock mutex(lock);
00106 
00107   if(joints->name.size() != joints->position.size())
00108   {
00109     ROS_ERROR("received invalid desired joints.");
00110     return;
00111   }
00112 
00113   for(unsigned int i=0; i < joints->name.size(); ++i)
00114   {
00115     // NOTE: JointState.position_ is declared read-only,
00116     //       but in a simulation this is supposedly safe to be written...
00117     state_->getJointState(joints->name[i])->position_ = joints->position[i];
00118   }
00119 
00120 }
00121 
00122 void LoopbackControllerManager::init()
00123 {
00124   rosnode_ = new ros::NodeHandle("/");
00125   cm_ = new pr2_controller_manager::ControllerManager(&hw_,*rosnode_);
00126   readUrdf();  // read urdf, setup actuators, then setup mechanism control node
00127 
00128   ros::NodeHandle private_node = ros::NodeHandle("~");
00129   private_node.param("dt", dt_, 0.01);
00130   private_node.param("damping", damping_, 0.1);
00131   private_node.param("mass", mass_, 0.1);
00132 
00133   desired_angles_sub_ = private_node.subscribe("desired_joints", 1, &LoopbackControllerManager::jointCallback, this);
00134 
00135   state_ = cm_->state_;
00136 
00137   // set all joints to zero
00138   for(unsigned int i = 0; i < state_->joint_states_.size(); i++)
00139   {
00140     pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00141     s.position_ = 0.0;
00142     s.velocity_ = 0.0;
00143     s.measured_effort_ = 0.0;
00144     s.commanded_effort_ = 0.0;
00145   }
00146 
00147   // set some joints to different starting positions
00148   try
00149   {
00150     XmlRpcValue jointLists, nameList, valueList;
00151     if(private_node.getParam("joints", jointLists))
00152     {
00153       nameList = jointLists["name"];
00154       valueList = jointLists["position"];
00155       for (int index = 0; index < nameList.size(); index++)
00156       {
00157         pr2_mechanism_model::JointState *s =
00158           state_->getJointState((string) nameList[index]);
00159         if(s)
00160           s->position_ = (double) valueList[index];
00161       }
00162     }
00163   }
00164   catch(XmlRpcException e)
00165   {
00166     // syntax error, print the (pretty useless) error message
00167     ROS_WARN("Error parsing initial joint positions: %s", e.getMessage().c_str());
00168   }
00169 
00170 
00171   // adjust joint positions to not violate soft limits
00172   for(unsigned int i = 0; i < state_->joint_states_.size(); i++)
00173   {
00174     pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00175     const boost::shared_ptr<urdf::JointSafety> safety = s.joint_->safety;
00176 
00177     if(safety)
00178     {
00179       double lower = safety->soft_lower_limit;
00180       double upper = safety->soft_upper_limit;
00181       if(lower != 0.0 || upper != 0.0)
00182       {
00183         double margin = (upper - lower) * 0.001;
00184         lower += margin;
00185         upper -= margin;
00186         double pos_old = s.position_;
00187 
00188         s.position_ = (s.position_ < lower) ? lower : s.position_;
00189         s.position_ = (s.position_ > upper) ? upper : s.position_;
00190 
00191         if(s.position_ != pos_old)
00192           ROS_INFO("adjusted joint %s to %f", s.joint_->name.c_str(), s.position_);
00193       }
00194     }
00195   }
00196 
00197   hw_.current_time_ = ros::Time::now();
00198 
00199   // pr2_etherCAT calls ros::spin(), we'll thread out one spinner here to mimic that
00200   ros_spinner_thread_ = new boost::thread( boost::bind( &LoopbackControllerManager::ControllerManagerROSThread,this ) );
00201 
00202 }
00203 
00204 
00205 void LoopbackControllerManager::simulateJoints()
00206 {
00207   // \todo: We should use KDL to do correct dynamics
00208 
00209   for (unsigned int i = 0; i < state_->joint_states_.size(); ++i)
00210   {
00211     pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00212     const boost::shared_ptr<urdf::JointDynamics> dynamics = state_->joint_states_[i].joint_->dynamics;
00213 
00214     // use damping from urdf (if specified)
00215     double damp = (dynamics) ? dynamics->damping : damping_;
00216     double effort = s.commanded_effort_ - damp*s.velocity_;
00217 
00218     double dv = effort/mass_*dt_;
00219     s.velocity_ += dv;
00220 
00221     double dx = s.velocity_*dt_;
00222     s.position_ += dx;
00223   }
00224 }
00225 
00226 
00227 void LoopbackControllerManager::update()
00228 {
00229   boost::mutex::scoped_lock mutex(lock);
00230 
00231   // Copies the state from the gazebo joints into the mechanism joints.
00232   for (unsigned int i = 0; i < state_->joint_states_.size(); ++i)
00233   {
00234     state_->joint_states_[i].measured_effort_ = state_->joint_states_[i].commanded_effort_;
00235   }
00236 
00237   // Reverses the transmissions to propagate the joint position into the actuators.
00238   state_->propagateJointPositionToActuatorPosition();
00239 
00240   //--------------------------------------------------
00241   //  Runs Mechanism Control
00242   //--------------------------------------------------
00243 
00244   // \todo: necessary?
00245   hw_.current_time_ = ros::Time::now();
00246 
00247   try
00248   {
00249     cm_->update();
00250   }
00251   catch (const char* c)
00252   {
00253     if (strcmp(c,"dividebyzero")==0)
00254       ROS_WARN("pid controller reports divide by zero error");
00255     else
00256       ROS_WARN("unknown const char* exception: %s", c);
00257   }
00258 
00259   //--------------------------------------------------
00260   //  Simulate the effort commands
00261   //--------------------------------------------------
00262 
00263   // Reverses the transmissions to propagate the actuator commands into the joints.
00264   state_->propagateActuatorEffortToJointEffort();
00265 
00266   simulateJoints();
00267 }
00268 
00269 void LoopbackControllerManager::fini()
00270 {
00271   ROS_DEBUG("calling LoopbackControllerManager::fini");
00272 
00273   //pr2_hardware_interface::ActuatorMap::const_iterator it;
00274   //for (it = hw_.actuators_.begin(); it != hw_.actuators_.end(); ++it)
00275   //  delete it->second; // why is this causing double free corrpution?
00276   cm_->~ControllerManager();
00277   rosnode_->shutdown();
00278 
00279   ros_spinner_thread_->join();
00280 }
00281 
00282 void LoopbackControllerManager::readUrdf()
00283 {
00284   std::string urdf_string;
00285   rosnode_->getParam("/robot_description", urdf_string);
00286 
00287   // initialize TiXmlDocument doc with a string
00288   TiXmlDocument doc;
00289   if (!doc.Parse(urdf_string.c_str()))
00290   {
00291     ROS_ERROR("Failed to load robot description");
00292     abort();
00293   }
00294 
00295   struct GetActuators : public TiXmlVisitor
00296   {
00297     std::set<std::string> actuators;
00298     virtual bool VisitEnter(const TiXmlElement &elt, const TiXmlAttribute *)
00299     {
00300       if (elt.Attribute("name") &&
00301             ( elt.ValueStr() == std::string("actuator")
00302            || elt.ValueStr() == std::string("rightActuator")
00303            || elt.ValueStr() == std::string("leftActuator") )) 
00304         actuators.insert(elt.Attribute("name"));
00305       return true;
00306     }
00307   } get_actuators;
00308   doc.RootElement()->Accept(&get_actuators);
00309 
00310   // Places the found actuators into the hardware interface.
00311   std::set<std::string>::iterator it;
00312   for (it = get_actuators.actuators.begin(); it != get_actuators.actuators.end(); ++it)
00313   {
00314     // ROS_INFO_STREAM("adding actuator " << *it);
00315     pr2_hardware_interface::Actuator* pr2_actuator = new pr2_hardware_interface::Actuator(*it);
00316     pr2_actuator->state_.is_enabled_ = true;
00317     hw_.addActuator(pr2_actuator);
00318   }
00319 
00320   // Setup mechanism control node
00321   cm_->initXml(doc.RootElement());
00322 
00323   for (unsigned int i = 0; i < cm_->state_->joint_states_.size(); ++i)
00324     cm_->state_->joint_states_[i].calibrated_ = true;
00325 }
00326 
00327 
00328 void LoopbackControllerManager::ControllerManagerROSThread()
00329 {
00330   ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
00331 
00332   ros::Rate rate(0.2/dt_);
00333 
00334   while (rosnode_->ok())
00335   {
00336     rate.sleep();
00337     ros::spinOnce();
00338   }
00339 }
00340 
00341 
00342 void LoopbackControllerManager::run()
00343 {
00344 
00345   ros::Rate rate(1.0/dt_);
00346   while(rosnode_->ok())
00347   {
00348     update();
00349     rate.sleep();
00350   }
00351 }
00352 
00353 
00354 int main(int argc, char *argv[])
00355 {
00356   ros::init(argc,argv,"loopback_controllers");
00357 
00358   // bring up mechanism controllers
00359   LoopbackControllerManager m;
00360 
00361   m.init();
00362   m.run();
00363   m.fini();
00364 }


loopback_controller_manager
Author(s): Ingo Kresse
autogenerated on Mon Oct 6 2014 09:15:40