Skip to content

Instantly share code, notes, and snippets.

@jdowner
Created January 5, 2012 01:52
Show Gist options
  • Save jdowner/1563274 to your computer and use it in GitHub Desktop.
Save jdowner/1563274 to your computer and use it in GitHub Desktop.
A simple turret that tracks a target.
#include "Turret.h"
#include <cmath>
#include <algorithm>
#include <cassert>
namespace
{
const double TWOPI = 2.0 * M_PI;
}
Turret::Turret()
: m_x(0.0)
, m_y(0.0)
, m_orientation(0.0)
, m_maxRotation(1.0)
{
}
void Turret::setPosition(double x, double y)
{
m_x = x;
m_y = y;
}
void Turret::setOrientation(double orientation)
{
m_orientation = orientation;
}
void Turret::setMaxRotationSpeed(double maxRotation)
{
assert(maxRotation >= 0.0);
m_maxRotation = maxRotation;
}
double Turret::x() const
{
return m_x;
}
double Turret::y() const
{
return m_y;
}
double Turret::orientation() const
{
return m_orientation;
}
void Turret::orientTo(double x, double y, double dt)
{
assert(dt > 0.0);
// Determine the position fo the target relative to the turret
const double rx = x - m_x;
const double ry = y - m_y;
// Determine the orientation of the target
const double target = atan2(ry, rx);
// Orient the turret to the target angle
orientTo(target, dt);
}
void Turret::orientTo(double target, double dt)
{
assert(dt > 0.0);
assert((-M_PI <= target) && (target <= M_PI));
// Determine how much the turret must rotate
const double delta = wrapAngle(target - m_orientation);
// Orient towards target
m_orientation += std::min(delta, m_maxRotation * dt);
m_orientation = wrapAngle(m_orientation);
}
double Turret::wrapAngle(double angle) const
{
if (angle > M_PI)
{
angle -= TWOPI;
}
else if (angle < -M_PI)
{
angle += TWOPI;
}
assert((-M_PI <= angle) && (angle <= M_PI));
return angle;
}
#ifndef TURRET_H
#define TURRET_H
/**
* This class describes a turret that has a fixed location and rotates about the
* z axis (note: a right handed co-ordinate system is used with the z axis
* oriented up). The turret rotates with a maximum rotational speed towards a
* specified location or target angle. If the turrent cannot move to the exact
* target location/angle within the specified time frame, it moves as quickly as
* it can to minimize the angular distance between it and the target.
*/
class Turret
{
public:
Turret();
/**
* Sets the x and y position of the turret
*/
void setPosition(double x, double y);
/**
* Sets the orientation of the turrent. The orientation is defined as the
* angle (in radians) between the turrents 'gun' and the x axis. The angle
* must be on the interval [-pi,pi]
*/
void setOrientation(double orientation);
/**
* Sets the maximum speed that the turret can rotate at.
*/
void setMaxRotationSpeed(double maxRotation);
/**
* Returns the position of the turret in the x axis
*/
double x() const;
/**
* Returns the position of the turret in the y axis
*/
double y() const;
/**
* Returns the orientation of the turret. The value will be on the interval
* [-pi,pi].
*/
double orientation() const;
/**
* Orients the turret towards the specified target position. The position
* of the target is given by x and y. The turret is given dt seconds to
* rotate.
*/
void orientTo(double x, double y, double dt);
/**
* Orients the turret towards the specified target position. The position of
* the target is given as an angle relative to the turret. The turret is
* given dt seconds to rotate.
*/
void orientTo(double target, double dt);
private:
/**
* Wraps the specified angle to the interval [-pi,pi] assuming that the
* angle is on the interval [-3*pi, 3*pi].
*/
double wrapAngle(double angle) const;
private:
double m_x;
double m_y;
double m_orientation;
double m_maxRotation;
};
#endif // TURRET_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment