pioneer_server.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <math.h>
3 #include <nav_msgs/Odometry.h>
5 #include <geometry_msgs/Twist.h>
6 #include <geometry_msgs/TransformStamped.h>
7 #include <geometry_msgs/Vector3.h>
8 #include <geometry_msgs/Pose2D.h> //msg
9 #include <pioneer_mrs/Pose2D.h> //srv
10 #include <dynamic_reconfigure/server.h>
11 #include <pioneer_mrs/PioneerConfig.h>
12 
13 class Pioneer
14 {
15  public:
16  Pioneer(ros::NodeHandle& nh, ros::NodeHandle& nh_private);
17  virtual ~Pioneer();
18 
19  /* role one: provide pose information */
20  public:
21  void odomPoseCallBack(const nav_msgs::Odometry &);
22  void gazeboPoseCallBack(const nav_msgs::Odometry &);
23  void viconPoseCallBack(const geometry_msgs::TransformStamped &);
24  bool poseServiceCallBack(pioneer_mrs::Pose2DRequest &, pioneer_mrs::Pose2DResponse &);
25 
26  protected:
27  // pose parameters
28  int HOSTNUM; // array index
29  std::string HOSTNAME;
30  std::string POSE;
31 
32  // pose info, theta from -3.14 to 3.14, left side is positive
33  geometry_msgs::Pose2D pose_hp; // handpoint pose
34 
35  // pose subscriber
39  // pose server
41 
42  /* role two: convert vel_hp to vel (of center point) */
43  public:
44  void handpointOffsetReconfigureCallBack(pioneer_mrs::PioneerConfig &, uint32_t);
45  void handpointVelocityCallBack(const geometry_msgs::Vector3 &);
46 
47  protected:
48  // handpoint parameter
49  double HANDPOINT_OFFSET; // metric: 10in = 0.25m
50  // reconfigure server
51  dynamic_reconfigure::Server<pioneer_mrs::PioneerConfig> *cfg_server;
52 
53  // subscribe handpoint velocity
55  geometry_msgs::Vector3 vel_hp; // x, y (hand point)
56  // publish center velocity
58  geometry_msgs::Twist vel; // v, w (center)
59 };
60 
61 
63  HOSTNUM(0),
64  HOSTNAME(""),
65  POSE(""),
67 {
68  // HOSTNAME
69  nh_private.param( "hostname", HOSTNAME, std::string("robot1") );
70 
71  // HOSTNUM
72  HOSTNUM = std::stoi( HOSTNAME.substr(5) ) - 1; // array index
73 
74  // POSE mode
75  nh_private.param( "pose", POSE, std::string("odom") );
76  if(POSE != "odom")
77  ROS_INFO_STREAM( HOSTNAME + " set pose = " << POSE << " (localization by " << POSE << ")");
78  if(POSE == "vicon")
79  vicon_pose_sub = nh.subscribe("/vicon/" + HOSTNAME + "/" + HOSTNAME, 1, &Pioneer::viconPoseCallBack, this);
80  else if(POSE == "gazebo")
81  gazebo_pose_sub = nh.subscribe("gazebo/odom", 1, &Pioneer::gazeboPoseCallBack, this);
82  else
83  odom_pose_sub = nh.subscribe("RosAria/pose", 1, &Pioneer::odomPoseCallBack, this);
84 
85  // handpoint offset
86  nh_private.param( "handpoint_offset", HANDPOINT_OFFSET, 0.25);
87  if(HANDPOINT_OFFSET != 0.25)
88  ROS_INFO_STREAM( HOSTNAME + " set handpoint offset = " << HANDPOINT_OFFSET);
89 
90  // handpoint offset reconfigure server
91  cfg_server = new dynamic_reconfigure::Server<pioneer_mrs::PioneerConfig>;
92  cfg_server->setCallback(boost::bind(&Pioneer::handpointOffsetReconfigureCallBack, this, _1, _2));
93 
94  // handpoint velocity callback
95  vel_hp_sub = nh.subscribe("cmd_vel_hp", 1, &Pioneer::handpointVelocityCallBack, this);
96  vel_pub = nh.advertise<geometry_msgs::Twist>("RosAria/cmd_vel", 1);
97 
98  // pose server
100 
101  // done
102  ROS_INFO_STREAM( HOSTNAME + " pioneer_server launched." );
103 }
104 
105 
107 {
108  delete cfg_server;
109  cfg_server = NULL;
110  ROS_INFO_STREAM("[" << HOSTNAME << "]: Quitting... \n");
111 }
112 
113 
114 void Pioneer::odomPoseCallBack(const nav_msgs::Odometry& msg)
115 {
116  // transform quaternion to Euler angle
117  tf::Quaternion q(msg.pose.pose.orientation.x, msg.pose.pose.orientation.y, msg.pose.pose.orientation.z, msg.pose.pose.orientation.w);
118  tf::Matrix3x3 m(q);
119  double roll, pitch, yaw;
120  m.getRPY(roll, pitch, yaw);
121  this->pose_hp.theta = yaw; //yaw from -3.14 to 3.14, left side is the positive number
122 
123  // convert center pose to handpoint pose
124  geometry_msgs::Pose2D pose; // center pose
125  pose.x = msg.pose.pose.position.x;
126  pose.y = msg.pose.pose.position.y;
127  pose.y = pose.y - (HOSTNUM - 2); // initialization offset: put robot 1-5 on a row, with 1 meter space
128  this->pose_hp.x = pose.x + HANDPOINT_OFFSET * cos(pose.theta);
129  this->pose_hp.y = pose.y + HANDPOINT_OFFSET * sin(pose.theta);
130  ROS_DEBUG_STREAM(HOSTNAME + " odom: theta="<<pose_hp.theta<<"; x_hp="<<pose_hp.x<<"; y_hp="<<pose_hp.y<<";\n");
131 }
132 
133 
134 void Pioneer::gazeboPoseCallBack(const nav_msgs::Odometry& msg)
135 {
136  // transform quaternion to Euler angle
137  tf::Quaternion q(msg.pose.pose.orientation.x, msg.pose.pose.orientation.y, msg.pose.pose.orientation.z, msg.pose.pose.orientation.w);
138  tf::Matrix3x3 m(q);
139  double roll, pitch, yaw;
140  m.getRPY(roll, pitch, yaw);
141  this->pose_hp.theta = yaw; //yaw from -3.14 to 3.14, left side is the positive number
142 
143  // convert center pose to handpoint pose
144  geometry_msgs::Pose2D pose; // center pose
145  pose.x = msg.pose.pose.position.x;
146  pose.y = msg.pose.pose.position.y;
147  this->pose_hp.x = pose.x + HANDPOINT_OFFSET * cos(pose.theta);
148  this->pose_hp.y = pose.y + HANDPOINT_OFFSET * sin(pose.theta);
149  ROS_DEBUG_STREAM(HOSTNAME + " gazebo: theta="<<pose_hp.theta<<"; x_hp="<<pose_hp.x<<"; y_hp="<<pose_hp.y<<";\n");
150 }
151 
152 
153 void Pioneer::viconPoseCallBack(const geometry_msgs::TransformStamped& msg)
154 {
155  // transform quaternion to Euler angle
156  tf::Quaternion q(msg.transform.rotation.x, msg.transform.rotation.y, msg.transform.rotation.z, msg.transform.rotation.w);
157  tf::Matrix3x3 m(q);
158  double roll, pitch, yaw;
159  m.getRPY(roll, pitch, yaw);
160 
161  this->pose_hp.theta = yaw;
162  this->pose_hp.x = msg.transform.translation.x;
163  this->pose_hp.y = msg.transform.translation.y;
164  ROS_DEBUG_STREAM(HOSTNAME + " vicon: theta="<<pose_hp.theta<<"; x_hp="<<pose_hp.x<<"; y_hp="<<pose_hp.y<<";\n");
165 }
166 
167 
168 bool Pioneer::poseServiceCallBack(pioneer_mrs::Pose2DRequest &rqt, pioneer_mrs::Pose2DResponse &res)
169 {
170  res.theta = this->pose_hp.theta;
171  res.x = this->pose_hp.x;
172  res.y = this->pose_hp.y;
173  res.success = true;
174  return true;
175 }
176 
177 
178 void Pioneer::handpointOffsetReconfigureCallBack(pioneer_mrs::PioneerConfig &config, uint32_t level)
179 {
180  double value;
181  value = config.handpoint_offset;
182  if(value != this->HANDPOINT_OFFSET && value > 0)
183  {
184  ROS_INFO_STREAM(HOSTNAME + " Set HANDPOINT_OFFSET = "<<value<<" m");
185  this->HANDPOINT_OFFSET = value;
186  }
187 }
188 
189 
190 void Pioneer::handpointVelocityCallBack(const geometry_msgs::Vector3& msg)
191 {
192  this->vel_hp = msg;
193  double x, y, v, w, theta;
194  x = vel_hp.x; // linear velocity x, y in ground frame
195  y = vel_hp.y;
196  theta = this->pose_hp.theta;
197 
203  v = x*cos(theta) + y*sin(theta);
204  w = ( x*(-sin(theta)) + y*cos(theta) )/HANDPOINT_OFFSET;
205  ROS_DEBUG_STREAM(HOSTNAME + " vel: theta="<<theta<<"; x="<<x<<"; y="<<y<<"; v="<<v<<"; w="<<w<<";\n");
206 
207  // pub vel
208  vel.linear.x = v;
209  vel.linear.y = 0;
210  vel.linear.z = 0;
211  vel.angular.x = 0;
212  vel.angular.y = 0;
213  vel.angular.z = w;
214  vel_pub.publish(this->vel);
215 }
216 
217 
218 int main(int argc, char **argv)
219 {
220  ros::init(argc, argv, "pioneer_server");
221  ros::NodeHandle nh;
222  ros::NodeHandle nh_private("~");
223 
224  Pioneer* pioneer = new Pioneer(nh, nh_private);
225  ros::spin();
226 
227  delete pioneer;
228  pioneer = NULL;
229 
230  return 0;
231 }
void handpointVelocityCallBack(const geometry_msgs::Vector3 &)
virtual ~Pioneer()
int main(int argc, char **argv)
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Subscriber vicon_pose_sub
std::string POSE
void odomPoseCallBack(const nav_msgs::Odometry &)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
geometry_msgs::Pose2D pose_hp
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
ros::ServiceServer pose_server
TFSIMD_FORCE_INLINE const tfScalar & y() const
ros::Publisher vel_pub
double HANDPOINT_OFFSET
geometry_msgs::Vector3 vel_hp
ROSCPP_DECL void spin(Spinner &spinner)
ros::Subscriber odom_pose_sub
geometry_msgs::Twist vel
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void viconPoseCallBack(const geometry_msgs::TransformStamped &)
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_DEBUG_STREAM(args)
void handpointOffsetReconfigureCallBack(pioneer_mrs::PioneerConfig &, uint32_t)
TFSIMD_FORCE_INLINE const tfScalar & w() const
ros::Subscriber vel_hp_sub
#define ROS_INFO_STREAM(args)
bool poseServiceCallBack(pioneer_mrs::Pose2DRequest &, pioneer_mrs::Pose2DResponse &)
std::string HOSTNAME
Pioneer(ros::NodeHandle &nh, ros::NodeHandle &nh_private)
dynamic_reconfigure::Server< pioneer_mrs::PioneerConfig > * cfg_server
void gazeboPoseCallBack(const nav_msgs::Odometry &)
ros::Subscriber gazebo_pose_sub


pioneer_mrs
Author(s): Hanzhe Teng
autogenerated on Thu Mar 5 2020 03:17:35