noid_mover_controller.cpp
Go to the documentation of this file.
3 
4 using namespace noid;
5 using namespace mover;
6 
8  nh_(_nh),hw_(_in_hw),
9  vx_(0), vy_(0), vth_(0), x_(0), y_(0), th_(0)//, base_spinner_(1, &base_queue_)
10 {
11  //--- calcurate the coefficient(k1_,k2_) for wheel FK--
12  float wheel_radius,tread,wheelbase;
13  nh_.getParam("noid_mover_controller/wheel_radius", wheel_radius);
14  nh_.getParam("noid_mover_controller/tread", tread);
15  nh_.getParam("noid_mover_controller/wheelbase", wheelbase);
16 
17  k1_ = - sqrt(2) * ( sqrt( pow(tread,2)+pow(wheelbase,2) )/2 ) * sin( M_PI/4 + atan2(tread/2,wheelbase/2) ) / wheel_radius;
18  k2_ = 1 / wheel_radius;
19  //---------
20 
21  nh_.getParam("noid_mover_controller/ros_rate", ros_rate_);
22  nh_.getParam("noid_mover_controller/odom_rate", odom_rate_);
23  nh_.getParam("noid_mover_controller/safety_rate", safety_rate_);
24  nh_.getParam("noid_mover_controller/safety_duration", safety_duration_);
25  nh_.getParam("/joint_settings/wheel/aero_index", aero_index_);
26 
27  num_of_wheels_ = aero_index_.size();
28 
29  servo_on_ = false;
32 
33 /*
34  base_ops_ = ros::SubscribeOptions::create<geometry_msgs::Twist >( "cmd_vel", 2, boost::bind(&NoidMoverController::cmdVelCallback, this, _1),ros::VoidPtr(), &base_queue_);
35  cmd_vel_sub_ = nh_.subscribe(base_ops_);
36  ros::TimerOptions tmopt(ros::Duration(safety_rate_), boost::bind(&NoidMoverController::safetyCheckCallback,this, _1), &base_queue_);
37  safe_timer_ = _nh.createTimer(tmopt);
38  base_spinner_.start();
39 */
40 
43 
44  // for odometory
45  odom_pub_ = nh_.advertise<nav_msgs::Odometry>("odom", 1);
47 }
48 
52 {
53 }
54 
57 void NoidMoverController::cmdVelCallback(const geometry_msgs::TwistConstPtr& _cmd_vel)
58 {
59  ros::Time now = ros::Time::now();
60  ROS_DEBUG("cmd_vel: %f %f %f", _cmd_vel->linear.x, _cmd_vel->linear.y, _cmd_vel->angular.z);
61 
62  if (base_mtx_.try_lock()) {
63  if (_cmd_vel->linear.x == 0.0 && _cmd_vel->linear.y == 0.0 && _cmd_vel->angular.z == 0.0) {
64  vx_ = vy_ = vth_ = 0.0;
65  }
66 /*
67  else{
68  vx_ = _cmd_vel->linear.x;
69  vy_ = _cmd_vel->linear.y;
70  vth_ = _cmd_vel->angular.z;
71  }
72 */
73  else {
74  double dt = (now - time_stamp_).toSec();
75  double acc_x = (_cmd_vel->linear.x - vx_) / dt;
76  double acc_y = (_cmd_vel->linear.y - vy_) / dt;
77  double acc_z = (_cmd_vel->angular.z - vth_) / dt;
78 
79  ROS_DEBUG("vel_acc: %f %f %f", acc_x, acc_y, acc_z);
80 
81  if (acc_x > MAX_ACC_X) acc_x = MAX_ACC_X;
82  if (acc_x < - MAX_ACC_X) acc_x = - MAX_ACC_X;
83  if (acc_y > MAX_ACC_Y) acc_y = MAX_ACC_Y;
84  if (acc_y < - MAX_ACC_Y) acc_y = - MAX_ACC_Y;
85  if (acc_z > MAX_ACC_Z) acc_z = MAX_ACC_Z;
86  if (acc_z < - MAX_ACC_Z) acc_z = - MAX_ACC_Z;
87 
88  vx_ += acc_x * dt;
89  vy_ += acc_y * dt;
90  vth_ += acc_z * dt;
91  }
92  ROS_DEBUG("act_vel: %f %f %f", vx_, vy_, vth_);
93 
94  //check servo state
95  if ( !servo_on_ ) {
96  servo_on_ = true;
98  }
99 
100  std::vector<int16_t> wheel_vel(num_of_wheels_);
101 
102  // convert velocity to wheel
103  // need to declarion check
104  velocityToWheel(vx_, vy_, vth_, wheel_vel);
105 
106  hw_->writeWheel(wheel_vel);
107 
108  //update time_stamp_
109  time_stamp_ = now;
110 
111  base_mtx_.unlock();
112  } else {
113  ROS_WARN("cmd_vel comes before sending pervious message");
114  }
115 }
116 
121 {
122  if((ros::Time::now() - time_stamp_).toSec() >= safety_duration_ && servo_on_) {
123  std::vector<int16_t> wheel_velocity(num_of_wheels_);
124 
125  vx_ = vy_ = vth_ = 0.0;
126  ROS_WARN("Base: safety stop");
127  for (size_t i = 0; i < num_of_wheels_; i++) {
128  wheel_velocity[i] = 0;
129  }
130  hw_->writeWheel(wheel_velocity);
131 
132  servo_on_ = false;
134  }
135 }
136 
140 {
142 
143  double dt, delta_x, delta_y, delta_th;
144  dt = (current_time_ - last_time_).toSec();
145  delta_x = (vx_ * cos(th_) - vy_ * sin(th_)) * dt;
146  delta_y = (vx_ * sin(th_) + vy_ * cos(th_)) * dt;
147  delta_th = vth_ * dt;
148 
149  x_ += delta_x;
150  y_ += delta_y;
151  th_ += delta_th;
152 
153  // odometry is 6DOF so we'll need a quaternion created from yaw
154  geometry_msgs::Quaternion odom_quat
156 
157  // first, we'll publish the transform over tf
158  geometry_msgs::TransformStamped odom_trans;
159  odom_trans.header.stamp = current_time_;
160  odom_trans.header.frame_id = "odom";
161  odom_trans.child_frame_id = "base_link";
162 
163  odom_trans.transform.translation.x = x_;
164  odom_trans.transform.translation.y = y_;
165  odom_trans.transform.translation.z = 0.0;
166  odom_trans.transform.rotation = odom_quat;
167 
168  // send the transform
169  odom_broadcaster_.sendTransform(odom_trans);
170 
171  // next, we'll publish the odometry message over ROS
172  nav_msgs::Odometry odom;
173  odom.header.stamp = current_time_;
174  odom.header.frame_id = "odom";
175 
176  // set the position
177  odom.pose.pose.position.x = x_;
178  odom.pose.pose.position.y = y_;
179  odom.pose.pose.position.z = 0.0;
180  odom.pose.pose.orientation = odom_quat;
181 
182  // set the velocity
183  odom.child_frame_id = "base_link";
184  odom.twist.twist.linear.x = vx_;
185  odom.twist.twist.linear.y = vy_;
186  odom.twist.twist.angular.z = vth_;
187 
188  // publish the message
189  odom_pub_.publish(odom);
190 
192 }
193 
194 void NoidMoverController::velocityToWheel(double _linear_x, double _linear_y, double _angular_z, std::vector<int16_t>& _wheel_vel)
195 {
196  float dx, dy, dtheta, theta;
197  float v1, v2, v3, v4;
198  int16_t front_right_wheel, rear_right_wheel, front_left_wheel, rear_left_wheel;
199  theta = 0.0; // this means angle in local coords, so always 0
200 
201  float cos_theta = cos(theta);
202  float sin_theta = sin(theta);
203 
204  // change dy and dx, because of between ROS and vehicle direction
205  dy = (_linear_x * cos_theta - _linear_y * sin_theta);
206  dx = (_linear_x * sin_theta + _linear_y * cos_theta);
207  dtheta = _angular_z; // desirede angular velocity
208 
209  // calculate wheel velocity
210  v1 = k1_ * dtheta + k2_ * ((-cos_theta + sin_theta) * dx + (-cos_theta - sin_theta) * dy);
211  v2 = k1_ * dtheta + k2_ * ((-cos_theta - sin_theta) * dx + ( cos_theta - sin_theta) * dy);
212  v3 = k1_ * dtheta + k2_ * (( cos_theta - sin_theta) * dx + ( cos_theta + sin_theta) * dy);
213  v4 = k1_ * dtheta + k2_ * (( cos_theta + sin_theta) * dx + (-cos_theta + sin_theta) * dy);
214 
215  //[rad/sec] -> [deg/sec]
216  front_right_wheel = static_cast<int16_t>(v1 * (180 / M_PI));
217  rear_right_wheel = static_cast<int16_t>(v4 * (180 / M_PI));
218  front_left_wheel = static_cast<int16_t>(v2 * (180 / M_PI));
219  rear_left_wheel = static_cast<int16_t>(v3 * (180 / M_PI));
220 
221  _wheel_vel[0] = front_left_wheel;
222  _wheel_vel[1] = front_right_wheel;
223  _wheel_vel[2] = rear_left_wheel;
224  _wheel_vel[3] = rear_right_wheel;
225 }
void velocityToWheel(double _linear_x, double _linear_y, double _angular_z, std::vector< int16_t > &_wheel_vel)
void publish(const boost::shared_ptr< M > &message) const
wheelbase
void calculateOdometry(const ros::TimerEvent &_event)
odometry publisher
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void cmdVelCallback(const geometry_msgs::TwistConstPtr &_cmd_vel)
control with cmd_vel
tf::TransformBroadcaster odom_broadcaster_
#define MAX_ACC_Z
NoidMoverController(const ros::NodeHandle &_nh, noid_robot_hardware::NoidRobotHW *_in_hw)
#define ROS_WARN(...)
void safetyCheckCallback(const ros::TimerEvent &_event)
safety stopper when msg is not reached for more than safety_duration_ [s]
void writeWheel(const std::vector< std::string > &_names, const std::vector< int16_t > &_vel, double _tm_sec)
#define MAX_ACC_Y
void sendTransform(const StampedTransform &transform)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
bool getParam(const std::string &key, std::string &s) const
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
static Time now()
#define MAX_ACC_X
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
noid_robot_hardware::NoidRobotHW * hw_
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
#define ROS_DEBUG(...)


noid_ros_controller
Author(s): Yohei Kakiuchi
autogenerated on Sat Jul 20 2019 03:44:30