mpc_node.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <tf/tf.h>
00003 #include <tf/transform_listener.h>
00004 #include <tf/tfMessage.h>
00005 #include <tf/transform_broadcaster.h>
00006 
00007 #include <geometry_msgs/PoseStamped.h>
00008 #include <geometry_msgs/QuaternionStamped.h>
00009 #include <visualization_msgs/Marker.h>
00010 #include <visualization_msgs/MarkerArray.h>
00011 
00012 #include <pr2_controllers_msgs/Pr2GripperCommandAction.h>
00013 #include <actionlib/client/simple_action_client.h>
00014 
00015 #include <motld/TrackedObjects.h>
00016 
00017 #include <mpc/types.h>
00018 #include <mpc/mpc.h>
00019 #include <mpc/finite_differences.h>
00020 #include <reactive_grasping_pr2/pr2_arm_ik.h>
00021 
00022 #ifndef SQR
00023 #define SQR(X) ((X)*(X))
00024 #endif
00025 
00026 using namespace MPC;
00027 
00028 typedef actionlib::SimpleActionClient<pr2_controllers_msgs::Pr2GripperCommandAction> GripperClient;
00029 
00030 class ArmMPC {
00031 
00032 private:
00033         bool initialized_;
00034         VectorT center_;
00035         tf::TransformBroadcaster *tf_broadcaster_;
00036         tf::TransformListener  *tf_transformer_;
00037 
00038         ros::Subscriber obj_sub_;
00039         
00040         ros::Publisher gripper_pose_pub_;
00041         ros::Publisher marker_pub_;
00042         int curr_t_;
00043 
00044         float eps_;
00045         float max_mov_dist_;
00046 
00047         bool on_way_to_goal_;
00048         bool last_goal_set_;
00049         bool last_pos_set_;
00050         VectorT last_goal_;
00051         VectorT last_pos_;
00052         pr2_arm_ik::Obstacles *obs_;
00053 
00054         int n, m, N;
00055         bool restart_ddp_;
00056         DDPParams params;
00057         Trajectory curr_traj_;
00058         MatrixT u0_;
00059         geometry_msgs::PoseStamped gripper_pose_;
00060         GripperClient *close_gripper_;
00061 
00062         ros::NodeHandle nh_;
00063         ros::NodeHandle private_nh_;
00064 
00065         // names of parameters to read
00066         std::string root_frame_;
00067         std::string gripper_frame_;
00068         std::string object_topic_;
00069         std::string gripper_action_topic_;
00070         std::string gripper_close_topic_;
00071         std::string marker_topic_;
00072 
00073 public:
00074         ArmMPC(ros::NodeHandle &nh) : nh_(nh), private_nh_(ros::NodeHandle("~")), initialized_(false) {
00075                 // read parameters
00076                 private_nh_.param("root_frame", root_frame_, std::string("/torso_lift_link"));
00077                 private_nh_.param("gripper_frame", gripper_frame_, std::string("/r_gripper_tool_frame"));
00078                 private_nh_.param("object_topic", object_topic_, std::string("/objects"));
00079                 private_nh_.param("gripper_action_topic", gripper_action_topic_, std::string("/r_cart/command_pose"));
00080                 private_nh_.param("gripper_close_topic", gripper_close_topic_, std::string("/r_gripper_controller/gripper_action"));
00081                 private_nh_.param("marker_topic", marker_topic_, std::string("MPC_markers"));
00082                      
00083                 // setup tf transformer and broadcaster
00084                 tf_broadcaster_ = new tf::TransformBroadcaster();
00085                 tf_transformer_ = new tf::TransformListener();
00086 
00087                 // setup mpc callback
00088                 obj_sub_ = nh_.subscribe(object_topic_, 1, &ArmMPC::mpc_callback, this);
00089 
00090                 // setup pose client
00091                 gripper_pose_pub_ = nh_.advertise<geometry_msgs::PoseStamped>(gripper_action_topic_, 1);
00092                 // setup gripper client
00093                 close_gripper_ = new GripperClient(gripper_close_topic_, true);
00094                 while(!close_gripper_->waitForServer(ros::Duration(5.0))){
00095                         ROS_INFO("Waiting for the gripper action server to come up");
00096                 }                     
00097 
00098                 // setup visualization
00099                 marker_pub_ = private_nh_.advertise<visualization_msgs::MarkerArray>(marker_topic_, 1); 
00100 
00101                 // setup DDP and dynamics
00102                 n = 3;
00103                 m = 3;
00104                 N = 20;
00105                 u0_.setZero(m, N);
00106                 VectorT internal_goal(VectorT::Zero(n));
00107                 // setup some constants
00108                 eps_ = 0.02;
00109                 max_mov_dist_ = 0.05;
00110                 // plan full number of steps in the first callback
00111                 restart_ddp_ = true;
00112 
00113 
00114                 // use finite differences
00115                 /*
00116                   euclidean::setGoal(internal_goal);
00117                   finite_differences::setBaseFunctions(&euclidean::dynamics, &euclidean::cost);
00118                   bool init_success = DDP_init(&finite_differences::dynamics, &finite_differences::dynamicsD, &finite_differences::cost, &finite_differences::costD);
00119                 */
00120 
00121                 // real euclidean robot dynamics
00123                 pr2_arm_ik::setGoal(internal_goal);
00124                 bool init_success = DDP_init(&pr2_arm_ik::dynamics, &pr2_arm_ik::dynamicsD, &pr2_arm_ik::cost, &pr2_arm_ik::costD);
00125                 //*/
00126                 // clear obstacles
00127                 obs_ = &pr2_arm_ik::getObstacles();
00128                 obs_->clear();
00129 
00130                 // init temporaries
00131                 center_.resize(3);
00132                 last_goal_.resize(n);
00133                 last_pos_.resize(3);
00134                 on_way_to_goal_ = false;
00135                 last_goal_set_ = false;
00136                 last_pos_set_ = false;
00137                 curr_t_ = 1;
00138                 
00139                 // mark as initialized
00140                 initialized_ = init_success;
00141                 ROS_INFO("Done initializing");
00142         }
00143 
00144         ~ArmMPC() {
00145                 delete obj_sub_;
00146                 delete close_gripper_;
00147         }
00148 
00149         void open_gripper(bool wait=false) {
00150                 pr2_controllers_msgs::Pr2GripperCommandGoal open;
00151                 open.command.position = 0.08;
00152                 open.command.max_effort = -1.0;
00153     
00154                 close_gripper_->sendGoal(open);
00155                 if (wait) {
00156                         close_gripper_->waitForResult();
00157                         if(close_gripper_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
00158                                 ROS_INFO("The gripper opened!");
00159                         else
00160                                 ROS_INFO("The gripper failed to open.");
00161                 }
00162         } 
00163         
00164         void close_gripper(bool wait=false) {
00165                 pr2_controllers_msgs::Pr2GripperCommandGoal close;
00166                 close.command.position = 0.0;
00167                 close.command.max_effort = 20.0;
00168     
00169                 close_gripper_->sendGoal(close);
00170                 if (wait) {
00171                         close_gripper_->waitForResult();
00172                         if(close_gripper_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
00173                                 ROS_INFO("The gripper closed!");
00174                         else
00175                                 ROS_INFO("The gripper failed to close.");
00176                 }
00177         } 
00178 
00179         void mpc_callback(const motld::TrackedObjectsConstPtr &objects) {
00180                 ROS_INFO("mpc_callback called!");
00181                 if (not initialized_) {
00182                         ROS_WARN("mpc not initialized");
00183                         return;
00184                 }
00185                 if (objects->name.size() < 1) {
00186                         ROS_WARN("no object poses received");
00187                         return;
00188                 }
00189                 if (objects->name.size() != objects->pose.poses.size()) {
00190                         ROS_WARN("object poses and object names array sizes do not match");
00191                         return;
00192                 }
00193                 
00194                 if (on_way_to_goal_ && curr_t_ +1 >= curr_traj_.x.cols()) {
00195                         // TODO: there was a sleep here in the python implementation to prevent weird near goal behaviour 
00196                         // when the last action has not been completely executed
00197                 }
00198 
00199                 ros::Time goal_stamp = objects->pose.header.stamp;
00200                 ros::Time time_stamp_now = ros::Time::now();
00201                 // we always assume that the first object is the goal
00202                 VectorT goal(3);
00203                 goal(0) = objects->pose.poses[0].position.x;
00204                 goal(1) = objects->pose.poses[0].position.y;
00205                 goal(2) = objects->pose.poses[0].position.z;
00206 
00207                 if (tf_transformer_->waitForTransform(objects->pose.header.frame_id, gripper_frame_, goal_stamp, ros::Duration(1.)) == false) {
00208                         ROS_ERROR("Did not find transform between %s and %s", objects->pose.header.frame_id.c_str(), gripper_frame_.c_str());
00209                         return;
00210                 }
00211                 ROS_INFO("Got transform!");
00212 
00213                 tf::StampedTransform trans;
00214                 tf_transformer_->lookupTransform(objects->pose.header.frame_id, gripper_frame_, goal_stamp, trans);
00215 
00216                 // set new center
00217                 center_(0) = trans.getOrigin().x();
00218                 center_(1) = trans.getOrigin().y();
00219                 center_(2) = trans.getOrigin().z();
00220 
00221                 // internal coordinates
00222                 VectorT x0(15);
00223                 x0(0) = center_(0) - goal(0);
00224                 x0(1) = center_(1) - goal(1);
00225                 x0(2) = center_(2) - goal(2);
00226 
00227                 // update parts
00228                 tf::Vector3 tmp_vec = btVector3(-0.08, -0.1, 0.);
00229 
00230                 tmp_vec = trans(tmp_vec);
00231                 x0(3) = tmp_vec.getX() - goal(0);
00232                 x0(4) = tmp_vec.getY() - goal(1);
00233                 x0(5) = tmp_vec.getZ() - goal(2);
00234 
00235                 tmp_vec.setX(-0.08);
00236                 tmp_vec.setY(0.1);
00237                 tmp_vec.setZ(0.);
00238                 tmp_vec = trans(tmp_vec);
00239                 x0(6) = tmp_vec.getX() - goal(0);
00240                 x0(7) = tmp_vec.getY() - goal(1);
00241                 x0(8) = tmp_vec.getZ() - goal(2);
00242 
00243                 tmp_vec.setX(-0.1);
00244                 tmp_vec.setY(0.);
00245                 tmp_vec.setZ(0.);
00246                 tmp_vec = trans(tmp_vec);
00247                 x0(9) = tmp_vec.getX() - goal(0);
00248                 x0(10) = tmp_vec.getY() - goal(1);
00249                 x0(11) = tmp_vec.getZ() - goal(2);
00250 
00251                 tmp_vec.setX(-0.2);
00252                 tmp_vec.setY(0.);
00253                 tmp_vec.setZ(0.);
00254                 tmp_vec = trans(tmp_vec);
00255                 x0(12) = tmp_vec.getX() - goal(0);
00256                 x0(13) = tmp_vec.getY() - goal(1);
00257                 x0(14) = tmp_vec.getZ() - goal(2);
00258 
00259                 if (objects->name.size() > 1) {
00260                         // assume all other objects are obstacles
00261                         obs_->resize(objects->name.size() - 1);
00262                         (*obs_)[0].resize(3);
00263                         (*obs_)[0](0) = objects->pose.poses[1].position.x - goal(0);
00264                         (*obs_)[0](1) = objects->pose.poses[1].position.y - goal(1);
00265                         (*obs_)[0](2) = objects->pose.poses[1].position.z - goal(2);
00266                 }
00267 
00268                 float goal_diff = x0.head(3).norm();
00269 
00270                 if (goal_diff < eps_ + 0.01) {
00271                         ROS_INFO("already at goal / goal reached");
00272                         close_gripper();
00273                         return;
00274                 }
00275                 // TODO: insert obstacles
00276                 float goal_change = 100.;
00277                 float pos_change = 100.;
00278                 if (last_goal_set_) {
00279                         goal_change = (last_goal_ - goal).norm();
00280                 }
00281                 if (last_pos_set_) {
00282                         pos_change = (center_ - last_pos_).norm();
00283                 }
00284                 ROS_INFO("pchange: %f gchange: %f max_dist: %f", pos_change, goal_change, max_mov_dist_);
00285                 if (pos_change > max_mov_dist_ || goal_change > max_mov_dist_) {
00286                         // reset policy, since we are too far from our last computed one
00287                         //actions_.setZero(actions_.rows(), actions_.cols());
00288                         on_way_to_goal_ = false;
00289                         restart_ddp_ = true;
00290                 }
00291 
00292                 /* check if we have a policy that gets us to the goal
00293                    if so and the goal did not change significantly execute it */
00294                 int x_len = curr_traj_.x.cols();
00295                 // TODO: check if we want to enable the on_way_to_goal_ behavior or not!
00296                 if (false && on_way_to_goal_ && goal_change < eps_ && curr_t_ < x_len - 1) {
00297                         curr_t_++;
00298                 } else {
00299                         // run ddp
00300                         if (restart_ddp_) {
00301                                 ROS_INFO("restarting ddp");
00302                                 u0_.setZero();
00303                                 DDP(x0, u0_, params, 100, curr_traj_);
00304                                 restart_ddp_ = false;
00305                         } else {
00306                                 u0_ = curr_traj_.u;
00307                                 DDP(x0, u0_, params, 10, curr_traj_);
00308                         }
00309                         curr_t_ = 1;
00310                 }
00311                 
00312                 // fill gripper message
00313                 // skip too small position changes (smaller than controller sensitivity)
00314                 double dist = (curr_traj_.x.col(curr_t_).head(3) - x0.head(3)).norm();
00315                 while (curr_t_ + 1 < curr_traj_.x.cols() && dist < 0.01) {
00316                     ++curr_t_;
00317                     dist = (curr_traj_.x.col(curr_t_).head(3) - x0.head(3)).norm();
00318                 }
00319                 ROS_INFO_STREAM("chosen dist = " << dist);
00320                 const VectorT &next = curr_traj_.x.col(curr_t_);
00321 
00322                 gripper_pose_.header.frame_id = objects->pose.header.frame_id;
00323                 gripper_pose_.header.stamp = time_stamp_now;
00324                 gripper_pose_.pose.position.x = next(0) + goal(0);
00325                 gripper_pose_.pose.position.y = next(1) + goal(1);
00326                 gripper_pose_.pose.position.z = next(2) + goal(2);
00327 
00328                 // for now assume that we want to come in with a fixed
00329                 // rotation on the z axis
00330                 geometry_msgs::QuaternionStamped quat;
00331                 quat.header.frame_id = root_frame_;
00332                 quat.header.stamp = goal_stamp;
00333                 // create fixed quaternion
00334                 quat.quaternion = tf::createQuaternionMsgFromRollPitchYaw(0., 0., M_PI/2.);
00335                 // transform into goal frame
00336                 // TODO: make sure transformation is present
00337                 tf_transformer_->transformQuaternion(objects->pose.header.frame_id, quat, quat);
00338                 gripper_pose_.pose.orientation = quat.quaternion;
00339                 
00340                 // remember last goal
00341                 last_goal_ = goal;
00342                 last_goal_set_ = true;
00343 
00344                 // remember last pos
00345                 last_pos_ = center_;
00346                 last_pos_set_ = true;
00347 
00348                 // check if we found a goal fulfilling trajectory
00349                 if (curr_traj_.x.col(curr_traj_.x.cols()-1).norm() < eps_) {
00350                         on_way_to_goal_ = true;
00351                 } else {
00352                         on_way_to_goal_ = false;
00353                 }
00354                 
00355                 // send action
00356                 gripper_pose_pub_.publish(gripper_pose_);
00357                 open_gripper();
00358 
00359                 // TODO: send out marker array
00360                 if (marker_pub_.getNumSubscribers() > 0) {
00361                         ROS_INFO("mpc sending markers");
00362                         visualization_msgs::MarkerArray markers;
00363                         int id = 0;
00364                         for (int p = 0; p < curr_traj_.x.cols(); ++p) {
00365                                 visualization_msgs::Marker marker;
00366                                 marker.header.frame_id = objects->pose.header.frame_id;
00367                                 marker.header.stamp = time_stamp_now;
00368                                 marker.type = marker.SPHERE;
00369                                 marker.action = marker.ADD;
00370                                 marker.id = id;
00371                                 marker.scale.x = 0.02;
00372                                 marker.scale.y = 0.02;
00373                                 marker.scale.z = 0.02;
00374                                 marker.color.a = 1.0;
00375                                 marker.color.r = 1.0;
00376                                 marker.color.g = 1.0;
00377                                 marker.color.b = 0.0;
00378                                 marker.pose.orientation.w = 1.0;
00379                                 marker.pose.position.x = curr_traj_.x(0, p) + goal(0);
00380                                 marker.pose.position.y = curr_traj_.x(1, p) + goal(1);
00381                                 marker.pose.position.z = curr_traj_.x(2, p) + goal(2);
00382                                 markers.markers.push_back(marker);
00383                                 ++id;
00384                                 // add parts
00385                                 marker.color.g = 0.0;
00386                                 for (int i = 3; i + 3 <= curr_traj_.x.rows(); i+=3) {
00387                                         marker.id = id;
00388                                         marker.pose.position.x = curr_traj_.x(i, p) + goal(0);
00389                                         marker.pose.position.y = curr_traj_.x(i+1, p) + goal(1);
00390                                         marker.pose.position.z = curr_traj_.x(i+2, p) + goal(2);
00391                                         markers.markers.push_back(marker);
00392                                         ++id;
00393                                 }
00394                         }
00395                         marker_pub_.publish(markers);
00396                 }
00397         }
00398 };
00399 
00400 int main(int argc, char *argv[]) {
00401         ros::init(argc, argv, "mpc_node");
00402         ros::NodeHandle n;
00403         ArmMPC mpc_client(n);
00404         while (ros::ok()) {
00405                 ros::spinOnce();
00406         }
00407 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


reactive_grasping_pr2
Author(s): Jost Tobias Springenberg, Jan Wuelfing
autogenerated on Wed Dec 26 2012 16:26:42