planning_display.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 #include "planning_display.h"
00031 
00032 #include "rviz/robot/robot.h"
00033 #include "rviz/robot/link_updater.h"
00034 #include "rviz/properties/property.h"
00035 
00036 #include <rviz/visualization_manager.h>
00037 
00038 #include <rviz/properties/property.h>
00039 #include <rviz/properties/string_property.h>
00040 #include <rviz/properties/bool_property.h>
00041 #include <rviz/properties/float_property.h>
00042 #include <rviz/properties/ros_topic_property.h>
00043 
00044 #include <urdf/model.h>
00045 
00046 #include <tf/transform_listener.h>
00047 #include <planning_environment/models/robot_models.h>
00048 #include <planning_models/kinematic_state.h>
00049 #include <OGRE/OgreSceneNode.h>
00050 #include <OGRE/OgreSceneManager.h>
00051 
00052 namespace motion_planning_rviz_plugin
00053 {
00054 
00055 class PlanningLinkUpdater : public rviz::LinkUpdater
00056 {
00057 public:
00058   PlanningLinkUpdater(const planning_models::KinematicState* state)
00059     : kinematic_state_(state)
00060   {}
00061 
00062   virtual bool getLinkTransforms(const std::string& link_name, Ogre::Vector3& visual_position, Ogre::Quaternion& visual_orientation,
00063                                  Ogre::Vector3& collision_position, Ogre::Quaternion& collision_orientation) const
00064   {
00065 
00066     const planning_models::KinematicState::LinkState* link_state = kinematic_state_->getLinkState( link_name );
00067 
00068     if ( !link_state )
00069     {
00070       return false;
00071     }
00072 
00073     tf::Vector3 robot_visual_position = link_state->getGlobalLinkTransform().getOrigin();
00074     tf::Quaternion robot_visual_orientation = link_state->getGlobalLinkTransform().getRotation();
00075     visual_position = Ogre::Vector3( robot_visual_position.getX(), robot_visual_position.getY(), robot_visual_position.getZ() );
00076     visual_orientation = Ogre::Quaternion( robot_visual_orientation.getW(), robot_visual_orientation.getX(), robot_visual_orientation.getY(), robot_visual_orientation.getZ() );
00077 
00078     tf::Vector3 robot_collision_position = link_state->getGlobalLinkTransform().getOrigin();
00079     tf::Quaternion robot_collision_orientation = link_state->getGlobalLinkTransform().getRotation();
00080     collision_position = Ogre::Vector3( robot_collision_position.getX(), robot_collision_position.getY(), robot_collision_position.getZ() );
00081     collision_orientation = Ogre::Quaternion( robot_collision_orientation.getW(), robot_collision_orientation.getX(), robot_collision_orientation.getY(), robot_collision_orientation.getZ() );
00082 
00083     return true;
00084   }
00085 
00086 private:
00087   const planning_models::KinematicState* kinematic_state_;
00088 };
00089 
00090 PlanningDisplay::PlanningDisplay():
00091   Display(), 
00092   env_models_(NULL), 
00093   kinematic_model_(NULL),
00094   new_kinematic_path_(false), 
00095   animating_path_(false), 
00096   state_display_time_(0.05f)
00097 {
00098   visual_enabled_property_ = new rviz::BoolProperty ("Visual Enabled", true, "", this,
00099                                                      SLOT (changedVisualVisible()), this);
00100   
00101   
00102   collision_enabled_property_ = new rviz::BoolProperty ("Collision Enabled", false, "", this,
00103                                                         SLOT (changedCollisionVisible()), this);
00104 
00105   state_display_time_property_ = new rviz::FloatProperty("State Display Time", 0.05f, "", this,
00106                                                          SLOT(changedStateDisplayTime()), this);
00107 
00108   state_display_time_property_->setMin(0.0001);
00109 
00110   loop_display_property_ = new rviz::BoolProperty("Loop Display", false, "", this,
00111                                                   SLOT(changedLoopDisplay), this);
00112   
00113   alpha_property_ = new rviz::FloatProperty ("Alpha", 1.0f, "", this,
00114                                              SLOT(changedAlpha()), this);
00115   
00116   robot_description_property_ = new rviz::StringProperty("Robot Description", "robot_description", "", this,
00117                                                          SLOT(changedRobotDescription()), this);
00118   
00119   topic_property_ = new rviz::RosTopicProperty("Topic", "", ros::message_traits::datatype<arm_navigation_msgs::DisplayTrajectory>(), "", this, 
00120                                                SLOT(changedTopic()), this);
00121 }
00122 
00123 void PlanningDisplay::onInitialize()
00124 {
00125   robot_ = new rviz::Robot(scene_node_, context_, "Planning Robot", this);  
00126 }
00127 
00128 
00129 PlanningDisplay::~PlanningDisplay()
00130 {
00131   unsubscribe();
00132 
00133   delete env_models_;
00134   delete robot_;
00135 }
00136 
00137 void PlanningDisplay::changedRobotDescription()
00138 {
00139   description_param_ = robot_description_property_->getStdString();
00140 
00141   if (isEnabled())
00142     load();
00143 }
00144 
00145 void  PlanningDisplay::changedLoopDisplay()
00146 {
00147   loop_display_ = loop_display_property_->getBool();
00148 }
00149 
00150 void PlanningDisplay::changedAlpha()
00151 {
00152   alpha_ = alpha_property_->getFloat();
00153   robot_->setAlpha(alpha_);
00154 }
00155 
00156 void PlanningDisplay::changedTopic()
00157 {
00158   unsubscribe();
00159   unadvertise();
00160   kinematic_path_topic_ = topic_property_->getStdString();
00161   subscribe();
00162   advertise();
00163 }
00164 
00165 void PlanningDisplay::changedStateDisplayTime()
00166 {
00167   state_display_time_ = state_display_time_property_->getFloat();
00168 }
00169 
00170 void PlanningDisplay::changedVisualVisible()
00171 {
00172   robot_->setVisualVisible(visual_enabled_property_->getBool());
00173 }
00174 
00175 void PlanningDisplay::changedCollisionVisible()
00176 {
00177   robot_->setCollisionVisible(collision_enabled_property_->getBool());
00178 }
00179 
00180 void PlanningDisplay::load()
00181 {
00182   std::string content;
00183   if (!update_nh_.getParam(description_param_, content))
00184   {
00185     std::string loc;
00186     if (update_nh_.searchParam(description_param_, loc))
00187     {
00188       update_nh_.getParam(loc, content);
00189     }
00190   }
00191 
00192   TiXmlDocument doc;
00193   doc.Parse(content.c_str());
00194   if (!doc.RootElement())
00195   {
00196     return;
00197   }
00198 
00199   urdf::Model descr;
00200   descr.initXml(doc.RootElement());
00201   robot_->load( descr);
00202 
00203   delete env_models_;
00204   env_models_ = new planning_environment::RobotModels(description_param_);
00205   kinematic_model_ = env_models_->getKinematicModel();
00206 
00207   planning_models::KinematicState state(kinematic_model_);
00208   state.setKinematicStateToDefault();
00209 
00210   //robot_->update(PlanningLinkUpdater(&state));
00211 }
00212 
00213 void PlanningDisplay::onEnable()
00214 {
00215   subscribe();
00216   advertise();
00217   load();
00218   robot_->setVisible(true);
00219 }
00220 
00221 void PlanningDisplay::onDisable()
00222 {
00223   unsubscribe();
00224   unadvertise();
00225   robot_->setVisible(false);
00226 }
00227 
00228 void PlanningDisplay::subscribe()
00229 {
00230   if (!isEnabled())
00231   {
00232     return;
00233   }
00234 
00235   if (!kinematic_path_topic_.empty())
00236   {
00237     sub_ = update_nh_.subscribe(kinematic_path_topic_, 2, &PlanningDisplay::incomingJointPath, this);
00238   }
00239 
00240 }
00241 
00242 void PlanningDisplay::unsubscribe()
00243 {
00244   sub_.shutdown();
00245 }
00246 
00247 void PlanningDisplay::advertise()
00248 {
00249   if (!isEnabled())
00250   {
00251     return;
00252   }
00253   state_publisher_ = update_nh_.advertise<std_msgs::Bool>(kinematic_path_topic_+std::string("state"), 1);
00254 }
00255 
00256 void PlanningDisplay::unadvertise()
00257 {
00258   state_publisher_.shutdown();
00259 }
00260 
00261 
00262 void PlanningDisplay::update(float wall_dt, float ros_dt)
00263 {
00264   if (!kinematic_model_)
00265     return;
00266 
00267   if (!animating_path_ && !new_kinematic_path_ && loop_display_ && displaying_kinematic_path_message_)
00268   {
00269       new_kinematic_path_ = true;
00270       incoming_kinematic_path_message_ = displaying_kinematic_path_message_;
00271   }
00272   
00273   planning_models::KinematicState state(kinematic_model_);
00274 
00275   if (!animating_path_ && new_kinematic_path_)
00276   {
00277     displaying_kinematic_path_message_ = incoming_kinematic_path_message_;
00278 
00279     animating_path_ = true;
00280     new_kinematic_path_ = false;
00281     current_state_ = -1;
00282     current_state_time_ = state_display_time_ + 1.0f;
00283 
00284     for(unsigned int i = 0; i < displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.joint_names.size(); i++) {
00285       planning_models::KinematicState::JointState* js = state.getJointState(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.joint_names[i]);
00286       if(!js) continue;
00287       if(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.frame_ids[i] != js->getParentFrameId() ||
00288          displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.child_frame_ids[i] != js->getChildFrameId()) {
00289         ROS_WARN_STREAM("Robot state msg has bad multi_dof transform");
00290       } else {
00291         tf::StampedTransform transf;
00292         tf::poseMsgToTF(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.poses[i], transf);
00293         js->setJointStateValues(transf);
00294       }
00295     }
00296 
00297     std::map<std::string, double> joint_state_map;
00298     for (unsigned int i = 0 ; i < displaying_kinematic_path_message_->robot_state.joint_state.name.size(); ++i)
00299     {
00300       joint_state_map[displaying_kinematic_path_message_->robot_state.joint_state.name[i]] = displaying_kinematic_path_message_->robot_state.joint_state.position[i];
00301     }
00302     //overwriting with vals in first value in trajectory
00303     for(unsigned int i = 0; i < displaying_kinematic_path_message_->trajectory.joint_trajectory.joint_names.size(); i++) {
00304       joint_state_map[displaying_kinematic_path_message_->trajectory.joint_trajectory.joint_names[i]] = displaying_kinematic_path_message_->trajectory.joint_trajectory.points[0].positions[i];
00305     }
00306     state.setKinematicState(joint_state_map);
00307     robot_->update(PlanningLinkUpdater(&state));
00308   }
00309 
00310   if (animating_path_)
00311   {
00312 
00313     for(unsigned int i = 0; i < displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.joint_names.size(); i++) {
00314       planning_models::KinematicState::JointState* js = state.getJointState(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.joint_names[i]);
00315       if(!js) continue;
00316       if(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.frame_ids[i] != js->getParentFrameId() ||
00317          displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.child_frame_ids[i] != js->getChildFrameId()) {
00318         ROS_WARN_STREAM("Robot state msg has bad multi_dof transform");
00319       } else {
00320         tf::StampedTransform transf;
00321         tf::poseMsgToTF(displaying_kinematic_path_message_->robot_state.multi_dof_joint_state.poses[i], transf);
00322         js->setJointStateValues(transf);
00323       }
00324     }
00325     std::map<std::string, double> joint_state_map;
00326     for (unsigned int i = 0 ; i < displaying_kinematic_path_message_->robot_state.joint_state.name.size(); ++i)
00327     {
00328       joint_state_map[displaying_kinematic_path_message_->robot_state.joint_state.name[i]] = displaying_kinematic_path_message_->robot_state.joint_state.position[i];
00329     }
00330     if (current_state_time_ > state_display_time_)
00331     {
00332       ++current_state_;
00333 
00334       calculateRobotPosition();
00335 
00336       if ((size_t) current_state_ < displaying_kinematic_path_message_->trajectory.joint_trajectory.points.size())
00337       {
00338         for(unsigned int i = 0; i < displaying_kinematic_path_message_->trajectory.joint_trajectory.joint_names.size(); i++) {
00339           joint_state_map[displaying_kinematic_path_message_->trajectory.joint_trajectory.joint_names[i]] = displaying_kinematic_path_message_->trajectory.joint_trajectory.points[current_state_].positions[i];
00340         }
00341 
00342         state.setKinematicState(joint_state_map);
00343         bool updKstate = false; 
00344         for(unsigned int i = 0; i < displaying_kinematic_path_message_->trajectory.multi_dof_joint_trajectory.joint_names.size(); i++) {
00345             planning_models::KinematicState::JointState* js = state.getJointState(displaying_kinematic_path_message_->trajectory.multi_dof_joint_trajectory.joint_names[i]);
00346             if(!js) continue;
00347             if(displaying_kinematic_path_message_->trajectory.multi_dof_joint_trajectory.frame_ids[i] != js->getParentFrameId() ||
00348                displaying_kinematic_path_message_->trajectory.multi_dof_joint_trajectory.child_frame_ids[i] != js->getChildFrameId()) {
00349                 ROS_WARN_STREAM("Robot state msg has bad multi_dof transform");
00350             } else {
00351                 updKstate = true;       
00352                 tf::StampedTransform transf;
00353                 tf::poseMsgToTF(displaying_kinematic_path_message_->trajectory.multi_dof_joint_trajectory.points[current_state_].poses[i], transf);
00354                 js->setJointStateValues(transf);
00355             }
00356         }
00357         if (updKstate)
00358             state.updateKinematicLinks();
00359         
00360         robot_->update(PlanningLinkUpdater(&state));
00361       }
00362       else
00363       {
00364         animating_path_ = false;
00365         std_msgs::Bool done;
00366         done.data = !animating_path_;        
00367         state_publisher_.publish(done);
00368       }
00369 
00370       current_state_time_ = 0.0f;
00371     }
00372     current_state_time_ += wall_dt;
00373   }
00374 }
00375 
00376 void PlanningDisplay::calculateRobotPosition()
00377 {
00378   if (!displaying_kinematic_path_message_)
00379   {
00380     return;
00381   }
00382 
00383   tf::Stamped<tf::Pose> pose(tf::Transform(tf::Quaternion(0, 0, 0, 1.0), tf::Vector3(0, 0, 0)), displaying_kinematic_path_message_->trajectory.joint_trajectory.header.stamp,
00384                              displaying_kinematic_path_message_->trajectory.joint_trajectory.header.frame_id);
00385 
00386   if (context_->getTFClient()->canTransform(fixed_frame_.toStdString(), displaying_kinematic_path_message_->trajectory.joint_trajectory.header.frame_id, displaying_kinematic_path_message_->trajectory.joint_trajectory.header.stamp))
00387   {
00388     try
00389     {
00390       context_->getTFClient()->transformPose(fixed_frame_.toStdString(), pose, pose);
00391     }
00392     catch (tf::TransformException& e)
00393     {
00394       ROS_ERROR( "Error transforming from frame '%s' to frame '%s'", pose.frame_id_.c_str(), fixed_frame_.toStdString().c_str() );
00395     }
00396   }
00397 
00398   Ogre::Vector3 position(pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z());
00399 
00400   double yaw, pitch, roll;
00401   pose.getBasis().getEulerYPR(yaw, pitch, roll);
00402   Ogre::Matrix3 orientation;
00403   orientation.FromEulerAnglesYXZ(Ogre::Radian(yaw), Ogre::Radian(pitch), Ogre::Radian(roll));
00404 
00405   robot_->setPosition(position);
00406   robot_->setOrientation(orientation);
00407 }
00408 
00409 void PlanningDisplay::incomingJointPath(const arm_navigation_msgs::DisplayTrajectory::ConstPtr& msg)
00410 {
00411   incoming_kinematic_path_message_ = msg;
00412   new_kinematic_path_ = true;
00413 }
00414 
00415 void PlanningDisplay::fixedFrameChanged()
00416 {
00417   calculateRobotPosition();
00418 }
00419 
00420 
00421 } // namespace motion_planning_rviz_plugin
00422 
00423 


motion_planning_rviz_plugin
Author(s): Josh Faust
autogenerated on Mon Dec 2 2013 12:39:30