00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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 motion_planning_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(motion_planning_msgs::DisplayTrajectory::__s_getDataType());
00464
00465 robot_->setPropertyManager(property_manager_, parent_category_);
00466 }
00467
00468 }
00469
00470