motors.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <signal.h>
3 #include <ros/package.h>
4 #include "std_srvs/Trigger.h"
5 #include "geometry_msgs/Twist.h"
6 #include "raspicat/MotorFreqs.h"
7 #include "raspicat/TimedMotion.h"
8 #include <nav_msgs/Odometry.h>
9 #include <tf/tf.h>
12 #include <fstream>
13 #include "sensor_msgs/Imu.h"
14 
15 using namespace ros;
16 
17 bool setPower(bool);
18 void setFreqs(int left, int right);
19 
20 void onSigint(int);
21 bool callbackOn(std_srvs::Trigger::Request&, std_srvs::Trigger::Response&);
22 bool callbackOff(std_srvs::Trigger::Request&, std_srvs::Trigger::Response&);
23 bool callbackTimedMotion(raspicat::TimedMotion::Request&, raspicat::TimedMotion::Response&);
24 void callbackRaw(const raspicat::MotorFreqs::ConstPtr& msg);
25 void callbackCmdvel(const geometry_msgs::Twist::ConstPtr& msg);
26 void callback9Axis(const sensor_msgs::Imu::ConstPtr& msg);
27 
28 bool is_on = false;
29 bool in_cmdvel = false;
33 
34 geometry_msgs::Twist vel;
36 
37 bool imu_flag = false;
38 
39 bool setPower(bool on)
40 {
41  std::ofstream ofs("/dev/rtmotoren0");
42  if(not ofs.is_open())
43  return false;
44 
45  ofs << (on ? '1' : '0') << std::endl;
46  is_on = on;
47  return true;
48 }
49 
50 void setFreqs(int left, int right)
51 {
52  std::ofstream ofsL("/dev/rtmotor_raw_l0");
53  std::ofstream ofsR("/dev/rtmotor_raw_r0");
54  if( (not ofsL.is_open()) or (not ofsR.is_open()) ){
55  ROS_ERROR("Cannot open /dev/rtmotor_raw_{l,r}0");
56  return;
57  }
58 
59  ofsL << left << std::endl;
60  ofsR << right << std::endl;
61 }
62 
63 void onSigint(int sig)
64 {
65  setPower(false);
66  exit(0);
67 }
68 
69 bool callbackOn(std_srvs::Trigger::Request& request, std_srvs::Trigger::Response& response)
70 {
71  if(not setPower(true))
72  return false;
73 
74  response.message = "ON";
75  response.success = true;
76  return true;
77 }
78 
79 bool callbackOff(std_srvs::Trigger::Request& request, std_srvs::Trigger::Response& response)
80 {
81  if(not setPower(false))
82  return false;
83 
84  response.message = "OFF";
85  response.success = true;
86  return true;
87 }
88 
89 bool callbackTimedMotion(raspicat::TimedMotion::Request& request, raspicat::TimedMotion::Response& response)
90 {
91  if(not is_on){
92  ROS_INFO("Motors are not enpowered");
93  return false;
94  }
95 
96  std::ofstream ofs("/dev/rtmotor0");
97  if(not ofs.is_open()){
98  ROS_ERROR("Cannot open /dev/rtmotor0");
99  return false;
100  }
101 
102  ofs << request.left_hz << ' ' << request.right_hz << ' '
103  << request.duration_ms << std::endl;
104 
105  response.success = true;
106  return true;
107 }
108 
109 void callbackRaw(const raspicat::MotorFreqs::ConstPtr& msg)
110 {
111  setFreqs(msg->left_hz, msg->right_hz);
112 }
113 
114 void callbackCmdvel(const geometry_msgs::Twist::ConstPtr& msg)
115 {
116  vel.linear.x = msg->linear.x;
117 
118  if(!imu_flag)
119  vel.angular.z = msg->angular.z;
120 
121  double forward_hz = 50000.0*msg->linear.x/(19.0*3.141592);
122  double rot_hz = 6975.0*msg->angular.z/(19.0*3.141592);
123  setFreqs((int)round(forward_hz-rot_hz), (int)round(forward_hz+rot_hz));
124  in_cmdvel = true;
125  last_cmdvel = Time::now();
126 }
127 
128 void callback9Axis(const sensor_msgs::Imu::ConstPtr& msg)
129 {
130  if(not imu_flag){
131  ROS_INFO("9-axis sensor mode");
132  imu_flag = true;
133  }
134 
135  vel.angular.z = round(msg->angular_velocity.z * 20)/20; // cut less than 0.05[rad/s]
136 }
137 
138 nav_msgs::Odometry send_odom(void)
139 {
140  cur_time = Time::now();
141 
142  double dt = cur_time.toSec() - send_time.toSec();
143  odom_x += vel.linear.x * cos(odom_theta) * dt;
144  odom_y += vel.linear.x * sin(odom_theta) * dt;
145 
146  odom_theta += vel.angular.z * dt;
147 
148  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(odom_theta);
149 
151 
152  geometry_msgs::TransformStamped odom_trans;
153  odom_trans.header.stamp = cur_time;
154  odom_trans.header.frame_id = "odom";
155  odom_trans.child_frame_id = "base_link";
156 
157  odom_trans.transform.translation.x = odom_x;
158  odom_trans.transform.translation.y = odom_y;
159  odom_trans.transform.translation.z = 0.0;
160 
161  tf2::Quaternion q;
162  q.setRPY(0, 0, odom_theta);
163  odom_trans.transform.rotation.x = q.x();
164  odom_trans.transform.rotation.y = q.y();
165  odom_trans.transform.rotation.z = q.z();
166  odom_trans.transform.rotation.w = q.w();
167 
168  br.sendTransform(odom_trans);
169 
170  nav_msgs::Odometry odom;
171  odom.header.stamp = cur_time;
172  odom.header.frame_id = "odom";
173  odom.child_frame_id = "base_link";
174 
175  odom.pose.pose.position.x = odom_x;
176  odom.pose.pose.position.y = odom_y;
177  odom.pose.pose.position.z = 0.0;
178  odom_trans.transform.rotation = odom_quat;
179  odom.pose.pose.orientation = odom_quat;
180 
181  odom.twist.twist.linear.x = vel.linear.x;
182  odom.twist.twist.linear.y = 0.0;
183  odom.twist.twist.angular.z = vel.angular.z;
184 
185  send_time = cur_time;
186  return odom;
187 }
188 
189 int main(int argc, char **argv)
190 {
191  setFreqs(0,0);
192 
193  init(argc,argv,"motors");
194  NodeHandle n;
195 
196  std::string onoff;
197  if(argc > 1)
198  onoff = argv[1];
199 
200  setPower(onoff == "on");
201 
202  signal(SIGINT, onSigint);
203 
204  last_cmdvel = Time::now();
205  cur_time = Time::now();
206  send_time = Time::now();
207 
208  ServiceServer srv_on = n.advertiseService("motor_on", callbackOn);
209  ServiceServer srv_off = n.advertiseService("motor_off", callbackOff);
210  ServiceServer srv_tm = n.advertiseService("timed_motion", callbackTimedMotion);
211 
212  Subscriber sub_raw = n.subscribe("motor_raw", 10, callbackRaw);
213  Subscriber sub_cmdvel = n.subscribe("cmd_vel", 10, callbackCmdvel);
214  Subscriber sub_9axis = n.subscribe("/imu/data_raw", 10, callback9Axis);
215 
216  Publisher pub_odom = n.advertise<nav_msgs::Odometry>("odom", 10);
217  odom_x = 0.0;
218  odom_y = 0.0;
219  odom_theta = 0.0;
220 
221  send_time = Time::now();
222 
223  Rate loop_rate(10);
224  while(ok()){
225  if(in_cmdvel and Time::now().toSec() - last_cmdvel.toSec() >= 1.0)
226  setFreqs(0,0);
227 
228  pub_odom.publish(send_odom());
229  spinOnce();
230  loop_rate.sleep();
231  }
232 
233  exit(0);
234 }
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
nav_msgs::Odometry send_odom(void)
Definition: motors.cpp:138
bool is_on
Definition: motors.cpp:28
void publish(const boost::shared_ptr< M > &message) const
bool in_cmdvel
Definition: motors.cpp:29
double odom_y
Definition: motors.cpp:35
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
Time last_cmdvel
Definition: motors.cpp:30
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
Time cur_time
Definition: motors.cpp:31
double odom_theta
Definition: motors.cpp:35
#define ROS_INFO(...)
bool imu_flag
Definition: motors.cpp:37
ROSCPP_DECL bool ok()
geometry_msgs::Twist vel
Definition: motors.cpp:34
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void sendTransform(const geometry_msgs::TransformStamped &transform)
int main(int argc, char **argv)
Definition: motors.cpp:189
bool sleep()
bool callbackTimedMotion(raspicat::TimedMotion::Request &, raspicat::TimedMotion::Response &)
Definition: motors.cpp:89
bool setPower(bool)
Definition: motors.cpp:39
void onSigint(int)
Definition: motors.cpp:63
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
bool callbackOff(std_srvs::Trigger::Request &, std_srvs::Trigger::Response &)
Definition: motors.cpp:79
static Time now()
void setFreqs(int left, int right)
Definition: motors.cpp:50
Time send_time
Definition: motors.cpp:32
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
void callbackCmdvel(const geometry_msgs::Twist::ConstPtr &msg)
Definition: motors.cpp:114
bool callbackOn(std_srvs::Trigger::Request &, std_srvs::Trigger::Response &)
Definition: motors.cpp:69
void callbackRaw(const raspicat::MotorFreqs::ConstPtr &msg)
Definition: motors.cpp:109
void callback9Axis(const sensor_msgs::Imu::ConstPtr &msg)
Definition: motors.cpp:128
double odom_x
Definition: motors.cpp:35


raspicat
Author(s): Ryuichi Ueda , Daisuke Sato
autogenerated on Mon Jun 10 2019 14:27:50