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
00031
00032
00033
00034
00035
00036
00037 #include "pr2_plugs_actions/move_base_omnidirectional.h"
00038
00039 using namespace ros;
00040 using namespace std;
00041
00042 static const string fixed_frame = "odom_combined";
00043
00044 namespace pr2_plugs_actions{
00045
00046 MoveBaseOmnidirectionalAction::MoveBaseOmnidirectionalAction() :
00047 costmap_ros_("costmap_move_base", tf_),
00048 costmap_model_(costmap_),
00049 action_server_(ros::NodeHandle(),
00050 "move_base_omnidirectional",
00051 boost::bind(&MoveBaseOmnidirectionalAction::execute, this, _1),
00052 true)
00053 {
00054 costmap_ros_.stop();
00055
00056 ros::NodeHandle node_private("~");
00057 node_private.param("k_trans", K_trans, 1.0);
00058 node_private.param("k_rot", K_rot, 1.0);
00059 node_private.param("tolerance_trans", tolerance_trans, 0.02);
00060 node_private.param("tolerance_rot", tolerance_rot, 0.04);
00061
00062 ros::NodeHandle node;
00063 base_pub_ = node.advertise<geometry_msgs::Twist>("base_controller/command", 10);
00064
00065 footprint_ = costmap_ros_.getRobotFootprint();
00066 };
00067
00068
00069
00070 MoveBaseOmnidirectionalAction::~MoveBaseOmnidirectionalAction()
00071 {};
00072
00073
00074
00075 void MoveBaseOmnidirectionalAction::execute(const move_base_msgs::MoveBaseGoalConstPtr& goal)
00076 {
00077 ROS_INFO("MoveBaseOmnidirectionalAction: execute");
00078 costmap_ros_.start();
00079
00080
00081 tf::Stamped<tf::Pose> robot_pose;
00082 costmap_ros_.getRobotPose(robot_pose);
00083 ROS_INFO("MoveBaseOmnidirectionalAction: current robot pose %f %f ==> %f", robot_pose.getOrigin().x(), robot_pose.getOrigin().y(), tf::getYaw(robot_pose.getRotation()));
00084
00085
00086 tf::Stamped<tf::Pose> desired_pose;
00087 tf::poseStampedMsgToTF(goal->target_pose, desired_pose);
00088 if (!tf_.waitForTransform(fixed_frame, desired_pose.frame_id_, desired_pose.stamp_, ros::Duration(2.0))){
00089 ROS_ERROR("MoveBaseOmnidirectionalAction: could not transform from %s to %s", fixed_frame.c_str(), desired_pose.frame_id_.c_str());
00090 action_server_.setAborted();
00091 return;
00092 }
00093 tf_.transformPose(fixed_frame, desired_pose, desired_pose);
00094 ROS_INFO("MoveBaseOmnidirectionalAction: desired robot pose %f %f ==> %f", desired_pose.getOrigin().x(), desired_pose.getOrigin().y(), tf::getYaw(desired_pose.getRotation()));
00095
00096
00097 geometry_msgs::Twist diff = diff2D(desired_pose, robot_pose);
00098 ROS_INFO("MoveBaseOmnidirectionalAction: diff %f %f ==> %f", diff.linear.x, diff.linear.y, diff.angular.z);
00099 ROS_INFO("MoveBaseOmnidirectionalAction: diff limit %f %f ==> %f", diff.linear.x, diff.linear.y, diff.angular.z);
00100 ros::Time goal_reached_time = ros::Time::now();
00101 while (goal_reached_time + ros::Duration(0.5) > ros::Time::now()) {
00102 diff = diff2D(desired_pose, robot_pose);
00103 ROS_DEBUG("Angular error: %f", fabs(diff.angular.z));
00104
00105 if (fabs(diff.linear.x) > tolerance_trans || fabs(diff.linear.y) > tolerance_trans || fabs(diff.angular.z) > tolerance_rot)
00106 goal_reached_time = ros::Time::now();
00107
00108 if (action_server_.isPreemptRequested()){
00109 ROS_WARN("MoveBaseOmnidirectionalAction: Preempted");
00110 lockWheels();
00111 action_server_.setPreempted();
00112 return;
00113 }
00114 base_pub_.publish(limitTwist(diff));
00115 costmap_ros_.getRobotPose(robot_pose);
00116 ros::Duration(0.01).sleep();
00117 }
00118 costmap_ros_.stop();
00119 lockWheels();
00120 action_server_.setSucceeded();
00121 }
00122
00123
00124
00125 void MoveBaseOmnidirectionalAction::lockWheels()
00126 {
00127 ROS_INFO("MoveBaseOmnidirectionalAction: Locking wheels sideways");
00128 geometry_msgs::Twist twist;
00129 twist.linear.y = -0.001;
00130 base_pub_.publish(twist);
00131 ros::Duration(0.5).sleep();
00132 twist.linear.y = 0.0;
00133 base_pub_.publish(twist);
00134 }
00135
00136 geometry_msgs::Twist MoveBaseOmnidirectionalAction::diff2D(const tf::Pose& pose1, const tf::Pose& pose2)
00137 {
00138 geometry_msgs::Twist res;
00139 tf::Pose diff = pose2.inverse() * pose1;
00140 res.linear.x = diff.getOrigin().x();
00141 res.linear.y = diff.getOrigin().y();
00142 res.angular.z = tf::getYaw(diff.getRotation());
00143 return res;
00144 }
00145
00146
00147 geometry_msgs::Twist MoveBaseOmnidirectionalAction::limitTwist(const geometry_msgs::Twist& twist)
00148 {
00149 geometry_msgs::Twist res = twist;
00150 res.linear.x *= K_trans;
00151 res.linear.y *= K_trans;
00152 res.angular.z *= K_rot;
00153
00154 if (fabs(res.linear.x) > 0.1) res.linear.x = 0.1 * res.linear.x / fabs(res.linear.x);
00155 if (fabs(res.linear.y) > 0.1) res.linear.y = 0.1 * res.linear.y / fabs(res.linear.y);
00156 if (fabs(res.angular.z) > 0.2) res.angular.z = 0.2 * res.angular.z / fabs(res.angular.z);
00157
00158 ROS_DEBUG("Angular command %f", res.angular.z);
00159 return res;
00160 }
00161
00162
00163
00164 std::vector<geometry_msgs::Point> MoveBaseOmnidirectionalAction::getOrientedFootprint(const tf::Vector3 pos, double theta_cost)
00165 {
00166 double cos_th = cos(theta_cost);
00167 double sin_th = sin(theta_cost);
00168 std::vector<geometry_msgs::Point> oriented_footprint;
00169 for(unsigned int i = 0; i < footprint_.size(); ++i){
00170 geometry_msgs::Point new_pt;
00171 new_pt.x = pos.x() + (footprint_[i].x * cos_th - footprint_[i].y * sin_th);
00172 new_pt.y = pos.y() + (footprint_[i].x * sin_th + footprint_[i].y * cos_th);
00173 oriented_footprint.push_back(new_pt);
00174 }
00175 return oriented_footprint;
00176 }
00177
00178
00179 }
00180
00181
00182
00183 int main(int argc, char** argv)
00184 {
00185 ros::init(argc, argv, "move_base_omnidirectional");
00186
00187 pr2_plugs_actions::MoveBaseOmnidirectionalAction action_server;
00188
00189 ros::spin();
00190 return 0;
00191 }