Go to the documentation of this file.00001
00009
00010
00011
00012
00013 #include "kobuki_auto_docking/auto_docking_ros.hpp"
00014
00015 namespace kobuki
00016 {
00017
00018
00019 AutoDockingROS::AutoDockingROS(std::string name)
00020
00021
00022 : name_(name)
00023 , shutdown_requested_(false)
00024 , as_(nh_, name_+"_action", false)
00025 {
00026 self = this;
00027
00028 as_.registerGoalCallback(boost::bind(&AutoDockingROS::goalCb, this));
00029 as_.registerPreemptCallback(boost::bind(&AutoDockingROS::preemptCb, this));
00030 as_.start();
00031 }
00032
00033 AutoDockingROS::~AutoDockingROS()
00034 {
00035 shutdown_requested_ = true;
00036 if (as_.isActive()) {
00037 result_.text = "Aborted: Shutdown requested.";
00038 as_.setAborted( result_, result_.text );
00039 }
00040 dock_.disable();
00041 toggleMotor(false);
00042 }
00043
00044 bool AutoDockingROS::init(ros::NodeHandle& nh)
00045 {
00046 motor_power_enabler_ = nh.advertise<kobuki_msgs::MotorPower>("motor_power", 10);
00047 velocity_commander_ = nh.advertise<geometry_msgs::Twist>("velocity", 10);
00048 debug_jabber_ = nh.advertise<std_msgs::String>("debug/feedback", 10);
00049
00050 debug_ = nh.subscribe("debug/mode_shift", 10, &AutoDockingROS::debugCb, this);
00051
00052 odom_sub_.reset(new message_filters::Subscriber<nav_msgs::Odometry>(nh, "odom", 10));
00053 core_sub_.reset(new message_filters::Subscriber<kobuki_msgs::SensorState>(nh, "core", 10));
00054 ir_sub_.reset(new message_filters::Subscriber<kobuki_msgs::DockInfraRed>(nh, "dock_ir", 10));
00055 sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), *odom_sub_, *core_sub_, *ir_sub_));
00056 sync_->registerCallback(boost::bind(&AutoDockingROS::syncCb, this, _1, _2, _3));
00057
00058 return dock_.init();
00059 }
00060
00061 void AutoDockingROS::spin()
00062 {
00063 return;
00064
00065 while(!shutdown_requested_){;}
00066 }
00067
00068 void AutoDockingROS::goalCb()
00069 {
00070 if (dock_.isEnabled()) {
00071 goal_ = *(as_.acceptNewGoal());
00072 result_.text = "Rejected: dock_drive is already enabled.";
00073 as_.setAborted( result_, result_.text );
00074 ROS_INFO_STREAM("[" << name_ << "] New goal received but rejected.");
00075 } else {
00076 goal_ = *(as_.acceptNewGoal());
00077 toggleMotor(true);
00078 dock_.enable();
00079 ROS_INFO_STREAM("[" << name_ << "] New goal received and accepted.");
00080 }
00081 }
00082
00083 void AutoDockingROS::preemptCb()
00084 {
00085
00086 dock_.disable();
00087 if (as_.isNewGoalAvailable()) {
00088 result_.text = "Preempted: New goal received.";
00089 as_.setPreempted( result_, result_.text );
00090 ROS_INFO_STREAM("[" << name_ << "] " << result_.text );
00091 } else {
00092 result_.text = "Cancelled: Cancel requested.";
00093 as_.setPreempted( result_, result_.text );
00094 ROS_INFO_STREAM("[" << name_ << "] " << result_.text );
00095 dock_.disable();
00096 toggleMotor(false);
00097 }
00098 }
00099
00100 void AutoDockingROS::syncCb(const nav_msgs::OdometryConstPtr& odom,
00101 const kobuki_msgs::SensorStateConstPtr& core,
00102 const kobuki_msgs::DockInfraRedConstPtr& ir)
00103 {
00104
00105 if (self->dock_.isEnabled()) {
00106
00107 KDL::Rotation rot;
00108 tf::quaternionMsgToKDL( odom->pose.pose.orientation, rot );
00109
00110 double r, p, y;
00111 rot.GetRPY(r, p, y);
00112
00113 ecl::Pose2D<double> pose;
00114 pose.x(odom->pose.pose.position.x);
00115 pose.y(odom->pose.pose.position.y);
00116 pose.heading(y);
00117
00118
00119 self->dock_.update(ir->data, core->bumper, core->charger, pose);
00120
00121
00122 std_msgs::StringPtr debug_log(new std_msgs::String);
00123 debug_log->data = self->dock_.getDebugStream();
00124 debug_jabber_.publish(debug_log);
00125
00126
00127 if (self->dock_.canRun()) {
00128 geometry_msgs::TwistPtr cmd_vel(new geometry_msgs::Twist);
00129 cmd_vel->linear.x = self->dock_.getVX();
00130 cmd_vel->angular.z = self->dock_.getWZ();
00131 velocity_commander_.publish(cmd_vel);
00132 }
00133 }
00134
00135
00136 if( as_.isActive() ) {
00137 if ( dock_.getState() == dock_.DONE ) {
00138 result_.text = "Arrived on docking station successfully.";
00139 as_.setSucceeded(result_);
00140 ROS_INFO_STREAM( "[" << name_ << "]: Arrived on docking station successfully.");
00141 ROS_DEBUG_STREAM( "[" << name_ << "]: Result sent.");
00142 dock_.disable();
00143 toggleMotor(false);
00144 } else if ( !dock_.isEnabled() ) {
00145 ROS_ERROR_STREAM("[" << name_ << "] Unintended Case: ActionService is active, but DockDrive is not enabled..");
00146 result_.text = "Aborted: dock_drive is disabled unexpectedly.";
00147 as_.setAborted( result_, "Aborted: dock_drive is disabled unexpectedly." );
00148 ROS_INFO_STREAM("[" << name_ << "] Goal aborted.");
00149 dock_.disable();
00150 toggleMotor(false);
00151 } else {
00152 feedback_.state = dock_.getStateStr();
00153 feedback_.text = dock_.getDebugStr();
00154 as_.publishFeedback(feedback_);
00155 ROS_DEBUG_STREAM( "[" << name_ << "]: Feedback sent.");
00156 }
00157 }
00158 return;
00159 }
00160
00161 void AutoDockingROS::debugCb(const std_msgs::StringConstPtr& msg)
00162 {
00163 dock_.modeShift(msg->data);
00164 }
00165
00166 void AutoDockingROS::toggleMotor(const bool& on_off)
00167 {
00168 kobuki_msgs::MotorPowerPtr power_cmd(new kobuki_msgs::MotorPower);
00169 if (on_off) power_cmd->state = kobuki_msgs::MotorPower::ON;
00170 else power_cmd->state = kobuki_msgs::MotorPower::OFF;
00171 motor_power_enabler_.publish(power_cmd);
00172 }
00173
00174 }