seed_r7_mover_controller.cpp
Go to the documentation of this file.
3 
5 (const ros::NodeHandle& _nh, robot_hardware::RobotHW *_in_hw) :
6  nh_(_nh),hw_(_in_hw),
7  vx_(0), vy_(0), vth_(0), x_(0), y_(0), th_(0)//, base_spinner_(1, &base_queue_)
8 {
9  move_base_action_ = new actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>("/move_base", true);
10 
11  //--- calcurate the coefficient(k1_,k2_) for wheel FK--
12  float wheel_radius,tread,wheelbase;
13  nh_.getParam("/seed_r7_mover_controller/wheel_radius", wheel_radius);
14  nh_.getParam("/seed_r7_mover_controller/tread", tread);
15  nh_.getParam("/seed_r7_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("/seed_r7_mover_controller/ros_rate", ros_rate_);
22  nh_.getParam("/seed_r7_mover_controller/odom_rate", odom_rate_);
23  nh_.getParam("/seed_r7_mover_controller/safety_rate", safety_rate_);
24  nh_.getParam("/seed_r7_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;
30  current_time_ = ros::Time::now();
31  last_time_ = current_time_;
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 
41  cmd_vel_sub_ = nh_.subscribe("cmd_vel",1, &MoverController::cmdVelCallback,this);
42  safe_timer_ = nh_.createTimer(ros::Duration(safety_rate_), &MoverController::safetyCheckCallback, this);
43 
44  // for odometory
45  odom_pub_ = nh_.advertise<nav_msgs::Odometry>("odom", 1);
46  odom_timer_ = nh_.createTimer(ros::Duration(odom_rate_), &MoverController::calculateOdometry, this);
47 
48  initialpose_pub_ = nh_.advertise<geometry_msgs::PoseWithCovarianceStamped>("/initialpose", 1);
49  led_control_server_
50  = nh_.advertiseService("led_control", &MoverController::ledControlCallback,this);
51 
52  set_initialpose_server_
53  = nh_.advertiseService("set_initialpose", &MoverController::setInitialPoseCallback,this);
54 
55 }
56 
60 {
61 }
62 
65 void robot_hardware::MoverController::cmdVelCallback(const geometry_msgs::TwistConstPtr& _cmd_vel)
66 {
67  ros::Time now = ros::Time::now();
68  ROS_DEBUG("cmd_vel: %f %f %f", _cmd_vel->linear.x, _cmd_vel->linear.y, _cmd_vel->angular.z);
69 
70  if (base_mtx_.try_lock()) {
72  {
73  //move_base_action_->cancelAllGoals(); //if you want to cancel goal, use this
74  vx_ = vy_ = vth_ = 0.0;
75  }
76  else if (_cmd_vel->linear.x == 0.0 && _cmd_vel->linear.y == 0.0 && _cmd_vel->angular.z == 0.0) {
77  vx_ = vy_ = vth_ = 0.0;
78  }
79  else{
80  vx_ = _cmd_vel->linear.x;
81  vy_ = _cmd_vel->linear.y;
82  vth_ = _cmd_vel->angular.z;
83  }
84 /*
85  else {
86  double dt = (now - time_stamp_).toSec();
87  double acc_x = (_cmd_vel->linear.x - vx_) / dt;
88  double acc_y = (_cmd_vel->linear.y - vy_) / dt;
89  double acc_z = (_cmd_vel->angular.z - vth_) / dt;
90 
91  ROS_DEBUG("vel_acc: %f %f %f", acc_x, acc_y, acc_z);
92 
93  if (acc_x > MAX_ACC_X) acc_x = MAX_ACC_X;
94  if (acc_x < - MAX_ACC_X) acc_x = - MAX_ACC_X;
95  if (acc_y > MAX_ACC_Y) acc_y = MAX_ACC_Y;
96  if (acc_y < - MAX_ACC_Y) acc_y = - MAX_ACC_Y;
97  if (acc_z > MAX_ACC_Z) acc_z = MAX_ACC_Z;
98  if (acc_z < - MAX_ACC_Z) acc_z = - MAX_ACC_Z;
99 
100  vx_ += acc_x * dt;
101  vy_ += acc_y * dt;
102  vth_ += acc_z * dt;
103  }
104 */
105  ROS_DEBUG("act_vel: %f %f %f", vx_, vy_, vth_);
106 
107  //check servo state
108  if ( !servo_on_ ) {
109  servo_on_ = true;
111  }
112 
113  std::vector<int16_t> wheel_vel(num_of_wheels_);
114 
115  // convert velocity to wheel
116  // need to declarion check
117  velocityToWheel(vx_, vy_, vth_, wheel_vel);
118 
119  hw_->turnWheel(wheel_vel);
120 
121  //update time_stamp_
122  time_stamp_ = now;
123 
124  base_mtx_.unlock();
125  } else {
126  ROS_WARN("cmd_vel comes before sending pervious message");
127  }
128 }
129 
134 {
135  if((ros::Time::now() - time_stamp_).toSec() >= safety_duration_ && servo_on_) {
136  std::vector<int16_t> wheel_velocity(num_of_wheels_);
137 
138  vx_ = vy_ = vth_ = 0.0;
139  ROS_WARN("Base: safety stop");
140  for (size_t i = 0; i < num_of_wheels_; i++) {
141  wheel_velocity[i] = 0;
142  }
143  hw_->turnWheel(wheel_velocity);
144 
145  servo_on_ = false;
147  }
148 }
149 
153 {
155 
156  double dt, delta_x, delta_y, delta_th;
157  dt = (current_time_ - last_time_).toSec();
158  delta_x = (vx_ * cos(th_) - vy_ * sin(th_)) * dt;
159  delta_y = (vx_ * sin(th_) + vy_ * cos(th_)) * dt;
160  delta_th = vth_ * dt;
161 
162  x_ += delta_x;
163  y_ += delta_y;
164  th_ += delta_th;
165 
166  // odometry is 6DOF so we'll need a quaternion created from yaw
167  geometry_msgs::Quaternion odom_quat
169 
170  // first, we'll publish the transform over tf
171  geometry_msgs::TransformStamped odom_trans;
172  odom_trans.header.stamp = current_time_;
173  odom_trans.header.frame_id = "odom";
174  odom_trans.child_frame_id = "base_link";
175 
176  odom_trans.transform.translation.x = x_;
177  odom_trans.transform.translation.y = y_;
178  odom_trans.transform.translation.z = 0.0;
179  odom_trans.transform.rotation = odom_quat;
180 
181  // send the transform
182  odom_broadcaster_.sendTransform(odom_trans);
183 
184  // next, we'll publish the odometry message over ROS
185  nav_msgs::Odometry odom;
186  odom.header.stamp = current_time_;
187  odom.header.frame_id = "odom";
188 
189  // set the position
190  odom.pose.pose.position.x = x_;
191  odom.pose.pose.position.y = y_;
192  odom.pose.pose.position.z = 0.0;
193  odom.pose.pose.orientation = odom_quat;
194 
195  // set the velocity
196  odom.child_frame_id = "base_link";
197  odom.twist.twist.linear.x = vx_;
198  odom.twist.twist.linear.y = vy_;
199  odom.twist.twist.angular.z = vth_;
200 
201  // publish the message
202  odom_pub_.publish(odom);
203 
205 }
206 
208 (double _linear_x, double _linear_y, double _angular_z, std::vector<int16_t>& _wheel_vel)
209 {
210  float dx, dy, dtheta, theta;
211  float v1, v2, v3, v4;
212  int16_t front_right_wheel, rear_right_wheel, front_left_wheel, rear_left_wheel;
213  theta = 0.0; // this means angle in local coords, so always 0
214 
215  float cos_theta = cos(theta);
216  float sin_theta = sin(theta);
217 
218  // change dy and dx, because of between ROS and vehicle direction
219  dy = (_linear_x * cos_theta - _linear_y * sin_theta);
220  dx = (_linear_x * sin_theta + _linear_y * cos_theta);
221  dtheta = _angular_z; // desirede angular velocity
222 
223  // calculate wheel velocity
224  v1 = k1_ * dtheta + k2_ * ((-cos_theta + sin_theta) * dx + (-cos_theta - sin_theta) * dy);
225  v2 = k1_ * dtheta + k2_ * ((-cos_theta - sin_theta) * dx + ( cos_theta - sin_theta) * dy);
226  v3 = k1_ * dtheta + k2_ * (( cos_theta - sin_theta) * dx + ( cos_theta + sin_theta) * dy);
227  v4 = k1_ * dtheta + k2_ * (( cos_theta + sin_theta) * dx + (-cos_theta + sin_theta) * dy);
228 
229  //[rad/sec] -> [deg/sec]
230  front_right_wheel = static_cast<int16_t>(v1 * (180 / M_PI));
231  rear_right_wheel = static_cast<int16_t>(v4 * (180 / M_PI));
232  front_left_wheel = static_cast<int16_t>(v2 * (180 / M_PI));
233  rear_left_wheel = static_cast<int16_t>(v3 * (180 / M_PI));
234 
235  _wheel_vel[0] = front_left_wheel;
236  _wheel_vel[1] = front_right_wheel;
237  _wheel_vel[2] = rear_left_wheel;
238  _wheel_vel[3] = rear_right_wheel;
239 }
240 
243 (seed_r7_ros_controller::SetInitialPose::Request& _req,
244 seed_r7_ros_controller::SetInitialPose::Response& _res)
245 {
246  geometry_msgs::PoseWithCovarianceStamped initial_pose;
247  geometry_msgs::Quaternion pose_quat = tf::createQuaternionMsgFromYaw(_req.theta);
248 
249  initial_pose.header.stamp = ros::Time::now();
250  initial_pose.header.frame_id = "map";
251  initial_pose.pose.pose.position.x = _req.x;
252  initial_pose.pose.pose.position.y = _req.y;
253  initial_pose.pose.pose.position.z = 0.0;
254  initial_pose.pose.pose.orientation = pose_quat;
255  initialpose_pub_.publish(initial_pose);
256 
257  return "SetInitialPose succeeded";
258 }
259 
261  (seed_r7_ros_controller::LedControl::Request& _req,
262  seed_r7_ros_controller::LedControl::Response& _res)
263 {
264  hw_->runLedScript(_req.send_number, _req.script_number);
265 
266  _res.result = "LED succeeded";
267 
268  return true;
269 }
void turnWheel(std::vector< int16_t > &_vel)
void publish(const boost::shared_ptr< M > &message) const
void runLedScript(uint8_t _number, uint16_t _script)
tf::TransformBroadcaster odom_broadcaster_
void cmdVelCallback(const geometry_msgs::TwistConstPtr &_cmd_vel)
control with cmd_vel
#define ROS_WARN(...)
struct robot_hardware::RobotHW::RobotStatus robot_status_
void calculateOdometry(const ros::TimerEvent &_event)
odometry publisher
bool setInitialPoseCallback(seed_r7_ros_controller::SetInitialPose::Request &_req, seed_r7_ros_controller::SetInitialPose::Response &_res)
void velocityToWheel(double _linear_x, double _linear_y, double _angular_z, std::vector< int16_t > &_wheel_vel)
void sendTransform(const StampedTransform &transform)
bool ledControlCallback(seed_r7_ros_controller::LedControl::Request &_req, seed_r7_ros_controller::LedControl::Response &_res)
void safetyCheckCallback(const ros::TimerEvent &_event)
safety stopper when msg is not reached for more than safety_duration_ [s]
MoverController(const ros::NodeHandle &_nh, robot_hardware::RobotHW *_in_hw)
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
static Time now()
#define ROS_DEBUG(...)


seed_r7_ros_controller
Author(s): Yohei Kakiuchi
autogenerated on Sun Apr 18 2021 02:40:34