simulation_odom.cpp
Go to the documentation of this file.
1 
7 #include <ros/ros.h>
8 #include <geometry_msgs/Twist.h>
9 #include <std_msgs/Int16.h>
10 #include <sensor_msgs/Imu.h>
12 #include <vector>
13 #include <nav_msgs/Odometry.h>
14 #include <tf/transform_broadcaster.h>
15 
21 namespace simulation
22 {
27 typedef geometry_msgs::Twist twist_msg;
32 typedef std_msgs::Int16 int16_msg;
37 typedef sensor_msgs::Imu imu_msg;
42 typedef nav_msgs::Odometry odom_msg;
43 
44 static const double DEFAULT_CAR_WHEELBASE = 0.25;
45 static const double DEFAULT_CAR_X_COORDINATE = 0;
46 static const double DEFAULT_CAR_Y_COORDINATE = 0;
47 static const double DEFAULT_CAR_YAW = 0;
48 static const double DEFAULT_LOOP_RATE =
49  100.0;
50 static const std::string DEFAULT_ODOM_FRAME_ID =
51  "odom";
52 static const std::string DEFAULT_ODOM_CHILD_FRAME_ID =
53  "base_footprint";
54 static const std::string DEFAULT_MOTION_COMMAND_TOPIC =
55  "cmd_vel";
56 static const std::string DEFAULT_STEERING_COMMAND_TOPIC =
57  "/uc_bridge/set_steering_level_msg";
59 static const std::string DEFAULT_MOTOR_COMMAND_TOPIC =
60  "/uc_bridge/set_motor_level_msg";
62 static const std::string DEFAULT_ODOM_TOPIC =
63  "odom";
64 static const std::string DEFAULT_IMU_TOPIC =
65  "/uc_bridge/imu";
72 void fetchWheelBase(ros::NodeHandle* nh, double& wheelBase)
73 {
74  if (nh->hasParam("odom_sim/wheel_base"))
75  {
76  nh->getParam("odom_sim/wheel_base", wheelBase);
77  }
78  else
79  {
80  wheelBase = DEFAULT_CAR_WHEELBASE;
81  }
82 }
83 
89 void fetchInitialX(ros::NodeHandle* nh, double& initialX)
90 {
91  if (nh->hasParam("odom_sim/initial_x_coordinate"))
92  {
93  nh->getParam("odom_sim/initial_x_coordinate", initialX);
94  }
95  else
96  {
97  initialX = DEFAULT_CAR_X_COORDINATE;
98  }
99 }
100 
106 void fetchInitialY(ros::NodeHandle* nh, double& initialY)
107 {
108  if (nh->hasParam("odom_sim/initial_y_coordinate"))
109  {
110  nh->getParam("odom_sim/initial_y_coordinate", initialY);
111  }
112  else
113  {
114  initialY = DEFAULT_CAR_Y_COORDINATE;
115  }
116 }
117 
123 void fetchInitialYaw(ros::NodeHandle* nh, double& initialYaw)
124 {
125  if (nh->hasParam("odom_sim/initial_yaw"))
126  {
127  nh->getParam("odom_sim/initial_yaw", initialYaw);
128  }
129  else
130  {
131  initialYaw = DEFAULT_CAR_YAW;
132  }
133 }
134 
140 void fetchLoopRate(ros::NodeHandle* nh, double& loopRate)
141 {
142  if (nh->hasParam("odom_sim/loop_rate_control"))
143  {
144  nh->getParam("odom_sim/loop_rate_control", loopRate);
145  }
146  else
147  {
148  loopRate = DEFAULT_LOOP_RATE;
149  }
150 }
156 void fetchOdomFrameID(ros::NodeHandle* nh, std::string& odomFrameID)
157 {
158  if (nh->hasParam("odom_sim/odom_frame_id"))
159  {
160  nh->getParam("odom_sim/odom_frame_id", odomFrameID);
161  }
162  else
163  {
164  odomFrameID = DEFAULT_ODOM_FRAME_ID;
165  }
166 }
173 void fetchOdomChildFrameID(ros::NodeHandle* nh, std::string& odomChildFrameID)
174 {
175  if (nh->hasParam("odom_sim/odom_child_frame_id"))
176  {
177  nh->getParam("odom_sim/odom_child_frame_id", odomChildFrameID);
178  }
179  else
180  {
181  odomChildFrameID = DEFAULT_ODOM_CHILD_FRAME_ID;
182  }
183 }
190 void fetchMotionCommandTopic(ros::NodeHandle* nh,
191  std::string& motionCommandTopic)
192 {
193  if (nh->hasParam("odom_sim/motion_command_topic"))
194  {
195  nh->getParam("odom_sim/motion_command_topic", motionCommandTopic);
196  }
197  else
198  {
199  motionCommandTopic = DEFAULT_MOTION_COMMAND_TOPIC;
200  }
201 }
208 void fetchSteeringCommandTopic(ros::NodeHandle* nh,
209  std::string& steeringCommandTopic)
210 {
211  if (nh->hasParam("odom_sim/steering_command_topic"))
212  {
213  nh->getParam("odom_sim/steering_command_topic", steeringCommandTopic);
214  }
215  else
216  {
217  steeringCommandTopic = DEFAULT_STEERING_COMMAND_TOPIC;
218  }
219 }
226 void fetchMotorCommandTopic(ros::NodeHandle* nh, std::string& motorCommandTopic)
227 {
228  if (nh->hasParam("odom_sim/motor_command_topic"))
229  {
230  nh->getParam("odom_sim/motor_command_topic", motorCommandTopic);
231  }
232  else
233  {
234  motorCommandTopic = DEFAULT_MOTOR_COMMAND_TOPIC;
235  }
236 }
242 void fetchOdomTopic(ros::NodeHandle* nh, std::string& odomTopic)
243 {
244  if (nh->hasParam("odom_sim/odom_topic"))
245  {
246  nh->getParam("odom_sim/odom_topic", odomTopic);
247  }
248  else
249  {
250  odomTopic = DEFAULT_ODOM_TOPIC;
251  }
252 }
258 void fetchImuTopic(ros::NodeHandle* nh, std::string& imuTopic)
259 {
260  if (nh->hasParam("odom_sim/imu_topic"))
261  {
262  nh->getParam("odom_sim/imu_topic", imuTopic);
263  }
264  else
265  {
266  imuTopic = DEFAULT_IMU_TOPIC;
267  }
268 }
276 void motionCommand(const twist_msg::ConstPtr& cmdIn, twist_msg* cmdOut,
277  bool* isTwistCmd)
278 {
279  *cmdOut = *cmdIn;
280  *isTwistCmd = true;
281 }
289 void steeringCommand(const int16_msg::ConstPtr& cmdIn, int* cmdOut,
290  bool* isTwistCmd)
291 {
292  *cmdOut = cmdIn->data;
293  *isTwistCmd = false;
294 }
302 void motorCommand(const int16_msg::ConstPtr& cmdIn, int* cmdOut,
303  bool* isTwistCmd)
304 {
305  *cmdOut = cmdIn->data;
306  *isTwistCmd = false;
307 }
308 }
309 
310 using namespace simulation;
314 int main(int argc, char** argv)
315 {
316 
317  ros::init(argc, argv, "simulation_control");
318  ros::NodeHandle nh;
319  // create parameter variables
320  double loopRate, wheelBase, initialX, initialY, initialYaw;
321  std::string motionCmdTopic, steeringCmdTopic, motorCmdTopic, odomTopic,
322  odomFrameID, odomChildFrameID, imuTopic;
323  // fetch parameters from ros param server
324  fetchLoopRate(&nh, loopRate);
325  fetchWheelBase(&nh, wheelBase);
326  fetchMotionCommandTopic(&nh, motionCmdTopic);
327  fetchSteeringCommandTopic(&nh, steeringCmdTopic);
328  fetchMotorCommandTopic(&nh, motorCmdTopic);
329  fetchOdomTopic(&nh, odomTopic);
330  fetchOdomFrameID(&nh, odomFrameID);
331  fetchOdomChildFrameID(&nh, odomChildFrameID);
332  fetchImuTopic(&nh, imuTopic);
333  fetchInitialX(&nh, initialX);
334  fetchInitialY(&nh, initialY);
335  fetchInitialYaw(&nh, initialYaw);
336  // Construct initial pose of the robot
337  std::vector<double> initialPose;
338  initialPose.push_back(-initialY);
339  initialPose.push_back(initialX);
340  initialPose.push_back(initialYaw);
341  // get current time and configure our car model simulation
342  ros::Time currentTime = ros::Time::now();
343  CarModel car(wheelBase, currentTime, initialPose);
344 
345  std::vector<double> simPose;
346  twist_msg motionCmd;
347  int steeringCmd = 0, motorCmd = 0;
348  bool isTwistCmd = true;
349  tf::TransformBroadcaster odom_broadcaster;
350  geometry_msgs::TransformStamped odom_trans;
351  odom_msg odom;
352  imu_msg imu;
353 
354  ros::Subscriber motionControl = nh.subscribe<twist_msg>(
355  motionCmdTopic, 10,
356  boost::bind(motionCommand, _1, &motionCmd, &isTwistCmd));
357  ros::Subscriber steeringControl = nh.subscribe<int16_msg>(
358  steeringCmdTopic, 1,
359  boost::bind(steeringCommand, _1, &steeringCmd, &isTwistCmd));
360  ros::Subscriber motorControl = nh.subscribe<int16_msg>(
361  motorCmdTopic, 1, boost::bind(motorCommand, _1, &motorCmd, &isTwistCmd));
362  ros::Publisher odomPub = nh.advertise<odom_msg>(odomTopic, 10);
363  ros::Publisher imuPub = nh.advertise<imu_msg>(imuTopic, 10);
364 
365  // Loop starts here:
366  ros::Rate loop_rate(loopRate);
367  while (ros::ok())
368  {
369  currentTime = ros::Time::now();
370  if (isTwistCmd == false)
371  {
372  simPose = *car.getUpdate(-steeringCmd / 20, motorCmd / 50, currentTime);
373  }
374  else
375  {
376  simPose = *car.getUpdateTwist(motionCmd, currentTime);
377  }
378 
379  geometry_msgs::Quaternion odom_quat =
380  tf::createQuaternionMsgFromYaw(simPose[2]);
381 
382  // first, we'll publish the transform over tf
383 
384  odom_trans.header.stamp = currentTime;
385  odom_trans.header.frame_id = odomFrameID;
386  odom_trans.child_frame_id = odomChildFrameID;
387 
388  odom_trans.transform.translation.x = simPose[1];
389  odom_trans.transform.translation.y = -simPose[0];
390  odom_trans.transform.translation.z = 0.0;
391  odom_trans.transform.rotation = odom_quat;
392  // send the transform
393  odom_broadcaster.sendTransform(odom_trans);
394 
395  // next, we'll publish the odometry message over ROS
396  odom.header.stamp = currentTime;
397  odom.header.frame_id = odomFrameID;
398  // set the position
399  odom.pose.pose.position.x = simPose[1];
400  odom.pose.pose.position.y = -simPose[0];
401  odom.pose.pose.position.z = 0.0;
402  odom.pose.pose.orientation = odom_quat;
403  // set the velocity
404  odom.child_frame_id = odomChildFrameID;
405  odom.twist.twist.linear.x = car.getVx();
406  odom.twist.twist.linear.y = car.getVy();
407  odom.twist.twist.angular.z = car.getAngularVelocity();
408 
409  // create imu sensor message
410  imu.header.stamp = currentTime;
411  imu.header.frame_id = "robot_simulation";
412  imu.angular_velocity.z = car.getAngularVelocity();
413  imu.linear_acceleration.x = car.getAx();
414  imu.linear_acceleration.y = car.getAy();
415 
416  // publish the messages
417  odomPub.publish(odom);
418  imuPub.publish(imu);
419 
420  ros::spinOnce();
421  loop_rate.sleep();
422  }
423 
424  ros::spin();
425 }
void fetchLoopRate(ros::NodeHandle *nh, double &loopRate)
Get loop rate launch parameter.
static const double DEFAULT_CAR_Y_COORDINATE
const pose_ptr getUpdate(const int newSteering, const int newSpeed, const ros::Time &time)
Update the simulation with current control settings and time.
Definition: CarModel.cpp:28
void motionCommand(const twist_msg::ConstPtr &cmdIn, twist_msg *cmdOut, bool *isTwistCmd)
Motion command topic callback.
static const std::string DEFAULT_ODOM_CHILD_FRAME_ID
nav_msgs::Odometry odom_msg
shortcut for a pointer to a Odometry message
void fetchSteeringCommandTopic(ros::NodeHandle *nh, std::string &steeringCommandTopic)
Get steering command topic launch parameter.
const double getVy() const
Get current velocity in y direction of the mobile plattform relative to the global coordinate system...
Definition: CarModel.cpp:76
static const std::string DEFAULT_MOTOR_COMMAND_TOPIC
static const double DEFAULT_CAR_WHEELBASE
const double getAy() const
Get current acceleration in y direction of the mobile plattform relative to the robot coordinate syst...
Definition: CarModel.cpp:78
static const std::string DEFAULT_MOTION_COMMAND_TOPIC
The CarModel class simulates kinematic behavoir of a car like mobile platform, by using the ForwardKi...
Definition: CarModel.h:39
static const std::string DEFAULT_STEERING_COMMAND_TOPIC
void fetchMotionCommandTopic(ros::NodeHandle *nh, std::string &motionCommandTopic)
Get motion command topic launch parameter.
void fetchMotorCommandTopic(ros::NodeHandle *nh, std::string &motorCommandTopic)
Get motor command topic launch parameter.
static const std::string DEFAULT_ODOM_FRAME_ID
void fetchInitialX(ros::NodeHandle *nh, double &initialX)
Get the initial x-coordinate of the robot.
Header file for the CarModel class.
void fetchWheelBase(ros::NodeHandle *nh, double &wheelBase)
Get wheel base launch parameter.
void fetchImuTopic(ros::NodeHandle *nh, std::string &imuTopic)
Get imu topic launch parameter.
void fetchInitialY(ros::NodeHandle *nh, double &initialY)
Get the initial y-coordinate of the robot.
void fetchOdomTopic(ros::NodeHandle *nh, std::string &odomTopic)
Get odometry topic launch parameter.
sensor_msgs::Imu imu_msg
shortcut for a pointer to a IMU message
static const std::string DEFAULT_IMU_TOPIC
const double getAngularVelocity() const
Get current angular velocity of the mobile plattform.
Definition: CarModel.cpp:73
void fetchOdomChildFrameID(ros::NodeHandle *nh, std::string &odomChildFrameID)
Get odom child frame id launch parameter.
const double getAx() const
Get current acceleration in x direction of the mobile plattform relative to the robot coordinate syst...
Definition: CarModel.cpp:77
void fetchInitialYaw(ros::NodeHandle *nh, double &initialYaw)
Get the initial yaw of the robot. (in radians).
void fetchOdomFrameID(ros::NodeHandle *nh, std::string &odomFrameID)
Get odom frame id launch parameter.
int main(int argc, char **argv)
Main function of this ros node.
static const std::string DEFAULT_ODOM_TOPIC
geometry_msgs::Twist twist_msg
shortcut for a pointer to a twist message
std_msgs::Int16 int16_msg
shortcut for a pointer to a int16 message
static const double DEFAULT_LOOP_RATE
static const double DEFAULT_CAR_X_COORDINATE
const double getVx() const
Get current velocity in x direction of the mobile plattform relative to the global coordinate system...
Definition: CarModel.cpp:75
void motorCommand(const int16_msg::ConstPtr &cmdIn, int *cmdOut, bool *isTwistCmd)
Motor command topic callback.
This namespace groups all typedefs, utility functions and parameter getter used in the simulation_odo...
void steeringCommand(const int16_msg::ConstPtr &cmdIn, int *cmdOut, bool *isTwistCmd)
Steering command topic callback.
const pose_ptr getUpdateTwist(const twist_msg cmd_vel, const ros::Time &time)
Update the simulation with current motion parameters and time.
Definition: CarModel.cpp:46
static const double DEFAULT_CAR_YAW
geometry_msgs::Twist twist_msg
shortcut for the twist message
Definition: CarModel.h:20


pses_simulation
Author(s): Sebastian Ehmes
autogenerated on Wed Dec 13 2017 19:37:54