-
Niklas Yann Wettengel authoredNiklas Yann Wettengel authored
SpeedControl.cpp 5.17 KiB
#include <cmath>
#include <iostream>
#include <ros/ros.h>
#include "SpeedControl.h"
#include "tools/loadRosConfig.h"
using namespace std;
// Robot dimensions in m
//
//
// /-------------\ <-- MAX_X
// | x |
// | | |
// | | |
// | y----- |
// | |
// | ROBOT |
// | |
// \-------------/ <-- MIN_X
// ^ ^
// | |
// MAX_Y MIN_Y
//
float ROBOT_MIN_X = -0.30;
float ROBOT_MAX_X = 0.30;
float ROBOT_MIN_Y = -0.27;
float ROBOT_MAX_Y = 0.27;
namespace {
Eigen::AlignedBox2f InnerDangerZone,
OuterDangerZone;
float InnerDangerZoneFactor,
OuterDangerZoneFactor;
inline Eigen::AlignedBox2f loadRect(const string& path)
{
pair<float, float> pX, pY;
loadConfigValue(path + "/x_min", pX.first);
loadConfigValue(path + "/x_max", pX.second);
loadConfigValue(path + "/y_min", pY.first);
loadConfigValue(path + "/y_max", pY.second);
Eigen::Vector2f first(pX.first, pY.first), second(pX.second, pY.second);
return Eigen::AlignedBox2f(first, second);
}
}
void SpeedControl::loadDimensions()
{
InnerDangerZone = loadRect("/homer_navigation/speed_control/inner_danger_zone");
InnerDangerZoneFactor;
loadConfigValue("/homer_navigation/speed_control/inner_danger_zone/speed_factor", InnerDangerZoneFactor);
OuterDangerZone = loadRect("/homer_navigation/speed_control/inner_danger_zone");
OuterDangerZoneFactor;
loadConfigValue("/homer_navigation/speed_control/outer_danger_zone/speed_factor", OuterDangerZoneFactor);
if(!OuterDangerZone.contains(InnerDangerZone))
ROS_WARN_STREAM("InnerDangerZone is not contained in OuterDangerZone");
}
float SpeedControl::getSpeedFactor(const vector<geometry_msgs::Point>& points, float minVal, float maxVal )
{
float minFactor = 1.0;
for (unsigned i = 0; i < points.size(); i++)
{
Eigen::Vector2f point(points[i].x, points[i].y);
if(InnerDangerZone.contains(point))
{
minFactor = InnerDangerZoneFactor;
break;
}
if(OuterDangerZone.contains(point))
minFactor = OuterDangerZoneFactor;
}
minFactor = sqrt(minFactor);
float range = maxVal - minVal;
minFactor = minVal + range*minFactor;
return minFactor;
}
float SpeedControl::getMaxMoveDistance(vector<geometry_msgs::Point> points)
{
float minDistance = 4; // distance in m to nearest obstacle in front
for (unsigned int i = 0; i < points.size(); i++)
{
if(points[i].y > ROBOT_MIN_Y && points[i].y < ROBOT_MAX_Y && points[i].x > ROBOT_MAX_X)
{
float distance = sqrt((points[i].x * points[i].x) + (points[i].y * points[i].y));
if (distance < minDistance)
{
minDistance = distance;
}
}
}
float maxMoveDist = minDistance - ROBOT_MAX_X;
if (maxMoveDist < 0) {
maxMoveDist = 0.0;
}
return maxMoveDist;
}
float SpeedControl::getMaxMoveDistance(std::vector< Eigen::Vector3d >* kinectData, float minObstacleHeight, float minObstacleFromRobotDistance, float maxObstacleFromRobotDistance)
{
// Check for obstacles in Kinect image: Look for closest point
float minDistance = 4; // distance to nearest obstacle in front
for(int i=0;i<kinectData->size();++i)
{
Eigen::Vector2d p = Eigen::Vector2d(kinectData->at(i).x(), kinectData->at(i).y());
if(!std::isnan(p.x()))
{
// Filter point cloud
if(p.x() > minObstacleFromRobotDistance && p.x() < maxObstacleFromRobotDistance && kinectData->at(i).z() > minObstacleHeight)
{
// Check for collisions outside of robot
if(p.y() > ROBOT_MIN_Y && p.y() < ROBOT_MAX_Y && p.x() > ROBOT_MAX_X)
{
float distance = sqrt((p.x() * p.x()) + (p.y() * p.y()));
if (distance < minDistance)
{
minDistance = distance;
}
}
}
}
}
float maxMoveDist = minDistance - ROBOT_MAX_X;
if (maxMoveDist < 0) {
maxMoveDist = 0.0;
}
return maxMoveDist;
}
float SpeedControl::getTurnSpeedFactor( float speedFactor, float turnAngle, float minVal, float maxVal )
{
//turn faster for larger angles
float angleDependentFactor = sqrt( fabs(turnAngle) / M_PI );
angleDependentFactor = minVal + angleDependentFactor*(maxVal-minVal);
return sqrt( speedFactor * angleDependentFactor );
}
float SpeedControl::getMinTurnAngle(std::vector<geometry_msgs::Point> laserData, float minAngle, float maxAngle, float minDistance, float maxDistance)
{
float turn_factor = 1.0;
for (unsigned int i = 0; i < laserData.size(); i++)
{
if(laserData[i].y > ROBOT_MIN_Y && laserData[i].y < ROBOT_MAX_Y && laserData[i].x > ROBOT_MAX_X)
{
float distance = sqrt((laserData[i].x * laserData[i].x) + (laserData[i].y * laserData[i].y));
if (distance < minDistance + ROBOT_MAX_X)
{
turn_factor = 0.0;
}
else if(distance > maxDistance + ROBOT_MAX_X)
{
turn_factor = 1.0;
}
else
{
turn_factor = (distance - minDistance)/maxDistance;
}
}
}
float range = maxAngle - minAngle;
return minAngle + turn_factor * range;
}
SpeedControl::SpeedControl() {
}
SpeedControl::~SpeedControl() {
}