Commit fda38ffe authored by Matthew Hausknecht's avatar Matthew Hausknecht

Added base class for feature extraction.

parent 02f7e648
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "feature_extractor.h"
#include <rcsc/common/logger.h>
#include <rcsc/common/server_param.h>
#include <sstream>
using namespace rcsc;
FeatureExtractor::FeatureExtractor() :
numFeatures(-1)
{
const ServerParam& SP = ServerParam::i();
// Grab the field dimensions
pitchLength = SP.pitchLength();
pitchWidth = SP.pitchWidth();
pitchHalfLength = SP.pitchHalfLength();
pitchHalfWidth = SP.pitchHalfWidth();
goalHalfWidth = SP.goalHalfWidth();
penaltyAreaLength = SP.penaltyAreaLength();
penaltyAreaWidth = SP.penaltyAreaWidth();
// Maximum possible radius in HFO
maxHFORadius = sqrtf(pitchHalfLength * pitchHalfLength +
pitchHalfWidth * pitchHalfWidth);
}
FeatureExtractor::~FeatureExtractor() {}
void FeatureExtractor::LogFeatures() {
assert(feature_vec.size() == numFeatures);
std::stringstream ss;
for (int i=0; i<numFeatures; ++i) {
ss << feature_vec[i] << " ";
}
elog.addText(Logger::WORLD, "StateFeatures %s", ss.str().c_str());
elog.flush();
}
void FeatureExtractor::addAngFeature(const rcsc::AngleDeg& ang) {
addFeature(ang.sin());
addFeature(ang.cos());
}
void FeatureExtractor::addDistFeature(float dist, float maxDist) {
float proximity = 1.f - std::max(0.f, std::min(1.f, dist/maxDist));
addNormFeature(proximity, 0., 1.);
}
// Add the angle and distance to the landmark to the feature_vec
void FeatureExtractor::addLandmarkFeatures(const rcsc::Vector2D& landmark,
const rcsc::Vector2D& self_pos,
const rcsc::AngleDeg& self_ang) {
if (self_pos == Vector2D::INVALIDATED) {
addFeature(0);
addFeature(0);
addFeature(0);
} else {
Vector2D vec_to_landmark = landmark - self_pos;
addAngFeature(self_ang - vec_to_landmark.th());
addDistFeature(vec_to_landmark.r(), maxHFORadius);
}
}
void FeatureExtractor::addPlayerFeatures(rcsc::PlayerObject& player,
const rcsc::Vector2D& self_pos,
const rcsc::AngleDeg& self_ang) {
assert(player.posValid());
// Angle dist to player.
addLandmarkFeatures(player.pos(), self_pos, self_ang);
// Player's body angle
addAngFeature(player.body());
if (player.velValid()) {
// Player's speed
addNormFeature(player.vel().r(), 0., observedPlayerSpeedMax);
// Player's velocity direction
addAngFeature(player.vel().th());
} else {
addFeature(0);
addFeature(0);
addFeature(0);
}
}
void FeatureExtractor::addFeature(float val) {
assert(featIndx < numFeatures);
feature_vec[featIndx++] = val;
}
void FeatureExtractor::addNormFeature(float val, float min_val, float max_val) {
assert(featIndx < numFeatures);
if (val < min_val || val > max_val) {
std::cout << "Feature " << featIndx << " Violated Feature Bounds: " << val
<< " Expected min/max: [" << min_val << ", " << max_val << "]" << std::endl;
val = std::min(std::max(val, min_val), max_val);
}
feature_vec[featIndx++] = ((val - min_val) / (max_val - min_val))
* (FEAT_MAX - FEAT_MIN) + FEAT_MIN;
}
void FeatureExtractor::checkFeatures() {
assert(feature_vec.size() == numFeatures);
for (int i=0; i<numFeatures; ++i) {
if (feature_vec[i] < FEAT_MIN || feature_vec[i] > FEAT_MAX) {
std::cout << "Invalid Feature! Indx:" << i << " Val:" << feature_vec[i] << std::endl;
exit(1);
}
}
}
#ifndef FEATURE_EXTRACTOR_H
#define FEATURE_EXTRACTOR_H
#include <rcsc/player/player_agent.h>
#include <vector>
class FeatureExtractor {
public:
FeatureExtractor();
virtual ~FeatureExtractor();
// Updated the state features stored in feature_vec
virtual const std::vector<float>& ExtractFeatures(const rcsc::WorldModel& wm) = 0;
// Record the current state
void LogFeatures();
// How many features are there?
inline int getNumFeatures() { return numFeatures; }
protected:
// Encodes an angle feature as the sin and cosine of that angle,
// effectively transforming a single angle into two features.
void addAngFeature(const rcsc::AngleDeg& ang);
// Encodes a proximity feature which is defined by a distance as
// well as a maximum possible distance, which acts as a
// normalizer. Encodes the distance as [0-far, 1-close]. Ignores
// distances greater than maxDist or less than 0.
void addDistFeature(float dist, float maxDist);
// Add the angle and distance to the landmark to the feature_vec
void addLandmarkFeatures(const rcsc::Vector2D& landmark,
const rcsc::Vector2D& self_pos,
const rcsc::AngleDeg& self_ang);
// Add features corresponding to another player.
void addPlayerFeatures(rcsc::PlayerObject& player,
const rcsc::Vector2D& self_pos,
const rcsc::AngleDeg& self_ang);
// Add a feature without normalizing
void addFeature(float val);
// Add a feature and normalize to the range [FEAT_MIN, FEAT_MAX]
void addNormFeature(float val, float min_val, float max_val);
// Checks that features are in the range of FEAT_MIN - FEAT_MAX
void checkFeatures();
protected:
int featIndx;
std::vector<float> feature_vec; // Contains the current features
const static float FEAT_MIN = -1;
const static float FEAT_MAX = 1;
int numFeatures; // Total number of features
// Observed values of some parameters.
const static float observedSelfSpeedMax = 0.46;
const static float observedPlayerSpeedMax = 0.75;
const static float observedStaminaMax = 8000.;
const static float observedBallSpeedMax = 5.0;
float maxHFORadius; // Maximum possible distance in HFO playable region
// Useful measures defined by the Server Parameters
float pitchLength, pitchWidth, pitchHalfLength, pitchHalfWidth,
goalHalfWidth, penaltyAreaLength, penaltyAreaWidth;
};
#endif // FEATURE_EXTRACTOR_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment