fake_kobuki_ros.cpp
Go to the documentation of this file.
3 
4 namespace kobuki
5 {
6  FakeKobukiRos::FakeKobukiRos(std::string& node_name)
7  {
8  this->name = node_name;
9  }
10 
12  {
13  }
14 
16  {
17  kobuki.init(nh);
18 
19  // initialize publishers
20  advertiseTopics(nh);
21 
22  // initialize subscribers
23  subscribeTopics(nh);
24 
26 
28  return true;
29  }
30 
31 
33  {
34  // turtlebot required
35  this->publisher["joint_states"] = nh.advertise<sensor_msgs::JointState>("joint_states",100);
36 
37  // kobuki esoterics
38  this->publisher["version_info"] = nh.advertise<kobuki_msgs::VersionInfo>("version_info",100,true);
39 
40  // odometry
41  this->publisher["odom"] = nh.advertise<nav_msgs::Odometry>("odom",100);
42 
43 
44  /*
45  // event publishers
46  std::string evt = "events/";
47  event_publisher["button"] = nh.advertise<kobuki_msgs::SensorState> (evt + "button", 100);
48  event_publisher["bumper"] = nh.advertise<kobuki_msgs::BumperEvent> (evt + "bumper", 100);
49  event_publisher["cliff"] = nh.advertise<kobuki_msgs::CliffEvent> (evt + "cliff", 100);
50  event_publisher["wheel_drop"] = nh.advertise<kobuki_msgs::WheelDropEvent> (evt + "wheel_drop", 100);
51  event_publisher["power_system"] = nh.advertise<kobuki_msgs::PowerSystemEvent> (evt + "power_system", 100);
52  event_publisher["digital_input"] = nh.advertise<kobuki_msgs::DigitalInputEvent> (evt + "digital_input", 100);
53  event_publisher["robot_state"] = nh.advertise<kobuki_msgs::RobotStateEvent> (evt + "robot_state", 100,true); // latched
54 
55  // sensor publishers
56  std::string sen = "sensors/";
57  sensor_publisher["core"] = nh.advertise<kobuki_msgs::SensorState> (sen + "core", 100);
58  sensor_publisher["dock_ir"] = nh.advertise<kobuki_msgs::SensorState> (sen + "dock_ir", 100);
59  sensor_publisher["imu_data"] = nh.advertise<kobuki_msgs::SensorState> (sen + "imu_data", 100);
60  */
61  }
62 
64  {
65  std::string cmd = "commands/";
66  this->subscriber["velocity"] = nh.subscribe(cmd + "velocity", 10, &FakeKobukiRos::subscribeVelocityCommand, this);
67  this->subscriber["motor_power"] = nh.subscribe(cmd + "motor_power", 10, &FakeKobukiRos::subscribeMotorPowerCommand,this);
68  }
69 
71  {
72  this->publisher["version_info"].publish(this->kobuki.versioninfo);
73  }
74 
75  void FakeKobukiRos::subscribeVelocityCommand(const geometry_msgs::TwistConstPtr msg)
76  {
78  this->kobuki.wheel_speed_cmd[LEFT] = msg->linear.x - msg->angular.z * this->kobuki.wheel_separation / 2;
79  this->kobuki.wheel_speed_cmd[RIGHT] = msg->linear.x + msg->angular.z * this->kobuki.wheel_separation / 2;
80  }
81 
82  void FakeKobukiRos::subscribeMotorPowerCommand(const kobuki_msgs::MotorPowerConstPtr msg)
83  {
84  if((msg->state == kobuki_msgs::MotorPower::ON) && (!this->kobuki.motor_enabled))
85  {
86  this->kobuki.motor_enabled = true;
87  ROS_INFO_STREAM("Motors fire up. [" << this->name << "]");
88  }
89  else if((msg->state == kobuki_msgs::MotorPower::OFF) && (this->kobuki.motor_enabled))
90  {
91  this->kobuki.motor_enabled = false;
92  ROS_INFO_STREAM("Motors take a break. [" << this->name << "]");
93  }
94  }
95 
96  void FakeKobukiRos::updateJoint(unsigned int index,double& w,ros::Duration step_time)
97  {
98  double v;
99  v = this->kobuki.wheel_speed_cmd[index];
100  w = v / (this->kobuki.wheel_diameter / 2);
101  this->kobuki.joint_states.velocity[index] = w;
102  this->kobuki.joint_states.position[index]= this->kobuki.joint_states.position[index] + w * step_time.toSec();
103  }
104 
105  void FakeKobukiRos::updateOdometry(double w_left,double w_right,ros::Duration step_time)
106  {
107  double d1,d2;
108  double dr,da;
109  d1 = d2 = 0;
110  dr = da = 0;
111 
112  d1 = step_time.toSec() * (this->kobuki.wheel_diameter / 2) * w_left;
113  d2 = step_time.toSec() * (this->kobuki.wheel_diameter / 2) * w_right;
114 
115  if(isnan(d1))
116  {
117  d1 = 0;
118  }
119  if(isnan(d2))
120  {
121  d2 = 0;
122  }
123 
124  dr = (d1 + d2) / 2;
125  da = (d2 - d1) / this->kobuki.wheel_separation;
126 
127  // compute odometric pose
128  this->kobuki.odom_pose[0] += dr * cos(this->kobuki.odom_pose[2]);
129  this->kobuki.odom_pose[1] += dr * sin(this->kobuki.odom_pose[2]);
130  this->kobuki.odom_pose[2] += da;
131 
132  // compute odometric instantaneouse velocity
133  this->kobuki.odom_vel[0] = dr / step_time.toSec();
134  this->kobuki.odom_vel[1] = 0.0;
135  this->kobuki.odom_vel[2] = da / step_time.toSec();
136 
137  this->kobuki.odom.pose.pose.position.x = this->kobuki.odom_pose[0];
138  this->kobuki.odom.pose.pose.position.y = this->kobuki.odom_pose[1];
139  this->kobuki.odom.pose.pose.position.z = 0;
140  this->kobuki.odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(this->kobuki.odom_pose[2]);
141 
142  // We should update the twist of the odometry
143  this->kobuki.odom.twist.twist.linear.x = this->kobuki.odom_vel[0];
144  this->kobuki.odom.twist.twist.angular.z = this->kobuki.odom_vel[2];
145  }
146 
147  void FakeKobukiRos::updateTF(geometry_msgs::TransformStamped& odom_tf)
148  {
149  odom_tf.header = this->kobuki.odom.header;
150  odom_tf.child_frame_id = this->kobuki.odom.child_frame_id;
151  odom_tf.transform.translation.x = this->kobuki.odom.pose.pose.position.x;
152  odom_tf.transform.translation.y = this->kobuki.odom.pose.pose.position.y;
153  odom_tf.transform.translation.z = this->kobuki.odom.pose.pose.position.z;
154  odom_tf.transform.rotation = this->kobuki.odom.pose.pose.orientation;
155  }
156 
157 
159  {
160  ros::Time time_now = ros::Time::now();
161  ros::Duration step_time = time_now - this->prev_update_time;
162  this->prev_update_time = time_now;
163 
164  // zero-ing after timeout
165  if(((time_now - this->last_cmd_vel_time).toSec() > this->kobuki.cmd_vel_timeout) || !this->kobuki.motor_enabled)
166  {
167  this->kobuki.wheel_speed_cmd[LEFT] = 0.0;
168  this->kobuki.wheel_speed_cmd[RIGHT] = 0.0;
169  }
170 
171  // joint_states
172  double w_left,w_right;
173  updateJoint(LEFT,w_left,step_time);
174  updateJoint(RIGHT,w_right,step_time);
175  this->kobuki.joint_states.header.stamp = time_now;
176  this->publisher["joint_states"].publish(this->kobuki.joint_states);
177 
178  // odom
179  updateOdometry(w_left,w_right,step_time);
180  this->kobuki.odom.header.stamp = time_now;
181  this->publisher["odom"].publish(this->kobuki.odom);
182 
183  // tf
184  geometry_msgs::TransformStamped odom_tf;
185  updateTF(odom_tf);
186  this->tf_broadcaster.sendTransform(odom_tf);
187 
188  return true;
189  }
190 }
std::map< std::string, ros::Subscriber > subscriber
void advertiseTopics(ros::NodeHandle &nh)
Chain d2()
void updateTF(geometry_msgs::TransformStamped &odom_tf)
std::map< std::string, ros::Publisher > publisher
void updateJoint(unsigned int index, double &w, ros::Duration step_time)
tf::TransformBroadcaster tf_broadcaster
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
string cmd
void subscribeTopics(ros::NodeHandle &nh)
void subscribeMotorPowerCommand(const kobuki_msgs::MotorPowerConstPtr msg)
void updateOdometry(double w_left, double w_right, ros::Duration step_time)
void sendTransform(const StampedTransform &transform)
bool init(ros::NodeHandle &nh)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
FakeKobukiRos(std::string &node_name)
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
#define ROS_INFO_STREAM(args)
void subscribeVelocityCommand(const geometry_msgs::TwistConstPtr msg)
static Time now()
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)


kobuki_softnode
Author(s): Jihoon Lee
autogenerated on Mon Jun 10 2019 13:52:14