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