Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef H_WHEEL_CONTROLLER_IMPL
00019 #define H_WHEEL_CONTROLLER_IMPL
00020
00021 #include <controller_interface/controller.h>
00022 #include <hardware_interface/joint_command_interface.h>
00023
00024 #include <pluginlib/class_list_macros.h>
00025
00026 #include <cob_omni_drive_controller/UndercarriageCtrlGeom.h>
00027 #include <geometry_msgs/Twist.h>
00028
00029 #include <boost/scoped_ptr.hpp>
00030 #include <boost/weak_ptr.hpp>
00031 #include <boost/thread/mutex.hpp>
00032
00033 #include <realtime_tools/realtime_publisher.h>
00034 #include <cob_omni_drive_controller/WheelCommands.h>
00035
00036 namespace cob_omni_drive_controller
00037 {
00038
00039 template<typename T> class WheelControllerBase: public T
00040 {
00041 public:
00042 bool setup(ros::NodeHandle &root_nh, ros::NodeHandle& controller_nh){
00043 controller_nh.param("max_rot_velocity", max_vel_rot_, 0.0);
00044 if(max_vel_rot_ < 0){
00045 ROS_ERROR_STREAM("max_rot_velocity must be non-negative.");
00046 return false;
00047 }
00048 controller_nh.param("max_trans_velocity", max_vel_trans_, 0.0);
00049 if(max_vel_trans_ < 0){
00050 ROS_ERROR_STREAM("max_trans_velocity must be non-negative.");
00051 return false;
00052 }
00053 double timeout;
00054 controller_nh.param("timeout", timeout, 1.0);
00055 if(timeout < 0){
00056 ROS_ERROR_STREAM("timeout must be non-negative.");
00057 return false;
00058 }
00059 timeout_.fromSec(timeout);
00060
00061 pub_divider_ = controller_nh.param("pub_divider",0);
00062
00063 wheel_commands_.resize(this->wheel_states_.size());
00064 twist_subscriber_ = controller_nh.subscribe("command", 1, &WheelControllerBase::topicCallbackTwistCmd, this);
00065
00066 commands_pub_.reset(new realtime_tools::RealtimePublisher<cob_omni_drive_controller::WheelCommands>(controller_nh, "wheel_commands", 5));
00067
00068 commands_pub_->msg_.drive_target_velocity.resize(this->wheel_states_.size());
00069 commands_pub_->msg_.steer_target_velocity.resize(this->wheel_states_.size());
00070 commands_pub_->msg_.steer_target_position.resize(this->wheel_states_.size());
00071 commands_pub_->msg_.steer_target_error.resize(this->wheel_states_.size());
00072
00073 return true;
00074 }
00075 virtual void starting(const ros::Time& time){
00076 this->geom_->reset();
00077 target_.updated = false;
00078 cycles_ = 0;
00079 }
00080 void updateCtrl(const ros::Time& time, const ros::Duration& period){
00081 {
00082 boost::mutex::scoped_try_lock lock(mutex_);
00083 if(lock){
00084 Target target = target_;
00085 target_.updated = false;
00086
00087 if(!target.stamp.isZero() && !timeout_.isZero() && (time - target.stamp) > timeout_){
00088 target_.stamp = ros::Time();
00089 target.state = PlatformState();
00090 target.updated = true;
00091 }
00092 lock.unlock();
00093
00094 if(target.updated){
00095 this->geom_->setTarget(target.state);
00096 }
00097 }
00098 }
00099
00100 this->geom_->calcControlStep(wheel_commands_, period.toSec(), false);
00101
00102 if(cycles_ < pub_divider_ && (++cycles_) == pub_divider_){
00103 if(commands_pub_->trylock()){
00104 ++(commands_pub_->msg_.header.seq);
00105 commands_pub_->msg_.header.stamp = time;
00106
00107 for (unsigned i=0; i<wheel_commands_.size(); i++){
00108 commands_pub_->msg_.drive_target_velocity[i] = wheel_commands_[i].dVelGearDriveRadS;
00109 commands_pub_->msg_.steer_target_velocity[i] = wheel_commands_[i].dVelGearSteerRadS;
00110 commands_pub_->msg_.steer_target_position[i] = wheel_commands_[i].dAngGearSteerRad;
00111 commands_pub_->msg_.steer_target_error[i] = wheel_commands_[i].dAngGearSteerRadDelta;
00112 }
00113 commands_pub_->unlockAndPublish();
00114
00115 }
00116 cycles_ = 0;
00117 }
00118 }
00119 virtual void stopping(const ros::Time& time) {}
00120
00121 protected:
00122 struct Target {
00123 PlatformState state;
00124 bool updated;
00125 ros::Time stamp;
00126 } target_;
00127
00128 std::vector<WheelCommand> wheel_commands_;
00129
00130 boost::mutex mutex_;
00131 ros::Subscriber twist_subscriber_;
00132
00133 boost::scoped_ptr<realtime_tools::RealtimePublisher<cob_omni_drive_controller::WheelCommands> > commands_pub_;
00134 uint32_t cycles_;
00135 uint32_t pub_divider_;
00136
00137 ros::Duration timeout_;
00138 double max_vel_trans_, max_vel_rot_;
00139
00140 void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr& msg){
00141 if(this->isRunning()){
00142 boost::mutex::scoped_lock lock(mutex_);
00143 if(isnan(msg->linear.x) || isnan(msg->linear.y) || isnan(msg->angular.z)) {
00144 ROS_FATAL("Received NaN-value in Twist message. Reset target to zero.");
00145 target_.state = PlatformState();
00146 }else{
00147 target_.state.setVelX(limitValue(msg->linear.x, max_vel_trans_));
00148 target_.state.setVelY(limitValue(msg->linear.y, max_vel_trans_));
00149 target_.state.dRotRobRadS = limitValue(msg->angular.z, max_vel_rot_);
00150 }
00151 target_.updated = true;
00152 target_.stamp = ros::Time::now();
00153 }
00154 }
00155
00156
00157 };
00158
00159 }
00160 #endif