WheelControllerBase.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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(); // only reset once
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


cob_omni_drive_controller
Author(s): Christian Connette, Mathias Lüdtke
autogenerated on Thu Jun 6 2019 21:19:19