Cleanup based on ControlledMotor branch
This commit is contained in:
		
							parent
							
								
									1b36f97e18
								
							
						
					
					
						commit
						d07ed323e2
					
				@ -29,17 +29,6 @@ void DifferentialDrive::SetTargetSpeeds(float leftSpeed, float rightSpeed) {
 | 
				
			|||||||
        motor->SetSpeed(leftSpeed);
 | 
					        motor->SetSpeed(leftSpeed);
 | 
				
			||||||
      else if (xPosition > 0)
 | 
					      else if (xPosition > 0)
 | 
				
			||||||
        motor->SetSpeed(rightSpeed);
 | 
					        motor->SetSpeed(rightSpeed);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    } else if (thing->type == Thing::ControlledMotorType) {
 | 
					 | 
				
			||||||
      ControlledMotor* motor = (ControlledMotor*)placement[motorIx].thing;
 | 
					 | 
				
			||||||
      if (motor == nullptr)
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      float xPosition = placement[motorIx].position.x;
 | 
					 | 
				
			||||||
      if (xPosition < 0)
 | 
					 | 
				
			||||||
        motor->SetTargetSpeed(leftSpeed);
 | 
					 | 
				
			||||||
      else if (xPosition > 0)
 | 
					 | 
				
			||||||
        motor->SetTargetSpeed(rightSpeed);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -49,10 +38,3 @@ void DifferentialDrive::SetTwistSpeed(float forward, float yaw) {
 | 
				
			|||||||
  float rightSpeed = Float::Clamp(forward + yaw, -1, 1);
 | 
					  float rightSpeed = Float::Clamp(forward + yaw, -1, 1);
 | 
				
			||||||
  SetTargetSpeeds(leftSpeed, rightSpeed);
 | 
					  SetTargetSpeeds(leftSpeed, rightSpeed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// void DifferentialDrive::SetTwistSpeed(float forward, float yaw, float pitch)
 | 
					 | 
				
			||||||
// {
 | 
					 | 
				
			||||||
//   float leftSpeed = Float::Clamp(forward - yaw, -1, 1);
 | 
					 | 
				
			||||||
//   float rightSpeed = Float::Clamp(forward + yaw, -1, 1);
 | 
					 | 
				
			||||||
//   SetTargetSpeeds(leftSpeed, rightSpeed);
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
#include "Perception.h"
 | 
					#include "Perception.h"
 | 
				
			||||||
#include "Angle.h"
 | 
					#include "Angle.h"
 | 
				
			||||||
 | 
					#include "DistanceSensor.h"
 | 
				
			||||||
#include "Switch.h"
 | 
					#include "Switch.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Perception::Perception() {}
 | 
					Perception::Perception() {}
 | 
				
			||||||
@ -203,18 +204,14 @@ void Perception::SetDepthMap(float angle, float distance) {
 | 
				
			|||||||
  depthMap[depthMapIx] = distance;
 | 
					  depthMap[depthMapIx] = distance;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DistanceSensor* Perception::GetSensor(float angle) {
 | 
					Sensor* Perception::GetSensor(float angle) {
 | 
				
			||||||
  angle = Angle::Normalize(angle);
 | 
					  angle = Angle::Normalize(angle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (unsigned int ix = 0; ix < this->sensorCount; ix++) {
 | 
					  for (unsigned int ix = 0; ix < this->sensorCount; ix++) {
 | 
				
			||||||
    Placement placement = this->sensorPlacements[ix];
 | 
					    Placement placement = this->sensorPlacements[ix];
 | 
				
			||||||
    if (abs(placement.horizontalDirection - angle) < 0.01F)
 | 
					    if (abs(placement.horizontalDirection - angle) < 0.01F)
 | 
				
			||||||
      return (DistanceSensor*)placement.thing;
 | 
					      return (Sensor*)placement.thing;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DistanceSensor* distanceSensor = new DistanceSensor();
 | 
					  return nullptr;
 | 
				
			||||||
  Placement* newPlacement = new Placement(distanceSensor, angle);
 | 
					 | 
				
			||||||
  AddSensors(newPlacement, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return distanceSensor;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -14,7 +14,7 @@ class Perception {
 | 
				
			|||||||
  /// @brief Template to make it possible to leave out ths sensorCount
 | 
					  /// @brief Template to make it possible to leave out ths sensorCount
 | 
				
			||||||
  /// @tparam sensorCount
 | 
					  /// @tparam sensorCount
 | 
				
			||||||
  /// @param sensors An array of sensor placements
 | 
					  /// @param sensors An array of sensor placements
 | 
				
			||||||
  template <size_t sensorCount>
 | 
					  template <unsigned int sensorCount>
 | 
				
			||||||
  inline Perception(Placement (&sensors)[sensorCount]) {
 | 
					  inline Perception(Placement (&sensors)[sensorCount]) {
 | 
				
			||||||
    Perception(sensors, sensorCount);
 | 
					    Perception(sensors, sensorCount);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -73,7 +73,7 @@ class Perception {
 | 
				
			|||||||
  unsigned int ToDepthMapIndex(float angle);
 | 
					  unsigned int ToDepthMapIndex(float angle);
 | 
				
			||||||
  void SetDepthMap(float angle, float distance);
 | 
					  void SetDepthMap(float angle, float distance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DistanceSensor* GetSensor(float angle);
 | 
					  Sensor* GetSensor(float angle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  // SensorPlacement* sensors = nullptr;
 | 
					  // SensorPlacement* sensors = nullptr;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,5 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ControlledMotor.h"
 | 
					 | 
				
			||||||
#include "DistanceSensor.h"
 | 
					 | 
				
			||||||
#include "Motor.h"
 | 
					 | 
				
			||||||
#include "Thing.h"
 | 
					#include "Thing.h"
 | 
				
			||||||
#include "Vector2.h"
 | 
					#include "Vector2.h"
 | 
				
			||||||
#include "Vector3.h"
 | 
					#include "Vector3.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
#include "Propulsion.h"
 | 
					#include "Propulsion.h"
 | 
				
			||||||
#include "ControlledMotor.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "FloatSingle.h"
 | 
					#include "FloatSingle.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,8 +15,6 @@ void Propulsion::AddMotors(Placement* things, unsigned int thingCount) {
 | 
				
			|||||||
    Thing* thing = things[thingIx].thing;
 | 
					    Thing* thing = things[thingIx].thing;
 | 
				
			||||||
    if (thing->IsMotor())
 | 
					    if (thing->IsMotor())
 | 
				
			||||||
      motorCount++;
 | 
					      motorCount++;
 | 
				
			||||||
    if (thing->type == Thing::ControlledMotorType)
 | 
					 | 
				
			||||||
      hasOdometer = true;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  this->placement = new Placement[motorCount];
 | 
					  this->placement = new Placement[motorCount];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -56,13 +53,6 @@ Placement* Propulsion::GetMotorPlacement(unsigned int motorId) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Propulsion::Update(float currentTimeMs) {
 | 
					void Propulsion::Update(float currentTimeMs) {
 | 
				
			||||||
  for (unsigned int motorIx = 0; motorIx < this->motorCount; motorIx++) {
 | 
					 | 
				
			||||||
    Thing* thing = placement[motorIx].thing;
 | 
					 | 
				
			||||||
    if (thing->type == Thing::ControlledMotorType) {
 | 
					 | 
				
			||||||
      ControlledMotor* motor = (ControlledMotor*)thing;
 | 
					 | 
				
			||||||
      motor->Update(currentTimeMs);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  this->lastUpdateTime = currentTimeMs;
 | 
					  this->lastUpdateTime = currentTimeMs;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -78,57 +68,3 @@ void Propulsion::SetTwistSpeed(Vector3 linear,
 | 
				
			|||||||
                               float yaw,
 | 
					                               float yaw,
 | 
				
			||||||
                               float pitch,
 | 
					                               float pitch,
 | 
				
			||||||
                               float roll) {}
 | 
					                               float roll) {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief Odometer returns the total distance traveled since start
 | 
					 | 
				
			||||||
/// @return The total distance
 | 
					 | 
				
			||||||
/// This returns the average distance of all wheels. The odometer cannot be
 | 
					 | 
				
			||||||
/// reset. When using a non-directional encoder, the distance is always
 | 
					 | 
				
			||||||
/// increasing. When using a directional encoder, the distance may go down when
 | 
					 | 
				
			||||||
/// the robot is driving backward.
 | 
					 | 
				
			||||||
/// When no wheel encoder is present, this function always returns zero.
 | 
					 | 
				
			||||||
float Propulsion::GetOdometer() {
 | 
					 | 
				
			||||||
  float odometer = 0;
 | 
					 | 
				
			||||||
  for (unsigned int motorIx = 0; motorIx < this->motorCount; motorIx++) {
 | 
					 | 
				
			||||||
    Thing* thing = placement[motorIx].thing;
 | 
					 | 
				
			||||||
    if ((thing->type & Thing::ControlledMotorType) != 0) {
 | 
					 | 
				
			||||||
      ControlledMotor* motor = (ControlledMotor*)thing;
 | 
					 | 
				
			||||||
      odometer += motor->encoder->GetDistance() / this->motorCount;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return odometer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Propulsion::Drive(Vector3 point, float rotation, float currentTimeMs) {
 | 
					 | 
				
			||||||
  if (!this->driving) {
 | 
					 | 
				
			||||||
    this->startTime = time(NULL);
 | 
					 | 
				
			||||||
    this->targetDistance = point.magnitude();
 | 
					 | 
				
			||||||
    if (hasOdometer)
 | 
					 | 
				
			||||||
      this->startOdometer = GetOdometer();
 | 
					 | 
				
			||||||
    this->driving = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (hasOdometer) {
 | 
					 | 
				
			||||||
    float distance = GetOdometer() - this->startOdometer;
 | 
					 | 
				
			||||||
    if (distance >= this->targetDistance) {
 | 
					 | 
				
			||||||
      this->driving = false;
 | 
					 | 
				
			||||||
      point = Vector3::zero;
 | 
					 | 
				
			||||||
      rotation = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    double duration = difftime(time(NULL), this->startTime);
 | 
					 | 
				
			||||||
    if (duration >= this->targetDistance) {
 | 
					 | 
				
			||||||
      this->driving = false;
 | 
					 | 
				
			||||||
      point = Vector3::zero;
 | 
					 | 
				
			||||||
      rotation = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (rotation > 0)
 | 
					 | 
				
			||||||
    rotation = 1;
 | 
					 | 
				
			||||||
  if (rotation < 0)
 | 
					 | 
				
			||||||
    rotation = -1;
 | 
					 | 
				
			||||||
  SetTwistSpeed(point.normalized() * this->maxSpeed, rotation);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Update(currentTimeMs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (!this->driving);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								Propulsion.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Propulsion.h
									
									
									
									
									
								
							@ -1,12 +1,9 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ControlledMotor.h"
 | 
					#include "Motor.h"
 | 
				
			||||||
#include "Placement.h"
 | 
					#include "Placement.h"
 | 
				
			||||||
// #include "Quadcopter.h"
 | 
					 | 
				
			||||||
#include "Vector2.h"
 | 
					#include "Vector2.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// #include <time.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Passer {
 | 
					namespace Passer {
 | 
				
			||||||
namespace RoboidControl {
 | 
					namespace RoboidControl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,11 +38,6 @@ class Propulsion {
 | 
				
			|||||||
                             float pitch = 0.0F,
 | 
					                             float pitch = 0.0F,
 | 
				
			||||||
                             float roll = 0.0F);  // 3D
 | 
					                             float roll = 0.0F);  // 3D
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Position control (or actually, distance control)
 | 
					 | 
				
			||||||
  bool Drive(Vector3 point, float rotation, float currentTimeMs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  float GetOdometer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Placement* placement = nullptr;
 | 
					  Placement* placement = nullptr;
 | 
				
			||||||
  unsigned int motorCount = 0;
 | 
					  unsigned int motorCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,8 +46,6 @@ class Propulsion {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  bool driving = false;
 | 
					  bool driving = false;
 | 
				
			||||||
  float targetDistance = 0;
 | 
					  float targetDistance = 0;
 | 
				
			||||||
  bool hasOdometer = false;
 | 
					 | 
				
			||||||
  float startOdometer;
 | 
					 | 
				
			||||||
  time_t startTime;
 | 
					  time_t startTime;
 | 
				
			||||||
  float lastUpdateTime;
 | 
					  float lastUpdateTime;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								Roboid.cpp
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								Roboid.cpp
									
									
									
									
									
								
							@ -1,47 +1,9 @@
 | 
				
			|||||||
#include "Roboid.h"
 | 
					#include "Roboid.h"
 | 
				
			||||||
#include <Arduino.h>
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Roboid::Roboid() {
 | 
					Roboid::Roboid() {}
 | 
				
			||||||
  // this->configuration = nullptr;
 | 
					 | 
				
			||||||
  // this->thingCount = 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Roboid::Roboid(Placement configuration[], unsigned int thingCount) {
 | 
					 | 
				
			||||||
//   // this->configuration = configuration;
 | 
					 | 
				
			||||||
//   // this->thingCount = thingCount;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//   perception.AddSensors(configuration, thingCount);
 | 
					 | 
				
			||||||
//   propulsion.AddMotors(configuration, thingCount);
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Roboid::Roboid(Perception* perception, Propulsion* propulsion) {
 | 
					Roboid::Roboid(Perception* perception, Propulsion* propulsion) {
 | 
				
			||||||
  this->perception = perception;
 | 
					  this->perception = perception;
 | 
				
			||||||
  this->propulsion = propulsion;
 | 
					  this->propulsion = propulsion;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Roboid::Drive(Waypoint* waypoint, float currentTimeMs) {
 | 
					 | 
				
			||||||
  bool finished =
 | 
					 | 
				
			||||||
      propulsion->Drive(waypoint->point, waypoint->rotation, currentTimeMs);
 | 
					 | 
				
			||||||
  return finished;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Roboid::FollowTrajectory(Trajectory* trajectory) {
 | 
					 | 
				
			||||||
  this->trajectory = trajectory;
 | 
					 | 
				
			||||||
  this->waypointIx = 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Roboid::Update(float currentTimeMs) {
 | 
					 | 
				
			||||||
  if (this->trajectory == nullptr)
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Waypoint* waypoint = &this->trajectory->waypoints[this->waypointIx];
 | 
					 | 
				
			||||||
  if (Drive(waypoint, currentTimeMs)) {
 | 
					 | 
				
			||||||
    this->waypointIx++;
 | 
					 | 
				
			||||||
    if (this->waypointIx >= this->trajectory->waypointCount) {
 | 
					 | 
				
			||||||
      this->trajectory = nullptr;
 | 
					 | 
				
			||||||
      this->waypointIx = 0;
 | 
					 | 
				
			||||||
      // stop
 | 
					 | 
				
			||||||
      // propulsion.SetTwistSpeed(0, 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										44
									
								
								Roboid.h
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								Roboid.h
									
									
									
									
									
								
							@ -1,42 +1,11 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Activation.h"
 | 
					 | 
				
			||||||
#include "Perception.h"
 | 
					#include "Perception.h"
 | 
				
			||||||
// #include "Placement.h"
 | 
					#include "Propulsion.h"
 | 
				
			||||||
//  #include "Propulsion.h"
 | 
					 | 
				
			||||||
#include "DifferentialDrive.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Passer {
 | 
					namespace Passer {
 | 
				
			||||||
namespace RoboidControl {
 | 
					namespace RoboidControl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Waypoint {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  Waypoint(float forwardDistance, float rotation) {
 | 
					 | 
				
			||||||
    this->point = Vector3(0, 0, forwardDistance);
 | 
					 | 
				
			||||||
    this->distance = forwardDistance;
 | 
					 | 
				
			||||||
    this->rotation = rotation;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  float distance = 0;
 | 
					 | 
				
			||||||
  Vector3 point = Vector3(0, 0, 0);
 | 
					 | 
				
			||||||
  float rotation = 0;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class Trajectory {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  Trajectory(){};
 | 
					 | 
				
			||||||
  Trajectory(Waypoint* waypoints, unsigned int waypointCount) {
 | 
					 | 
				
			||||||
    this->waypoints = waypoints;
 | 
					 | 
				
			||||||
    this->waypointCount = waypointCount;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Waypoint* waypoints;
 | 
					 | 
				
			||||||
  unsigned int waypointCount;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Acceleration {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  float GetMagnitude() { return 0; };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Roboid {
 | 
					class Roboid {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  Roboid();
 | 
					  Roboid();
 | 
				
			||||||
@ -45,19 +14,8 @@ class Roboid {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  Perception* perception;
 | 
					  Perception* perception;
 | 
				
			||||||
  Propulsion* propulsion;
 | 
					  Propulsion* propulsion;
 | 
				
			||||||
  Acceleration acceleration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Placement* configuration;
 | 
					 | 
				
			||||||
  // unsigned int thingCount;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void Update(float currentTimeMs);
 | 
					  void Update(float currentTimeMs);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool Drive(Waypoint* waypoint, float currentTimeMs);
 | 
					 | 
				
			||||||
  void FollowTrajectory(Trajectory* Trajectory);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  Trajectory* trajectory;
 | 
					 | 
				
			||||||
  unsigned int waypointIx = 0;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}  // namespace RoboidControl
 | 
					}  // namespace RoboidControl
 | 
				
			||||||
}  // namespace Passer
 | 
					}  // namespace Passer
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user