一、AirSim没有直接获取无人机物理参数的API
AirSim 是微软开源的一个跨平台的建立在虚幻引擎(Unreal Engine)上的无人机以及其它自主移动设备的模拟器。
AirSim为开发者提供了一定数量的API(Application Programming Interface,应用程序编程接口)以供使用者迅速快捷进行仿真实验。
然而,AirSim中没有用于获取无人机物理参数,包括质量、尺寸、惯性矩阵等的API,考虑到在相当多的仿真情境下,使用者需要获取以及修改无人机物理参数,因此本文介绍一种获取无人机物理参数的方法,与大家交流,如有错误,欢迎大家批评指正。
二、Airsim源码中各参数的位置
为了获取无人机相关物理参数,需要查阅AirSim源码中的MultiRotorParameters.hpp文件,其路径为
AirLib/include/vehicles/multirotor/MultiRotorParams.hpp
该文件中,给出了包括四旋翼、六旋翼、八旋翼无人机以及轮式机器人的相关参数,我们以四旋翼无人机为例,相关代码为
void setupFrameGenericQuad(Params& params)
{
//set up arm lengths
//dimensions are for F450 frame: http://artofcircuits.com/product/quadcopter-frame-hj450-with-power-distribution
params.rotor_count = 4;
std::vector<real_T> arm_lengths(params.rotor_count, 0.2275f);
//set up mass
//this has to be between max_thrust*rotor_count/10 (1.6kg using default parameters in RotorParams.hpp) and (idle throttle percentage)*max_thrust*rotor_count/10 (0.8kg using default parameters and SimpleFlight)
//any value above the maximum would result in the motors not being able to lift the body even at max thrust,
//and any value below the minimum would cause the drone to fly upwards on idling throttle (50% of the max throttle if using SimpleFlight)
//Note that the default idle throttle percentage is 50% if you are using SimpleFlight
params.mass = 1.0f;
real_T motor_assembly_weight = 0.055f; //weight for MT2212 motor for F450 frame
real_T box_mass = params.mass - params.rotor_count * motor_assembly_weight;
// using rotor_param default, but if you want to change any of the rotor_params, call calculateMaxThrust() to recompute the max_thrust
// given new thrust coefficients, motor max_rpm and propeller diameter.
params.rotor_params.calculateMaxThrust();
//set up dimensions of core body box or abdomen (not including arms).
params.body_box.x() = 0.180f;
params.body_box.y() = 0.11f;
params.body_box.z() = 0.040f;
real_T rotor_z = 2.5f / 100;
//computer rotor poses
initializeRotorQuadX(params.rotor_poses, params.rotor_count, arm_lengths.data(), rotor_z);
//compute inertia matrix
computeInertiaMatrix(params.inertia, params.body_box, params.rotor_poses, box_mass, motor_assembly_weight);
}
1、无人机质量
根据代码,四旋翼无人机的质量为1kg,并且注释中提及,四旋翼无人机的质量需要介于0.8kg(使用默认参数时的怠速油门升力)和1.6kg(使用默认参数时的最大升力)之间
2、电机质量和机身质量
四旋翼无人机每个电机的质量为0.055kg,因此机身质量为1kg-4*0.055kg,即0.78kg
3、无人机臂长
四旋翼无人机臂长为0.2275m
4、机身尺寸
机身尺寸为x方向上0.18m,y方向上0.11m,z方向上0.04m,电机平面到无人机质心的距离为0.0025m
5、四旋翼无人机布局与电机旋转方向
代码中给出四旋翼无人机布局为“X”型,注释中也给出了电机旋转方向
protected: //static utility functions for derived classes to use
/// Initializes 4 rotors in the usual QuadX pattern: http://ardupilot.org/copter/_images/MOTORS_QuadX_QuadPlus.jpg
/// which shows that given an array of 4 motors, the first is placed top right and flies counter clockwise (CCW) and
/// the second is placed bottom left, and also flies CCW. The third in the array is placed top left and flies clockwise (CW)
/// while the last is placed bottom right and also flies clockwise. This is how the 4 items in the arm_lengths and
/// arm_angles arrays will be used. So arm_lengths is 4 numbers (in meters) where four arm lengths, 0 is top right,
/// 1 is bottom left, 2 is top left and 3 is bottom right. arm_angles is 4 numbers (in degrees) relative to forward vector (0,1),
/// provided in the same order where 0 is top right, 1 is bottom left, 2 is top left and 3 is bottom right, so for example,
/// the angles for a regular symmetric X pattern would be 45, 225, 315, 135. The rotor_z is the offset of each motor upwards
/// relative to the center of mass (in meters).
static void initializeRotorQuadX(vector<RotorPose>& rotor_poses /* the result we are building */,
uint rotor_count /* must be 4 */,
real_T arm_lengths[],
real_T rotor_z /* z relative to center of gravity */)
{
Vector3r unit_z(0, 0, -1); //NED frame
if (rotor_count == 4) {
rotor_poses.clear();
/* Note: rotor_poses are built in this order:
x-axis
(2) | (0)
|
-------------- y-axis
|
(1) | (3)
*/
// vectors below are rotated according to NED left hand rule (so the vectors are rotated counter clockwise).
Quaternionr quadx_rot(AngleAxisr(M_PIf / 4, unit_z));
rotor_poses.emplace_back(VectorMath::rotateVector(Vector3r(0, arm_lengths[0], rotor_z), quadx_rot, true),
unit_z,
RotorTurningDirection::RotorTurningDirectionCCW);
rotor_poses.emplace_back(VectorMath::rotateVector(Vector3r(0, -arm_lengths[1], rotor_z), quadx_rot, true),
unit_z,
RotorTurningDirection::RotorTurningDirectionCCW);
rotor_poses.emplace_back(VectorMath::rotateVector(Vector3r(arm_lengths[2], 0, rotor_z), quadx_rot, true),
unit_z,
RotorTurningDirection::RotorTurningDirectionCW);
rotor_poses.emplace_back(VectorMath::rotateVector(Vector3r(-arm_lengths[3], 0, rotor_z), quadx_rot, true),
unit_z,
RotorTurningDirection::RotorTurningDirectionCW);
}
else
throw std::invalid_argument("Rotor count other than 4 is not supported by this method!");
}
第一个电机在无人机右前方(序号0),转动方向为逆时针;第二个电机在无人机左后方(序号1),转动方向也为逆时针;第三个电机在无人机左前方(序号2),转动方向为顺时针;第四个电机在无人机右后方(序号3),转动方向为顺时针。
代码中还描述了四个电机的当前位置,是由“十”字型的位置,即电机在机体坐标系中的坐标分别为(0, arm_lengths, rotor_z)、(0, -arm_lengths, rotor_z)、(arm_lengths, 0, rotor_z)和(-arm_lengths, 0, rotor_z),绕z轴逆时针旋转45度得到的。
6、转动惯量矩阵
代码中给出的转动惯量矩阵计算方法为
{
inertia = Matrix3x3r::Zero();
//http://farside.ph.utexas.edu/teaching/336k/Newtonhtml/node64.html
inertia(0, 0) = box_mass / 12.0f * (body_box.y() * body_box.y() + body_box.z() * body_box.z());
inertia(1, 1) = box_mass / 12.0f * (body_box.x() * body_box.x() + body_box.z() * body_box.z());
inertia(2, 2) = box_mass / 12.0f * (body_box.x() * body_box.x() + body_box.y() * body_box.y());
for (size_t i = 0; i < rotor_poses.size(); ++i) {
const auto& pos = rotor_poses.at(i).position;
inertia(0, 0) += (pos.y() * pos.y() + pos.z() * pos.z()) * motor_assembly_weight;
inertia(1, 1) += (pos.x() * pos.x() + pos.z() * pos.z()) * motor_assembly_weight;
inertia(2, 2) += (pos.x() * pos.x() + pos.y() * pos.y()) * motor_assembly_weight;
}
}
其中,总转动惯量为机身转动惯量加四个电机的转动惯量
代入上面的数据,机身转动惯量为:
I_xx = 0.78/12 * (0.11^2 + 0.04^2) = 0.0008905
I_yy = 0.78/12 * (0.18^2 + 0.04^2) = 0.00221
I_yy = 0.78/12 * (0.18^2 + 0.11^2) = 0.0028925
电机产生的转动惯量计算公式中,pos.x()、pos.y()、pos.z()分别表示电机质心到无人机x轴、y轴、z轴的距离,因此电机产生的转动惯量为:
I_xx = 4 * ( 0.2275^2 / 2 + 0.0025^2 ) * 0.055 = 0.0058307
I_yy = 4 * ( 0.2275^2 / 2 + 0.0025^2 ) * 0.055 = 0.0058307
I_zz = 4 * (0.2275^2 / 2 * 2) * 0.055 = 0.0113864
最终,计算得到的转动惯量为机体和电机产生的转动惯量之和,因此默认参数情况下,四旋翼无人机转动惯量为
[I_xx I_yy I_zz] = [0.0067212 0.0080407 0.0142789]
三、声明
上述内容均为个人判断,如果有什么问题,非常欢迎大家在评论区指出问题,以及进行讨论