Updated Documentation

This commit is contained in:
Pascal Serrarens 2023-12-05 12:25:27 +01:00
parent 58448538fb
commit da29673459
13 changed files with 167 additions and 187 deletions

View File

@ -6,6 +6,7 @@
namespace Passer {
namespace RoboidControl {
/// @brief Activation function for control
class Activation {
public:
static float HeavisideStep(float inputValue, float bias = 0); // Range: {0,1}

View File

@ -38,3 +38,14 @@ void DifferentialDrive::SetTwistSpeed(float forward, float yaw) {
float rightSpeed = Float::Clamp(forward + yaw, -1, 1);
SetTargetSpeeds(leftSpeed, rightSpeed);
}
void DifferentialDrive::SetTwistSpeed(Vector2 linear, float yaw) {
SetTwistSpeed(linear.y, yaw);
}
void DifferentialDrive::SetTwistSpeed(Vector3 linear,
float yaw,
float pitch,
float roll) {
SetTwistSpeed(linear.z, yaw);
}

View File

@ -5,15 +5,57 @@
namespace Passer {
namespace RoboidControl {
/// @brief A two-wheeled Propulsion method
///
/// The wheels are put at either side of the roboid with the following behaviour
/// * When both wheels spin forward, the Roboid moves forward
/// * When both wheels spin backward, the Roboid moves backward
/// * When both wheels are spinning in opposite directions, the Roboid rotates
/// wihout moving forward or backward
/// * When just one wheel is spinning, the Roboid turnes while moving forward or
/// backward.
class DifferentialDrive : public Propulsion {
public:
/// @brief Default constructor
DifferentialDrive();
/// @brief Setup of the DifferentialDrive with the Placement of the motors
/// @param leftMotorPlacement Placement of the left Motor
/// @param rightMotorPlacement Placement of the right Motor
/// In this setup, the left motor Direction will be CounterClockWise when
/// driving forward, while the right motor will turn Clockwise.
/// @note When not using controlled motors, the placement of the motors is
/// irrelevant.
DifferentialDrive(Placement leftMotorPlacement,
Placement rightMotorPlacement);
/// @brief Set the target speeds of the motors directly
/// @param leftSpeed The target speed of the left Motor
/// @param rightSpeed The target speed of the right Motor
void SetTargetSpeeds(float leftSpeed, float rightSpeed);
/// @brief Controls the motors through forward and rotation speeds
/// @param forward The target forward speed of the Roboid
/// @param yaw The target rotation speed of the Roboid
virtual void SetTwistSpeed(float forward, float yaw) override;
// virtual void SetTwistSpeed(float forward, float yaw, float pitch) override;
/// @brief Controls the motors through forward and rotation speeds
/// @param linear The target linear speed of the Roboid
/// @param yaw The target rotation speed of the Roboid
/// @note As a DifferentialDrive cannot move sideward, this function has the
/// same effect as using the void SetTwistSpeed(float forward, float yaw)
/// function.
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F);
/// @brief Controls the motors through forward and rotation speeds
/// @param linear The target linear speed
/// @param yaw The target rotation speed around the vertical axis
/// @param pitch Pitch is not supported and is ignored
/// @param roll Roll is not supported and is ignores
/// @note As a DifferentialDrive cannot move sideward or vertical, this
/// function has the same effect as using the void SetTwistSpeed(float
/// forward, float yaw) function.
virtual void SetTwistSpeed(Vector3 linear,
float yaw = 0.0F,
float pitch = 0.0F,
float roll = 0.0F);
};
} // namespace RoboidControl

View File

@ -12,16 +12,7 @@ float DistanceSensor::GetDistance() {
return distance;
};
void DistanceSensor::SetDistance(float distance) {
this->distance = distance;
}; // for simulation purposes
bool DistanceSensor::IsOn() {
bool isOn = GetDistance() <= triggerDistance;
return isOn;
}
bool DistanceSensor::isOff() {
bool isOff = GetDistance() > triggerDistance;
return isOff;
}

View File

@ -8,21 +8,26 @@ namespace RoboidControl {
/// @brief A Sensor which can measure the distance to the nearest object
class DistanceSensor : public Sensor {
public:
/// @brief Default constructor
DistanceSensor();
/// @brief Creates a DistanceSensor with the given trigger distance
/// @param triggerDistance The distance at which the sensors indicates that a
/// object is close by
DistanceSensor(float triggerDistance);
/// @brief Determine the distance to the nearest object
/// @return the measured distance in meters to the nearest object
virtual float GetDistance();
void SetDistance(float distance);
/// @brief The distance at which ObjectNearby triggers
float triggerDistance = 1;
/// @brief Indicate that an object is nearby
/// @return True when an object is nearby
bool IsOn();
bool isOff();
protected:
/// @brief Distance to the closest object
float distance = 0;
};

View File

@ -12,19 +12,3 @@ float Motor::GetSpeed() {
void Motor::SetSpeed(float targetSpeed) {
this->currentTargetSpeed = targetSpeed;
}
bool Motor::Drive(float distance) {
if (!this->driving) {
this->startTime = time(NULL);
this->targetDistance = distance >= 0 ? distance : -distance;
this->driving = true;
}
double duration = difftime(time(NULL), this->startTime);
if (duration >= this->targetDistance) {
this->driving = false;
return true;
}
SetSpeed(distance < 0 ? -1 : 1); // max speed
return false;
}

View File

@ -27,13 +27,8 @@ class Motor : public Thing {
/// forward)
virtual float GetSpeed();
bool Drive(float distance);
protected:
float currentTargetSpeed = 0;
bool driving = false;
float targetDistance = 0;
time_t startTime = 0;
};
} // namespace RoboidControl

View File

@ -10,24 +10,6 @@ Perception::Perception(Placement* sensors, unsigned int sensorCount) {
this->sensorPlacements = (Placement*)sensors;
}
void Perception::AddSensors(Placement* things, unsigned int thingCount) {
sensorCount = 0;
for (unsigned int thingIx = 0; thingIx < thingCount; thingIx++) {
Thing* thing = things[thingIx].thing;
if (thing->IsSensor())
sensorCount++;
}
sensorPlacements = new Placement[sensorCount];
unsigned int sensorIx = 0;
for (unsigned int thingIx = 0; thingIx < thingCount; thingIx++) {
Thing* thing = things[thingIx].thing;
if (thing->IsSensor())
sensorPlacements[sensorIx++] = things[thingIx];
}
}
unsigned int Perception::GetSensorCount() {
return this->sensorCount;
}
@ -154,64 +136,4 @@ bool Perception::SwitchOn(float fromAngle, float toAngle) {
}
}
return false;
}
unsigned int Perception::ToDepthMapIndex(float angle) {
unsigned int depthMapIx =
(unsigned int)(((angle - rangeMinimum) / (rangeMaximum - rangeMinimum)) *
(float)resolution);
return depthMapIx;
}
float Perception::GetDistance(float angle) {
if (depthMap != nullptr) {
if (angle < rangeMinimum || angle > rangeMaximum)
return INFINITY;
unsigned int depthMapIx = ToDepthMapIndex(angle);
return depthMap[depthMapIx];
} else {
for (unsigned int sensorIx = 0; sensorIx < this->sensorCount; sensorIx++) {
Placement placement = sensorPlacements[sensorIx];
float placementAngle = placement.horizontalDirection;
if (placementAngle == angle) {
DistanceSensor* distanceSensor = (DistanceSensor*)placement.thing;
return distanceSensor->GetDistance();
}
}
}
return INFINITY;
}
void Perception::SetResolution(unsigned int resolution) {
this->resolution = resolution;
this->depthMap = new float[this->resolution];
}
void Perception::SetRange(float min, float max) {
this->rangeMinimum = min;
this->rangeMaximum = max;
}
float* Perception::GetDepthMap() {
return this->depthMap;
}
void Perception::SetDepthMap(float angle, float distance) {
if (angle < rangeMinimum || angle > rangeMaximum)
return;
unsigned int depthMapIx = ToDepthMapIndex(angle);
depthMap[depthMapIx] = distance;
}
Sensor* Perception::GetSensor(float angle) {
angle = Angle::Normalize(angle);
for (unsigned int ix = 0; ix < this->sensorCount; ix++) {
Placement placement = this->sensorPlacements[ix];
if (abs(placement.horizontalDirection - angle) < 0.01F)
return (Sensor*)placement.thing;
}
return nullptr;
}

View File

@ -6,9 +6,10 @@
namespace Passer {
namespace RoboidControl {
/// @brief Module to which keeps track of objects around the roboid
class Perception {
public:
/// @brief Setup perception
/// @brief Default Constructor
Perception();
/// @brief Template to make it possible to leave out ths sensorCount
@ -18,14 +19,31 @@ class Perception {
inline Perception(Placement (&sensors)[sensorCount]) {
Perception(sensors, sensorCount);
}
/// @brief Create a perception setup with the given Sensors
/// @param sensors The Placement of Sensors on the Roboid
/// @param sensorCount The number of sensors in the placement array
Perception(Placement* sensors, unsigned int sensorCount);
void AddSensors(Placement* sensors, unsigned int sensorCount);
/// @brief Get the number of Sensors
/// @return The number of sensors, zero when no sensors are present
unsigned int GetSensorCount();
Sensor* GetSensor(unsigned int sensorId);
/// @brief Get a specific Sensor on the Roboid
/// @param sensorId The index of the Sensor
/// @return The requested Sensor or a nullptr when no Sensor with the given
/// index could be found
Sensor* GetSensor(unsigned int sensorIx);
/// @brief Get the placement of a specific Sensor
/// @param motorIx The index of the Sensor
/// @return Returns the Placement or a nullptr when no Placement with the
/// given index could be found
Placement* GetSensorPlacement(unsigned int sensorIx);
float DistanceForward(float angle = 90);
/// @brief Distance to the closest object on the front of the Roboid
/// @param direction The direction relative to the forward direction in which
/// the object should be present
/// @return The distance to the closest object within the given range,
/// INFINITY when no object is detected
float DistanceForward(float direction = 90);
/// @brief Distance to the closest object on the left
/// @return distance in meters, INFINITY when no object is detected.
@ -57,33 +75,39 @@ class Perception {
/// @note When an object is beyond `angle` meters, it is not reported.
float DistanceRight(float angle);
/// @brief Distance to the closest object above the Roboid
/// @return distance in meters, INFINITY when no object is detected
float DistanceUp() { return DistanceUp(180); }
/// @brief Distance to the closest object above the Roboid within the give
/// range
/// @param angle The angle relative to the upward direction to indicate the
/// range
/// @return distance in meters, INFINITY when no object is detected
float DistanceUp(float angle);
/// @brief Disatnce to the closest object under the Roboid
/// @return distance in meters, INFINITY when no object is detected
float DistanceDown() { return DistanceDown(180); }
/// @brief Distance to the closest object under th4e Roboid within the given
/// range
/// @param angle The angle relative to the downward direciton to indicate the
/// range
/// @return distance in meters, INFINITY when no object is detected
float DistanceDown(float angle);
float Distance(float leftAngle, float rightAngle);
float GetDistance(float angle);
/// @brief Checks if an object is close within the give range in the
/// horizontal plane
/// @param fromAngle Start angle in the horizontal plane
/// @param toAngle End angle in the horizontal plane
/// @return True is an object is closeby
/// @note Whether an object is closeby depends on the Distance Sensor
/// @remark This function is likely to change in the near future
bool SwitchOn(float fromAngle, float toAngle);
void SetResolution(unsigned int resolution);
void SetRange(float min, float max);
float* GetDepthMap();
unsigned int ToDepthMapIndex(float angle);
void SetDepthMap(float angle, float distance);
Sensor* GetSensor(float angle);
protected:
// SensorPlacement* sensors = nullptr;
/// @brief The Placement of the Sensors used for Perception
Placement* sensorPlacements = nullptr;
/// @brief The number of Sensors used for Perception
unsigned int sensorCount = 0;
unsigned int resolution;
float rangeMinimum;
float rangeMaximum;
float* depthMap = nullptr;
};
} // namespace RoboidControl

View File

@ -9,23 +9,6 @@ Propulsion::Propulsion() {
this->motorCount = 0;
}
void Propulsion::AddMotors(Placement* things, unsigned int thingCount) {
this->motorCount = 0;
for (unsigned int thingIx = 0; thingIx < thingCount; thingIx++) {
Thing* thing = things[thingIx].thing;
if (thing->IsMotor())
motorCount++;
}
this->placement = new Placement[motorCount];
unsigned int motorIx = 0;
for (unsigned int thingIx = 0; thingIx < thingCount; thingIx++) {
Thing* thing = things[thingIx].thing;
if (thing->IsMotor())
this->placement[motorIx++] = things[thingIx];
}
}
unsigned int Propulsion::GetMotorCount() {
return this->motorCount;
}
@ -52,13 +35,7 @@ Placement* Propulsion::GetMotorPlacement(unsigned int motorId) {
return nullptr;
}
void Propulsion::Update(float currentTimeMs) {
this->lastUpdateTime = currentTimeMs;
}
void Propulsion::SetMaxSpeed(float maxSpeed) {
this->maxSpeed = abs(maxSpeed);
}
void Propulsion::Update(float currentTimeMs) {}
void Propulsion::SetTwistSpeed(float forward, float yaw) {}

View File

@ -7,47 +7,65 @@
namespace Passer {
namespace RoboidControl {
/// @brief The Propulsion module for a Roboid is used to move the Roboid in
/// space
///
/// Usually, a specific implementation of the propulsion module is used for a
/// robot. This base class does not implement the functions to move the Roboid
/// around.
class Propulsion {
public:
/// @brief Setup sensing
/// @brief Default Constructor for Propulsion
Propulsion();
/// @brief Update the propulsion state of the Roboid
/// @param currentTimeMs The time in milliseconds when calling this
void Update(float currentTimeMs);
void AddMotors(Placement* motors, unsigned int motorCount);
// void AddQuadcopter(Quadcopter* quadcopter);
// Quadcopter* GetQuadcopter();
/// @brief Get the number of motors in this roboid
/// @return The number of motors. Zero when no motors are present
unsigned int GetMotorCount();
/// @brief Get a specific motor
/// @param motorIx The index of the motor
/// @return Returns the motor or a nullptr when no motor with the given index
/// could be found
Motor* GetMotor(unsigned int motorIx);
/// @brief Get the Placement of a specific Motor
/// @param motorIx The index of the Motor
/// @return Returns the Placement or a nullptr when no Placement with the give
/// index could be found
Placement* GetMotorPlacement(unsigned int motorIx);
/// @brief Set the maximum linear speed.
/// @param maxSpeed The new maximum linear speed
/// For controlled motors, this is rpm.
/// For calibrated controlled motors, this is m/s
/// For uncontrolled motors this is a value between 0 and 1 where 1 is the
/// maximum speed of the motor
void SetMaxSpeed(float maxSpeed);
// Velocity control
virtual void SetTwistSpeed(float forward, float yaw = 0.0F); // 2D
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F); // 2D plus
/// @brief Sets the forward and rotation speed of a (grounded) Roboid
/// @param forward The target forward speed
/// @param yaw The target rotation speed around the vertical axis
/// This function is typically used for Roboid which are driving on the
/// ground.
virtual void SetTwistSpeed(float forward, float yaw = 0.0F);
/// @brief Sets the forward, sideward and rotation speed of a (grounded)
/// Roboid
/// @param linear The target linear (forward, sideward) speed
/// @param yaw The target rotation speed around the vertical axis
/// This function is typically used for Roboid which are driving on the ground
/// which have to ability to move sideward
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F);
/// @brief Set the target 3D linear and 3D rotation speed of a (flying) Roboid
/// @param linear The target linear speed
/// @param yaw The target rotation speed around the vertical axis
/// @param pitch The target rotation speed around the sideward axis
/// @param roll The target rotation speed around hte forward axis
virtual void SetTwistSpeed(Vector3 linear,
float yaw = 0.0F,
float pitch = 0.0F,
float roll = 0.0F); // 3D
Placement* placement = nullptr;
unsigned int motorCount = 0;
float roll = 0.0F);
protected:
float maxSpeed = 1;
bool driving = false;
float targetDistance = 0;
time_t startTime;
float lastUpdateTime;
/// @brief The number of motors used for Propulsion
unsigned int motorCount = 0;
/// @brief The Placement of the motors used for Propulsion
Placement* placement = nullptr;
};
} // namespace RoboidControl

View File

@ -6,16 +6,25 @@
namespace Passer {
namespace RoboidControl {
/// @brief A Roboid is used to control autonomous robots
class Roboid {
public:
/// @brief Default constructor for a Roboid
Roboid();
Roboid(Placement configuration[], unsigned int thingCount);
/// @brief Creates a Roboid with Perception and Propulsion abilities
/// @param perception The Perception implementation to use for this Roboid
/// @param propulsion The Propulsion implementation to use for this Roboid
Roboid(Perception* perception, Propulsion* propulsion);
Perception* perception;
Propulsion* propulsion;
/// @brief Update the state of the Roboid
/// @param currentTimeMs The time in milliseconds when calling this
/// function
void Update(float currentTimeMs);
/// @brief The Perception module of this Roboid
Perception* perception;
/// @brief The Propulsion module of this Roboid
Propulsion* propulsion;
};
} // namespace RoboidControl
} // namespace Passer

View File

@ -8,6 +8,7 @@ namespace RoboidControl {
/// @brief A sensor is a thing which can perform measurements in the environment
class Sensor : public Thing {
public:
/// @brief Default Constructor for a Sensor
Sensor();
};