double PathFollowingGeometry::getCurveRadius() { if (!this->has_curve_radius) { PointArr points = this->getCurvatureDetectionPoints(); if (!points.empty()) { Point center = this->getFeedforwardCurveCenterPoint(); //Equation 13 double radius = 0; for (PointArrIt it = points.begin(); it < points.end(); it++) { radius += distance(*it, center); } radius /= points.size(); this->curve_radius = radius; //std::stringstream sstr; //sstr << center; //ROS_INFO("Getting curve radius %f, pts.size %d. %.2f, %.2f", radius, (unsigned int)points.size(), center.x, center.y); this->has_curve_radius = true; } else { //ROS_WARN("Failed to calculate radius. Detection points are empty"); } } return this->curve_radius; }
void PathFollowingGeometry::updateLocalFrame() { //Transform points to robot-centered coordinate frame //Depending on where (left or right) feedback path point is //make reference distance positive or negative //Transformation this->feedback_path_point_in_local_frame = this->localFramePoint(this->getFeedbackPathPoint()); this->feedback_point_in_local_frame = this->localFramePoint(this->getFeedbackPoint()); this->feedforward_point_in_local_frame = this->localFramePoint(this->getFeedforwardPoint()); this->deviation_path_point_in_local_frame = this->localFramePoint(this->getDeviationPathPoint()); PointArr points = this->getCurvatureDetectionPoints(); this->curvature_detection_points_in_local_frame.clear(); for (PointArrIt it = points.begin(); it < points.end(); it++) { this->curvature_detection_points_in_local_frame.push_back(this->localFramePoint(*it)); } this->has_local_frame = true; }
Point PathFollowingGeometry::getClosestPointFromSet(Point referencePoint, PointArr pointSet) { Point result; if (pointSet.size() > 0) { result = pointSet.at(0); double closest_distance = distance(referencePoint, result); for (PointArrIt it = pointSet.begin()+1; it < pointSet.end(); it++) { double new_distance = distance(referencePoint, *it); //ROS_INFO("%.2f,%.2f -> %.2f,%.2f = %.4f", referencePoint.x, referencePoint.y, (*it).x, (*it).y, new_distance); if (new_distance < closest_distance) { closest_distance = new_distance; result = *it; } } // ROS_WARN("Shortest %.2f,%.2f -> %.2f,%.2f = %.4f", referencePoint.x, referencePoint.y, result.x, result.y, closest_distance); } else { result = referencePoint; } return result; }
void MotionControlNode::callbackGoal(const lunabotics::Goal::ConstPtr &msg) { this->_waypoints.clear(); this->_motionConstraints.point_turn_angle_accuracy = msg->angleAccuracy; this->_motionConstraints.point_turn_distance_accuracy = msg->distanceAccuracy; //Specify params Point goal = Point_from_geometry_msgs_Point(msg->point); //ROS_INFO("Requesting path between (%.1f,%.1f) and (%.1f,%.1f)", // this->_currentPose.position.x, this->_currentPose.position.y, // goal.x, goal.y); float resolution; PathPtr path = this->findPath(this->_currentPose, goal, resolution); if (path->is_initialized()) { std::stringstream sstr; nav_msgs::Path pathMsg; pathMsg.header.stamp = ros::Time::now(); pathMsg.header.seq = this->_sequence++; pathMsg.header.frame_id = "map"; PointArr corner_points = path->cornerPoints(resolution); PointArr pts; if (this->_steeringMode == lunabotics::proto::ACKERMANN) { unsigned int size = corner_points.size(); if (size > 2) { delete this->_trajectory; this->_trajectory = new Trajectory(); Point startPoint = corner_points.at(0); Point endPoint = corner_points.at(size-1); IndexedPointArr closest_obstacles = path->closestObstaclePoints(resolution); unsigned int obst_size = closest_obstacles.size(); pts.push_back(startPoint); //Get bezier quadratic curves for each point-turn for (unsigned int i = 1; i < size-1; i++) { Point q0, q2; Point prev = corner_points.at(i-1); Point curr = corner_points.at(i); Point next = corner_points.at(i+1); bool hasObstacle = false; Point obstaclePoint; //Since obstacle is the center of occupied cell, we want p to be at its edge if (obst_size > 0) { int start = std::min(obst_size-1, i-1); for (int j = start; j >= 0; j--) { IndexedPoint indexedObstacle = closest_obstacles.at(j); if (indexedObstacle.index == (int)i) { hasObstacle = true; obstaclePoint = indexedObstacle.point; break; } } } if (i == 1) { q0 = prev; } else { q0 = midPoint(prev, curr); } if (i == size-2) { q2 = next; } else { q2 = midPoint(next, curr); } TrajectorySegment s; if (hasObstacle) { Point p = midPoint(obstaclePoint, curr); s.curve = CreateConstrainedBezierCurve(q0, curr, q2, p, this->_motionConstraints.bezier_segments_num); //ROS_INFO("Curve from tetragonal q0=(%f,%f) q1=(%f,%f), q2=(%f,%f), p=(%f,%f)", q0.x, q0.y, curr.x, curr.y, q2.x, q2.y, p.x, p.y); } else { s.curve = new BezierCurve(q0, curr, q2, this->_motionConstraints.bezier_segments_num); //ROS_INFO("Curve without tetragonal q0=(%f,%f) q1=(%f,%f), q2=(%f,%f)", q0.x, q0.y, curr.x, curr.y, q2.x, q2.y); } this->_trajectory->appendSegment(s); } pts = this->_trajectory->getPoints(); pts.push_back(endPoint); ROS_WARN("Trajectory max curvature %f (Min ICR radius %f m)", this->_trajectory->maxCurvature(), 1/this->_trajectory->maxCurvature()); } else { pts = corner_points; } } else { pts = corner_points; } int poseSeq = 0; for (PointArr::iterator it = pts.begin(); it != pts.end(); it++) { Point pt = *it; //float x_m = node.x*resolution; //float y_m = node.y*resolution; //float x_m = pt.x; //float y_m = pt.y; this->_waypoints.push_back(pt); // sstr << "->(" << x_m << "," << y_m << ")"; geometry_msgs::PoseStamped pose; pose.header.seq = poseSeq++; pose.header.stamp = ros::Time::now(); pose.header.frame_id = "map"; pose.pose.position = geometry_msgs_Point_from_Point(pt); pose.pose.orientation = tf::createQuaternionMsgFromYaw(0); pathMsg.poses.push_back(pose); } this->_PIDHelper->setTrajectory(pts); this->_waypointsIt = this->_steeringMode == lunabotics::proto::ACKERMANN ? this->_waypoints.begin() : this->_waypoints.begin()+1; // ROS_INFO("Returned path: %s", sstr.str().c_str()); //Point waypoint = this->_waypoints.at(0); //ROS_INFO("Heading towards (%.1f,%.1f)", (*this->_waypointsIt).x, (*this->_waypointsIt).y); this->_publisherPath.publish(pathMsg); this->_autonomyEnabled = true; lunabotics::ControlParams controlParamsMsg; controlParamsMsg.driving = this->_autonomyEnabled; controlParamsMsg.next_waypoint_idx = this->_waypointsIt < this->_waypoints.end() ? this->_waypointsIt-this->_waypoints.begin()+1 : 0; this->_publisherControlParams.publish(controlParamsMsg); } else { ROS_INFO("Path is empty"); } delete path; }