control_plugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <math.h>
19 #include <angles/angles.h>
20 #include <boost/scoped_ptr.hpp>
21 #include <boost/thread/mutex.hpp>
22 
26 
28 #include <cob_base_controller_utils/WheelCommands.h>
29 #include <geometry_msgs/Twist.h>
30 
32 
34 
36 {
37 
38 double limitValue(double value, double limit){
39  if(limit != 0){
40  if (value > limit){
41  value = limit;
42  } else if (value < -limit) {
43  value = -limit;
44  }
45  }
46  return value;
47 }
48 
49 
50 class WheelController : public controller_interface::MultiInterfaceController<hardware_interface::VelocityJointInterface, hardware_interface::PositionJointInterface>
51 {
52 public:
53  virtual bool init(hardware_interface::RobotHW* robot_hw, ros::NodeHandle &nh)
54  {
55  if (!nh.getParam("steer_joint", wheel_state_.steer_name)){
56  ROS_ERROR("Parameter 'steer_joint' not set");
57  return false;
58  }
59  if (!nh.getParam("drive_joint", wheel_state_.drive_name)){
60  ROS_ERROR("Parameter 'drive_joint' not set");
61  return false;
62  }
63 
66  steer_joint_ = p->getHandle(wheel_state_.steer_name);
68 
69  urdf::Model model;
70  std::string description_name;
71  bool has_model = nh.searchParam("robot_description", description_name) && model.initParam(description_name);
72 
73  urdf::Vector3 steer_pos;
74  urdf::JointConstSharedPtr steer_joint;
75  urdf::JointConstSharedPtr drive_joint;
76 
77  if(has_model){
78  steer_joint = model.getJoint(wheel_state_.steer_name);
79  if(steer_joint){
80  tf2::Transform transform;
81  //root link for tricycle is "base_pivot_link"
82  if(parseWheelTransform(wheel_state_.steer_name, model.getRoot()->name, transform, &model)){
83  wheel_state_.pos_x = transform.getOrigin().getX();
84  wheel_state_.pos_y = transform.getOrigin().getY();
85  wheel_state_.radius = transform.getOrigin().getZ();
86  wheel_state_.sign = cos(transform.getRotation().getAngle());
87  }
88  nh.param("max_steer_rate", max_steer_rate_, 0.0);
89  max_steer_rate_ = (max_steer_rate_ != 0.0 && max_steer_rate_ < steer_joint->limits->velocity) ? max_steer_rate_ : steer_joint->limits->velocity;
90  }
91  drive_joint = model.getJoint(wheel_state_.drive_name);
92  if(drive_joint){
93  nh.param("max_drive_rate", max_drive_rate_, 0.0);
94  max_drive_rate_ = (max_drive_rate_ != 0.0 && max_drive_rate_ < drive_joint->limits->velocity) ? max_drive_rate_ : drive_joint->limits->velocity;
95  }
96  }
97 
98  nh.param("max_trans_velocity", max_vel_trans_, 0.0);
99  if(max_vel_trans_ < 0){
100  ROS_ERROR_STREAM("max_trans_velocity must be non-negative.");
101  return false;
102  }
103  nh.param("max_rot_velocity", max_vel_rot_, 0.0);
104  if(max_vel_rot_ < 0){
105  ROS_ERROR_STREAM("max_rot_velocity must be non-negative.");
106  return false;
107  }
108  double timeout;
109  nh.param("timeout", timeout, 1.0);
110  if(timeout < 0){
111  ROS_ERROR_STREAM("timeout must be non-negative.");
112  return false;
113  }
114  timeout_.fromSec(timeout);
115 
116  pub_divider_ = nh.param("pub_divider", 0);
119 
120  commands_pub_->msg_.drive_target_velocity.resize(1);
121  commands_pub_->msg_.steer_target_velocity.resize(1);
122  commands_pub_->msg_.steer_target_position.resize(1);
123  commands_pub_->msg_.steer_target_error.resize(1);
124 
125  return true;
126  }
127 
128  virtual void starting(const ros::Time& time){
129  cycles_ = 0;
130  }
131 
132  virtual void update(const ros::Time& time, const ros::Duration& period)
133  {
134  {
135  boost::mutex::scoped_try_lock lock(mutex_);
136  if(lock){
137  Target target = target_;
138  target_.updated = false;
139 
140  if(!target.stamp.isZero() && !timeout_.isZero() && (time - target.stamp) > timeout_){
141  ROS_WARN_STREAM("target timed out");
142  target_.stamp = ros::Time(); // only reset once
143  target.state = PlatformState();
144  target.updated = true;
145  }
146  lock.unlock();
147  }
148  }
149 
150  updateCommand();
151 
154 
155  if(cycles_ < pub_divider_ && (++cycles_) == pub_divider_){
156  if(commands_pub_->trylock()){
157  ++(commands_pub_->msg_.header.seq);
158  commands_pub_->msg_.header.stamp = time;
159 
160  commands_pub_->msg_.drive_target_velocity[0] = wheel_command_.drive_vel;
161  commands_pub_->msg_.steer_target_velocity[0] = 0.0;
162  commands_pub_->msg_.steer_target_position[0] = wheel_command_.steer_pos;
163  commands_pub_->msg_.steer_target_error[0] = wheel_command_.steer_pos - wheel_state_.steer_pos;
164  commands_pub_->unlockAndPublish();
165  }
166  cycles_ = 0;
167  }
168  }
169 
170 private:
171  struct Target {
173  bool updated;
175  } target_;
176 
181 
182  boost::mutex mutex_;
184 
185  boost::scoped_ptr<realtime_tools::RealtimePublisher<cob_base_controller_utils::WheelCommands> > commands_pub_;
186  uint32_t cycles_;
187  uint32_t pub_divider_;
188 
192 
193  void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr& msg){
194  if(this->isRunning()){
195  boost::mutex::scoped_lock lock(mutex_);
196  if(isnan(msg->linear.x) || isnan(msg->linear.y) || isnan(msg->angular.z)) {
197  ROS_FATAL("Received NaN-value in Twist message. Reset target to zero.");
199  }else{
200  target_.state.velX = limitValue(msg->linear.x, max_vel_trans_);
201  target_.state.velY = limitValue(msg->linear.y, max_vel_trans_);
202  target_.state.rotTheta = limitValue(msg->angular.z, max_vel_rot_);
203  }
204  target_.updated = true;
206  }
207  }
208 
210  //get JointState from JointHandles
215 
216  // calculate inverse kinematics
217  // http://www.wolframalpha.com/input/?i=Solve%5Bx%3D%3Dw*cos(a),+phi%3D%3Dw*sin(a)%2Fr,a,w%5D
218  double r_base = wheel_state_.pos_x * wheel_state_.sign;
219  double k = sqrt(pow(r_base,2)*pow(target_.state.rotTheta,2) + pow(target_.state.velX,2));
220  if (target_.state.rotTheta != 0)
221  {
222  double a1 = 2 * atan2(k - target_.state.velX, r_base*target_.state.rotTheta);
223  a1 = angles::normalize_angle(a1);
224  double b1 = k / wheel_state_.radius;
225 
226  double a2 = -2 * atan2(k + target_.state.velX, r_base*target_.state.rotTheta);
227  a2 = angles::normalize_angle(a2);
228  double b2 = - k / wheel_state_.radius;
229 
230  if (fabs(a1-wheel_state_.steer_pos) <= fabs(a2-wheel_state_.steer_pos))
231  {
234  }
235  else
236  {
239  }
240  }
241  else if (target_.state.velX != 0)
242  {
243  if (fabs(0.0-wheel_state_.steer_pos) <= fabs(M_PI-wheel_state_.steer_pos))
244  {
247  }
248  else
249  {
250  wheel_command_.steer_pos = M_PI;
252  }
253  }
254  else {
257  }
258 
260  }
261 };
262 
263 }
264 
cob_tricycle_controller::WheelController::Target::state
PlatformState state
Definition: control_plugin.cpp:172
WheelState::sign
double sign
Definition: TricycleCtrlTypes.h:47
realtime_publisher.h
cob_tricycle_controller
Definition: control_plugin.cpp:35
WheelState
Definition: TricycleCtrlTypes.h:35
DurationBase< Duration >::fromSec
Duration & fromSec(double t)
WheelState::drive_vel
double drive_vel
Definition: TricycleCtrlTypes.h:41
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
cob_tricycle_controller::WheelController::twist_subscriber_
ros::Subscriber twist_subscriber_
Definition: control_plugin.cpp:183
cob_tricycle_controller::WheelController::topicCallbackTwistCmd
void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr &msg)
Definition: control_plugin.cpp:193
cob_tricycle_controller::WheelController::cycles_
uint32_t cycles_
Definition: control_plugin.cpp:186
HardwareResourceManager< JointHandle, ClaimResources >::getHandle
JointHandle getHandle(const std::string &name)
cob_tricycle_controller::WheelController::mutex_
boost::mutex mutex_
Definition: control_plugin.cpp:182
hardware_interface::InterfaceManager::get
T * get()
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
WheelState::drive_name
std::string drive_name
Definition: TricycleCtrlTypes.h:36
WheelState::pos_y
double pos_y
Definition: TricycleCtrlTypes.h:44
PlatformState::rotTheta
double rotTheta
Definition: TricycleCtrlTypes.h:30
tf2::Transform::getOrigin
TF2SIMD_FORCE_INLINE Vector3 & getOrigin()
WheelState::steer_vel
double steer_vel
Definition: TricycleCtrlTypes.h:39
angles::normalize_angle
def normalize_angle(angle)
cob_tricycle_controller::WheelController::max_drive_rate_
double max_drive_rate_
Definition: control_plugin.cpp:191
urdf::Model
cob_tricycle_controller::WheelController::max_vel_trans_
double max_vel_trans_
Definition: control_plugin.cpp:190
hardware_interface::JointHandle::setCommand
void setCommand(double command)
cob_tricycle_controller::WheelController::starting
virtual void starting(const ros::Time &time)
Definition: control_plugin.cpp:128
cob_tricycle_controller::WheelController::pub_divider_
uint32_t pub_divider_
Definition: control_plugin.cpp:187
WheelState::steer_pos
double steer_pos
Definition: TricycleCtrlTypes.h:38
cob_tricycle_controller::WheelController::updateCommand
void updateCommand()
Definition: control_plugin.cpp:209
WheelState::steer_name
std::string steer_name
Definition: TricycleCtrlTypes.h:36
cob_tricycle_controller::WheelController
Definition: control_plugin.cpp:50
class_list_macros.h
realtime_tools::RealtimePublisher
controller_interface::ControllerBase
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
hardware_interface::VelocityJointInterface
cob_tricycle_controller::WheelController::wheel_state_
WheelState wheel_state_
Definition: control_plugin.cpp:177
PLUGINLIB_EXPORT_CLASS
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
parseWheelTransform
bool parseWheelTransform(const std::string &joint_name, const std::string &parent_link_name, tf2::Transform &transform, urdf::Model *model)
Definition: param_parser.h:27
joint_command_interface.h
hardware_interface::RobotHW
TimeBase< Time, Duration >::isZero
bool isZero() const
cob_tricycle_controller::WheelController::max_vel_rot_
double max_vel_rot_
Definition: control_plugin.cpp:190
controller_interface::MultiInterfaceController
tf2::Quaternion::getAngle
tf2Scalar getAngle() const
cob_tricycle_controller::WheelController::steer_joint_
hardware_interface::JointHandle steer_joint_
Definition: control_plugin.cpp:179
ros::NodeHandle::searchParam
bool searchParam(const std::string &key, std::string &result) const
cob_tricycle_controller::WheelController::init
virtual bool init(hardware_interface::RobotHW *robot_hw, ros::NodeHandle &nh)
Definition: control_plugin.cpp:53
tf2::Transform
cob_tricycle_controller::WheelController::Target::stamp
ros::Time stamp
Definition: control_plugin.cpp:174
tf2::Transform::getRotation
Quaternion getRotation() const
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
PlatformState::velX
double velX
Definition: TricycleCtrlTypes.h:28
cob_tricycle_controller::WheelController::target_
struct cob_tricycle_controller::WheelController::Target target_
controller_interface::ControllerBase::isRunning
bool isRunning() const
TricycleCtrlTypes.h
WheelState::pos_x
double pos_x
Definition: TricycleCtrlTypes.h:43
cob_tricycle_controller::limitValue
double limitValue(double value, double limit)
Definition: control_plugin.cpp:38
ROS_FATAL
#define ROS_FATAL(...)
param_parser.h
PlatformState::velY
double velY
Definition: TricycleCtrlTypes.h:29
WheelState::radius
double radius
Definition: TricycleCtrlTypes.h:46
hardware_interface::JointHandle
WheelState::drive_pos
double drive_pos
Definition: TricycleCtrlTypes.h:40
PlatformState
Definition: TricycleCtrlTypes.h:27
hardware_interface::JointStateHandle::getVelocity
double getVelocity() const
ros::Time
cob_tricycle_controller::WheelController::Target
Definition: control_plugin.cpp:171
hardware_interface::JointStateHandle::getPosition
double getPosition() const
cob_tricycle_controller::WheelController::Target::updated
bool updated
Definition: control_plugin.cpp:173
urdf::Model::initParam
URDF_EXPORT bool initParam(const std::string &param)
cob_tricycle_controller::WheelController::max_steer_rate_
double max_steer_rate_
Definition: control_plugin.cpp:191
cob_tricycle_controller::WheelController::wheel_command_
WheelState wheel_command_
Definition: control_plugin.cpp:178
ROS_ERROR
#define ROS_ERROR(...)
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
cob_tricycle_controller::WheelController::timeout_
ros::Duration timeout_
Definition: control_plugin.cpp:189
cob_tricycle_controller::WheelController::drive_joint_
hardware_interface::JointHandle drive_joint_
Definition: control_plugin.cpp:180
cob_tricycle_controller::WheelController::commands_pub_
boost::scoped_ptr< realtime_tools::RealtimePublisher< cob_base_controller_utils::WheelCommands > > commands_pub_
Definition: control_plugin.cpp:185
cob_tricycle_controller::WheelController::update
virtual void update(const ros::Time &time, const ros::Duration &period)
Definition: control_plugin.cpp:132
hardware_interface::PositionJointInterface
ros::Duration
DurationBase< Duration >::isZero
bool isZero() const
ros::NodeHandle
ros::Subscriber
angles.h
ros::Time::now
static Time now()
multi_interface_controller.h


cob_tricycle_controller
Author(s): Felix Messmer
autogenerated on Mon May 1 2023 02:44:40