21 #include <boost/algorithm/clamp.hpp> 38 for(
size_t idx = 0; idx < 8; idx++){
50 template<
int ROWS,
int COLS,
int ORDER>
51 Eigen::MatrixXd
getTableNew(
const std::string& path,
const char* name){
52 std::vector<double> data;
55 throw std::invalid_argument(std::string(
"Wrong parameter name: ") + name);
58 return Eigen::Matrix<double, ROWS, COLS, ORDER>(data.data());
63 tables_.
CS_rudder = getTableNew<8, 20, Eigen::RowMajor>(path,
"CS_rudder_table");
64 tables_.
CS_beta = getTableNew<8, 90, Eigen::RowMajor>(path,
"CS_beta");
65 tables_.
AoA = getTableNew<1, 47, Eigen::RowMajor>(path,
"AoA");
66 tables_.
AoS = getTableNew<90, 1, Eigen::ColMajor>(path,
"AoS");
67 tables_.
actuator = getTableNew<20, 1, Eigen::ColMajor>(path,
"actuator_table");
68 tables_.
airspeed = getTableNew<8, 1, Eigen::ColMajor>(path,
"airspeed_table");
78 tables_.
prop = getTableNew<40, 5, Eigen::RowMajor>(path,
"prop");
80 throw std::invalid_argument(std::string(
"Wrong parameter name: ") +
"actuatorTimeConstants");
88 double mainEngineLocX;
111 params_.
inertia = getTableNew<3, 3, Eigen::RowMajor>(path,
"inertia");
115 const Eigen::Quaterniond& attitude){
122 const Eigen::Vector3d& angularVelocity){
139 constexpr
double MAG_ROTATION_SPEED = 2 * 3.1415 / 10;
150 if(prevCalibrationType != calType){
156 if(prevCalibrationType != calType){
162 if(prevCalibrationType != calType){
168 if(prevCalibrationType != calType){
174 if(prevCalibrationType != calType){
180 if(prevCalibrationType != calType){
186 state_.
angularVel << MAG_ROTATION_SPEED, MAG_ROTATION_SPEED, MAG_ROTATION_SPEED;
189 state_.
angularVel << -MAG_ROTATION_SPEED, MAG_ROTATION_SPEED, MAG_ROTATION_SPEED;
192 state_.
angularVel << MAG_ROTATION_SPEED, -MAG_ROTATION_SPEED, MAG_ROTATION_SPEED;
196 if(prevCalibrationType != calType){
202 if(prevCalibrationType != calType){
208 if(prevCalibrationType != calType){
214 if(prevCalibrationType != calType){
220 if(prevCalibrationType != calType){
226 if(prevCalibrationType != calType){
241 auto modeInteger =
static_cast<int>(calType);
242 if(prevCalibrationType != calType){
244 prevCalibrationType = calType;
249 constexpr
double DELTA_TIME = 0.001;
254 state_.
attitude.coeffs() += attitudeDelta.coeffs() * 0.5 * DELTA_TIME;
260 const std::vector<double>& motorCmd,
286 std::cerr <<
"ERROR: InnoVtolDynamicsSim wrong control size. It is " << cmd.size()
287 <<
", but should be 8" << std::endl;
291 std::vector<double> actuators(8);
292 actuators[0] = cmd[0];
293 actuators[1] = cmd[1];
294 actuators[2] = cmd[2];
295 actuators[3] = cmd[3];
296 actuators[4] = cmd[4];
297 actuators[5] = (cmd[5] - cmd[6]) / 2;
298 actuators[6] = -cmd[7];
301 for(
size_t idx = 0; idx < 5; idx++){
302 actuators[idx] = boost::algorithm::clamp(actuators[idx], 0.0, +1.0);
306 for(
size_t idx = 5; idx < 8; idx++){
307 actuators[idx] = boost::algorithm::clamp(actuators[idx], -1.0, +1.0);
331 std::cerr <<
"ERROR: InnoVtolDynamicsSim wrong control size. It is " << cmd.size()
332 <<
", but should be 8" << std::endl;
336 std::vector<double> actuators(8);
337 actuators[0] = cmd[0];
338 actuators[1] = cmd[1];
339 actuators[2] = cmd[2];
340 actuators[3] = cmd[3];
342 actuators[4] = cmd[7];
343 actuators[5] = cmd[4];
344 actuators[6] = cmd[5];
345 actuators[7] = cmd[6];
347 for(
size_t idx = 0; idx < 5; idx++){
348 actuators[idx] = boost::algorithm::clamp(actuators[idx], 0.0, +1.0);
352 actuators[5] = (actuators[5] - 0.5) * 2;
353 for(
size_t idx = 5; idx < 8; idx++){
354 actuators[idx] = boost::algorithm::clamp(actuators[idx], -1.0, +1.0);
363 for(
size_t idx = 0; idx < 8; idx++){
371 Eigen::Vector3d wind;
380 Eigen::Vector3d gust;
391 const Eigen::Vector3d& velocity,
392 const Eigen::Vector3d& windSpeed)
const{
393 Eigen::Vector3d airspeed = rotationMatrix * (velocity - windSpeed);
394 if(abs(airspeed[0]) > 40 || abs(airspeed[1]) > 40 || abs(airspeed[2]) > 40){
395 airspeed[0] = boost::algorithm::clamp(airspeed[0], -40, +40);
396 airspeed[1] = boost::algorithm::clamp(airspeed[1], -40, +40);
397 airspeed[2] = boost::algorithm::clamp(airspeed[2], -40, +40);
398 std::cout <<
"Warning: airspeed is out of limit." << std::endl;
413 double A = sqrt(airSpeed[0] * airSpeed[0] + airSpeed[2] * airSpeed[2]);
418 A = boost::algorithm::clamp(A, -1.0, +1.0);
419 A = (airSpeed[0] > 0) ? asin(A) : 3.1415 - asin(A);
420 return (A > 3.1415) ? A - 2 * 3.1415 : A;
424 double B = airSpeed.norm();
429 B = boost::algorithm::clamp(B, -1.0, +1.0);
445 Eigen::Vector3d& Faero,
446 Eigen::Vector3d& Maero){
448 double AoA_deg = boost::algorithm::clamp(AoA * 180 / 3.1415, -45.0, +45.0);
449 double AoS_deg = boost::algorithm::clamp(AoS * 180 / 3.1415, -90.0, +90.0);
450 double airspeedMod = airspeed.norm();
452 double airspeedModClamped = boost::algorithm::clamp(airspeed.norm(), 5, 40);
455 Eigen::VectorXd polynomialCoeffs(7);
462 FL = (Eigen::Vector3d(0, 1, 0).cross(airspeed.normalized())) * CL;
468 FS = airspeed.cross(Eigen::Vector3d(0, 1, 0).cross(airspeed.normalized())) * (CS + CS_rudder + CS_beta);
471 double CD =
Math::polyval(polynomialCoeffs.block<5, 1>(0, 0), AoA_deg);
472 FD = (-1 * airspeed).normalized() * CD;
474 Faero = 0.5 * dynamicPressure * (FL + FS + FD);
496 auto Mx = Cmx + Cmx_aileron * aileron_pos;
497 auto My = Cmy + Cmy_elevator * elevator_pos;
498 auto Mz = Cmz + Cmz_rudder * rudder_pos;
506 state_.
moments.
steer << Cmx_aileron * aileron_pos, Cmy_elevator * elevator_pos, Cmz_rudder * rudder_pos;
513 double& thrust,
double& torque,
double& rpm)
const{
514 constexpr
size_t CONTROL_IDX = 0;
515 constexpr
size_t THRUST_IDX = 1;
516 constexpr
size_t TORQUE_IDX = 2;
517 constexpr
size_t RPM_IDX = 4;
520 size_t next_idx = prev_idx + 1;
524 auto t = (actuator - prev_row(CONTROL_IDX)) / (next_row(CONTROL_IDX) - prev_row(CONTROL_IDX));
525 thrust =
Math::lerp(prev_row(THRUST_IDX), next_row(THRUST_IDX), t);
526 torque =
Math::lerp(prev_row(TORQUE_IDX), next_row(TORQUE_IDX), t);
527 rpm =
Math::lerp(prev_row(RPM_IDX), next_row(RPM_IDX), t);
532 const Eigen::Vector3d& Faero,
533 const std::vector<double>& actuator,
535 Eigen::VectorXd thrust(5);
536 Eigen::VectorXd torque(5);
537 for(
size_t idx = 0; idx < 5; idx++){
541 for(
size_t idx = 0; idx < 4; idx++){
546 std::array<Eigen::Vector3d, 5> motorTorquesInBodyCS;
547 motorTorquesInBodyCS[0] << 0, 0, torque[0];
548 motorTorquesInBodyCS[1] << 0, 0, torque[1];
549 motorTorquesInBodyCS[2] << 0, 0, -torque[2];
550 motorTorquesInBodyCS[3] << 0, 0, -torque[3];
551 motorTorquesInBodyCS[4] << -torque[4], 0, 0;
552 std::array<Eigen::Vector3d, 5> MdueToArmOfForceInBodyCS;
553 for(
size_t idx = 0; idx < 5; idx++){
563 state_.
attitude.coeffs() += attitudeDelta.coeffs() * 0.5 * dt_sec;
568 Eigen::Vector3d Fspecific = std::accumulate(&Fmotors[0], &Fmotors[5], Faero) /
params_.
mass;
593 Eigen::VectorXd& polynomialCoeffs)
const{
597 Eigen::VectorXd& polynomialCoeffs)
const{
601 Eigen::VectorXd& polynomialCoeffs)
const{
605 Eigen::VectorXd& polynomialCoeffs)
const{
609 Eigen::VectorXd& polynomialCoeffs)
const{
613 Eigen::VectorXd& polynomialCoeffs)
const{
634 const Eigen::Vector3d& moment,
635 const Eigen::Vector3d& prevAngVel)
const{
636 return inertia.inverse() * (moment - prevAngVel.cross(inertia * prevAngVel));
663 Eigen::Vector3d& gyroOutFrd){
673 Eigen::Quaterniond imuOrient(1, 0, 0, 0);
674 accOutFrd = imuOrient.inverse() * specificForce +
params_.
accelBias + accNoise;
675 gyroOutFrd = imuOrient.inverse() * angularVelocity +
params_.
gyroBias + gyroNoise;
682 double windVariance){
Eigen::Matrix< double, 3, 3, Eigen::RowMajor > inertia
double calculateCSRudder(double rudder_pos, double airspeed) const
const Forces & getForces() const
Eigen::Matrix< double, 8, 20, Eigen::RowMajor > CS_rudder
std::vector< double > mapCmdToActuatorStandardVTOL(const std::vector< double > &cmd) const
Eigen::Matrix< double, 8, 20, Eigen::RowMajor > CmzRudder
Eigen::Vector3d getBodyLinearVelocity() const
void setInitialVelocity(const Eigen::Vector3d &linearVelocity, const Eigen::Vector3d &angularVelocity)
std::vector< double > mapCmdToActuatorInnoVTOL(const std::vector< double > &cmd) const
Eigen::Vector3d getAngularAcceleration() const
#define ROS_WARN_STREAM_THROTTLE(period, args)
double lerp(double a, double b, double f)
Eigen::Matrix< double, 8, 8, Eigen::RowMajor > CLPolynomial
int8_t init() override
Use rosparam here to initialize sim.
Eigen::MatrixXd getTableNew(const std::string &path, const char *name)
Eigen::Quaterniond initialAttitude
void calculateCDPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
Eigen::Matrix< double, 8, 8, Eigen::RowMajor > CmxPolynomial
Eigen::Vector3d windVelocity
Eigen::Vector3d getVehicleVelocity() const override
void calculateCSPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
Eigen::Vector3d angularVel
void setWindParameter(Eigen::Vector3d windMeanVelocity, double wind_velocityVariance)
double calculateCmxAileron(double aileron_pos, double airspeed) const
Eigen::Vector3d linearVel
Eigen::Quaterniond getVehicleAttitude() const override
void calculateCmxPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
double characteristicLength
Eigen::Matrix< double, 90, 1, Eigen::ColMajor > AoS
void updateActuators(std::vector< double > &cmd, double dtSecs)
size_t findPrevRowIdxInMonotonicSequence(const Eigen::MatrixXd &matrix, double key)
Given monotonic sequence (increasing or decreasing) and key, return the index of the previous element...
Eigen::Vector3d accelBias
void getIMUMeasurement(Eigen::Vector3d &accOut, Eigen::Vector3d &gyroOut) override
Eigen::Vector3d angularAccel
std::normal_distribution< double > distribution_
void loadTables(const std::string &path)
double calculateCSBeta(double AoS_deg, double airspeed) const
Eigen::Matrix< double, 8, 8, Eigen::RowMajor > CmzPolynomial
Eigen::Matrix< double, 8, 1, Eigen::ColMajor > airspeed
void thruster(double actuator, double &thrust, double &torque, double &rpm) const
double polyval(const Eigen::VectorXd &poly, double val)
std::array< double, 5 > motorsRpm
Eigen::Vector3d calculateWind()
Eigen::Matrix< double, 40, 5, Eigen::RowMajor > prop
Eigen::Vector3d calculateAirSpeed(const Eigen::Matrix3d &rotationMatrix, const Eigen::Vector3d &estimatedVelocity, const Eigen::Vector3d &windSpeed) const
std::vector< double > prevActuators
Eigen::Matrix< double, 1, 47, Eigen::RowMajor > AoA
double calculateAnglesOfSideslip(const Eigen::Vector3d &airSpeed) const
ROSCPP_DECL bool get(const std::string &key, std::string &s)
double calculateCmyElevator(double elevator_pos, double airspeed) const
const Moments & getMoments() const
double griddata(const Eigen::MatrixXd &x, const Eigen::MatrixXd &y, const Eigen::MatrixXd &z, double x_val, double y_val)
void calculateAerodynamics(const Eigen::Vector3d &airspeed, double AoA, double AoS, double aileron_pos, double elevator_pos, double rudder_pos, Eigen::Vector3d &Faero, Eigen::Vector3d &Maero)
Eigen::Matrix3d calculateRotationMatrix() const
std::array< Eigen::Vector3d, 5 > motors
Eigen::Vector3d getVehicleAngularVelocity() const override
Eigen::Quaterniond attitude
Eigen::Vector3d getVehiclePosition() const override
bool calculatePolynomial(const Eigen::MatrixXd &table, double airSpeedMod, Eigen::VectorXd &polynomialCoeffs)
Eigen::Matrix< double, 8, 20, Eigen::RowMajor > CmyElevator
void calculateNewState(const Eigen::Vector3d &Maero, const Eigen::Vector3d &Faero, const std::vector< double > &actuator, double dt_sec)
Eigen::Matrix< double, 8, 8, Eigen::RowMajor > CmyPolynomial
void calculateCLPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
Eigen::Matrix< double, 8, 6, Eigen::RowMajor > CDPolynomial
Eigen::Matrix< double, 8, 20, Eigen::RowMajor > CmxAileron
Eigen::Vector3d getLinearAcceleration() const
int8_t calibrate(SimMode_t calibrationType) override
Eigen::Vector3d initialPose
std::vector< double > actuatorMin
Eigen::Matrix< double, 20, 1, Eigen::ColMajor > actuator
double calculateCmzRudder(double rudder_pos, double airspeed) const
void calculateCmzPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
std::array< Eigen::Vector3d, 5 > motors
Eigen::Vector3d calculateAngularAccel(const Eigen::Matrix< double, 3, 3, Eigen::RowMajor > &inertia, const Eigen::Vector3d &moment, const Eigen::Vector3d &prevAngVel) const
void calculateCmyPolynomial(double airSpeedMod, Eigen::VectorXd &polynomialCoeffs) const
void loadParams(const std::string &path)
Eigen::Matrix< double, 8, 90, Eigen::RowMajor > CS_beta
bool getMotorsRpm(std::vector< double > &motorsRpm) override
double calculateDynamicPressure(double airSpeedMod) const
std::vector< double > crntActuators
Eigen::Vector3d linearAccel
std::vector< double > actuatorTimeConstants
void process(double dt_secs, const std::vector< double > &motorSpeedCommandIn, bool isCmdPercent) override
Eigen::Vector3d calculateNormalForceWithoutMass() const
void setInitialPosition(const Eigen::Vector3d &position, const Eigen::Quaterniond &attitude) override
Eigen::Matrix< double, 8, 8, Eigen::RowMajor > CSPolynomial
Eigen::Vector3d bodylinearVel
std::array< Eigen::Vector3d, 5 > propellersLocation
std::vector< double > actuatorMax
std::default_random_engine generator_
double calculateAnglesOfAtack(const Eigen::Vector3d &airSpeed) const