kobuki_bumper2pc.cpp
Go to the documentation of this file.
1 
10 /*****************************************************************************
11 ** Includes
12 *****************************************************************************/
13 
15 
17 
18 namespace kobuki_bumper2pc
19 {
20 
21 void Bumper2PcNodelet::coreSensorCB(const kobuki_msgs::SensorState::ConstPtr& msg)
22 {
24  return;
25 
26  // We publish just one "no events" pc (with all three points far away) and stop spamming when bumper/cliff conditions disappear
27  if (! msg->bumper && ! msg->cliff && ! prev_bumper && ! prev_cliff)
28  return;
29 
30  prev_bumper = msg->bumper;
31  prev_cliff = msg->cliff;
32 
33  // We replicate the sensors order of bumper/cliff event messages: LEFT = 0, CENTER = 1 and RIGHT = 2
34  // For any of {left/center/right} with no bumper/cliff event, we publish a faraway point that won't get used
35  if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_LEFT) ||
36  (msg->cliff & kobuki_msgs::SensorState::CLIFF_LEFT))
37  {
38  memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
39  memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &p_side_y_, sizeof(float));
40  }
41  else
42  {
43  memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
44  memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &P_INF_Y, sizeof(float));
45  }
46 
47  if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_CENTRE) ||
48  (msg->cliff & kobuki_msgs::SensorState::CLIFF_CENTRE))
49  {
50  memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &pc_radius_, sizeof(float));
51  }
52  else
53  {
54  memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
55  }
56 
57  if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_RIGHT) ||
58  (msg->cliff & kobuki_msgs::SensorState::CLIFF_RIGHT))
59  {
60  memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
61  memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &n_side_y_, sizeof(float));
62  }
63  else
64  {
65  memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
66  memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &N_INF_Y, sizeof(float));
67  }
68 
69  pointcloud_.header.stamp = msg->header.stamp;
71 }
72 
74 {
76 
77  // Bumper/cliff pointcloud distance to base frame; should be something like the robot radius plus
78  // costmap resolution plus an extra to cope with robot inertia. This is a bit tricky parameter: if
79  // it's too low, costmap will ignore this pointcloud (the robot footprint runs over the hit obstacle),
80  // but if it's too big, hit obstacles will be mapped too far from the robot and the navigation around
81  // them will probably fail.
82  std::string base_link_frame;
83  double r, h, angle;
84  nh.param("pointcloud_radius", r, 0.25); pc_radius_ = r;
85  nh.param("pointcloud_height", h, 0.04); pc_height_ = h;
86  nh.param("side_point_angle", angle, 0.34906585);
87  nh.param<std::string>("base_link_frame", base_link_frame, "/base_link");
88 
89  // Lateral points x/y coordinates; we need to store float values to memcopy later
90  p_side_x_ = + pc_radius_*sin(angle); // angle degrees from vertical
91  p_side_y_ = + pc_radius_*cos(angle); // angle degrees from vertical
92  n_side_y_ = - pc_radius_*cos(angle); // angle degrees from vertical
93 
94  // Prepare constant parts of the pointcloud message to be published
95  pointcloud_.header.frame_id = base_link_frame;
96  pointcloud_.width = 3;
97  pointcloud_.height = 1;
98  pointcloud_.fields.resize(3);
99 
100  // Set x/y/z as the only fields
101  pointcloud_.fields[0].name = "x";
102  pointcloud_.fields[1].name = "y";
103  pointcloud_.fields[2].name = "z";
104 
105  int offset = 0;
106  // All offsets are *4, as all field data types are float32
107  for (size_t d = 0; d < pointcloud_.fields.size(); ++d, offset += 4)
108  {
109  pointcloud_.fields[d].count = 1;
110  pointcloud_.fields[d].offset = offset;
111  pointcloud_.fields[d].datatype = sensor_msgs::PointField::FLOAT32;
112  }
113 
114  pointcloud_.point_step = offset;
115  pointcloud_.row_step = pointcloud_.point_step * pointcloud_.width;
116 
117  pointcloud_.data.resize(3 * pointcloud_.point_step);
118  pointcloud_.is_bigendian = false;
119  pointcloud_.is_dense = true;
120 
121  // Bumper/cliff "points" fix coordinates (the others depend on sensor activation/deactivation)
122 
123  // y: always 0 for central bumper
124  memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[1].offset], &ZERO, sizeof(float));
125 
126  // z: constant elevation from base frame
127  memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
128  memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
129  memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
130 
131  pointcloud_pub_ = nh.advertise <sensor_msgs::PointCloud2> ("pointcloud", 10);
132  core_sensor_sub_ = nh.subscribe("core_sensors", 10, &Bumper2PcNodelet::coreSensorCB, this);
133 
134  ROS_INFO("Bumper/cliff pointcloud configured at distance %f and height %f from base frame", pc_radius_, pc_height_);
135 }
136 
137 } // namespace kobuki_bumper2pc
138 
139 
d
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::NodeHandle & getPrivateNodeHandle() const
sensor_msgs::PointCloud2 pointcloud_
PLUGINLIB_EXPORT_CLASS(kobuki_bumper2pc::Bumper2PcNodelet, nodelet::Nodelet)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
Bumper2PcNodelet class declaration.
void coreSensorCB(const kobuki_msgs::SensorState::ConstPtr &msg)
Core sensors state structure callback.
uint32_t getNumSubscribers() const
Bumper/cliff to pointcloud nodelet class declaration.


kobuki_bumper2pc
Author(s): Jorge Santos Simon
autogenerated on Mon Jun 10 2019 13:44:59