-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Lidar-based obstacle detection #30
Conversation
@@ -217,6 +289,25 @@ void ObstacleDetector::get_points() | |||
obstacle_mutex.unlock(); | |||
} | |||
|
|||
// Get points from lidar - convert from polar to cartesian coords | |||
void ObstacleDetector::get_lidar_points(std::vector<tf2::Vector3>& points) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't 'get', since it doesn't return. Call it 'add_lidar_points'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it may be worth keeping it get
so it is consistent in naming with the range senors
|
||
// Handle Range messages and computes distance to obstacles | ||
class ObstacleDetector | ||
{ | ||
std::map<std::string, RangeSensor> sensors; | ||
ros::Subscriber sonar_sub; | ||
ros::Subscriber scan_sub;; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double semicolon
public: | ||
float radius; | ||
float theta; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also take the origin of the line, and maybe the normal vector.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment around L300 for why.
float y = lidar_origin.y() + p.radius * (lidar_normal.y() * cos_theta + | ||
lidar_normal.x() * sin_theta); | ||
|
||
points.push_back(tf2::Vector3(x, y, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all of the code to compute this vector should be within PolarLine, in a function that returns a Vector3. (Which would mean that PolarLine would need the lidar origin and normal).
At least going from polar to Cartesian should be, and those points could be transformed to the robot coordinate system here (still a function that returns a vector3).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The points are transformed to a 2D projection of base_link here, that's what lidar_origin and lidar_normal do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if it makes much sense to have a class that has a point in r, theta
form and has its origin in point normal form. I think it's cleaner if the coordinate system transform is done outside the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense.
src/obstacle_detector.cpp
Outdated
if (!have_lidar) { | ||
try { | ||
geometry_msgs::TransformStamped tfs = | ||
tf_buffer->lookupTransform("base_link", "laser", ros::Time(0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more sensical name for the variable like laser_tf
or base2laser_tf
would make the following code clearer
src/obstacle_detector.cpp
Outdated
normal.vector.z = 0.0; | ||
geometry_msgs::Vector3Stamped base_normal; | ||
tf2::doTransform(normal, base_normal, tfs); | ||
fromMsg(base_normal.vector, lidar_normal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of a question:
Why do we need the normal?
I see it is being used in the Polar to xy computation, but I don't understand why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It allows us to have the lidar in any orientation, instead of assuming that it is pointing forward, as the previous code did.
src/obstacle_detector.cpp
Outdated
@@ -413,3 +555,10 @@ void RangeSensor::update(float range, ros::Time stamp) | |||
left_vertex = origin + left_vec * range; | |||
right_vertex = origin + right_vec * range; | |||
} | |||
|
|||
PolarLine::PolarLine(float radius, float theta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just put this inline the class.
@@ -378,6 +482,44 @@ float ObstacleDetector::obstacle_angle(bool left) | |||
} | |||
} | |||
} | |||
|
|||
// Draw rotated footprint to show limit of rotation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it really make sense to draw the whole footprint?
I think we should be only drawing the side of the box in the direction of the turn. So if turning left, only show the left side of the box.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When turning, an obstacle collision could be with any of the four sides of the robot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/obstacle_detector.cpp
Outdated
check_dist(p.x(), forward, min_dist); | ||
} | ||
} | ||
|
||
if (forward) { | ||
draw_line(tf2::Vector3(min_dist, -robot_width, 0), | ||
tf2::Vector3(min_dist, robot_width, 0), 1, 0, 0, 1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't forward and backward have the same line id so that they replace each other. Otherwise we would have old data on screen until the robot moves in that direction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good point.
Just curious, how well does this work for detecting/stopping for chair legs? |
src/obstacle_detector.cpp
Outdated
@@ -158,14 +165,70 @@ void ObstacleDetector::sensor_callback(const sensor_msgs::Range::ConstPtr &msg) | |||
else { | |||
RangeSensor& sensor = sensors[frame]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another minor comment, not necessarily part of this PR:
We are effectively running find twice because we are not using the value of the iterator it here.
I think this line could become RangeSensor& sensor = *it;
which means we are only doing the map lookup once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@rohbotics thanks for the review. I think it's ready to merge now, do you agree? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good now
Moves handling of LaserScan messages into ObstacleDetector class #28