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
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
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
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 }
00422
00423