C++ 单位库

WPILib is coupled with a Units library for C++ teams. This library leverages the C++ type system to enforce proper dimensionality for method parameters, automatically perform unit conversions, and even allow users to define arbitrary defined unit types. Since the C++ type system is enforced at compile-time, the library has essentially no runtime cost.

使用单位库

单位库是仅有标头的库。您必须在源文件中包含要使用的单位的相关标头。下面是可用单位的列表。

#include <units/acceleration.h>
#include <units/angle.h>
#include <units/angular_acceleration.h>
#include <units/angular_velocity.h>
#include <units/area.h>
#include <units/capacitance.h>
#include <units/charge.h>
#include <units/concentration.h>
#include <units/conductance.h>
#include <units/current.h>
#include <units/curvature.h>
#include <units/data.h>
#include <units/data_transfer_rate.h>
#include <units/density.h>
#include <units/dimensionless.h>
#include <units/energy.h>
#include <units/force.h>
#include <units/frequency.h>
#include <units/illuminance.h>
#include <units/impedance.h>
#include <units/inductance.h>
#include <units/length.h>
#include <units/luminous_flux.h>
#include <units/luminous_intensity.h>
#include <units/magnetic_field_strength.h>
#include <units/magnetic_flux.h>
#include <units/mass.h>
#include <units/moment_of_inertia.h>
#include <units/power.h>
#include <units/pressure.h>
#include <units/radiation.h>
#include <units/solid_angle.h>
#include <units/substance.h>
#include <units/temperature.h>
#include <units/time.h>
#include <units/torque.h>
#include <units/velocity.h>
#include <units/voltage.h>
#include <units/volume.h>

“units/math.h” 标头提供了单位感知功能,例如 “units::math::abs()”。

单位类型和容器类型

C ++ 单位库基于两种类型定义 : 单位类型和容器类型。

单位类型

单元类型对应于单元的抽象概念,没有任何实际的存储值。单元类型是单元库的基本“构建块”-所有单元类型都通过少量“基本”单元类型 (例如“ meters”,“ `seconds’等) 在被构造时定义 (通过 “compound_unit” 模版) 。

While unit types cannot contain numerical values, their use in building other unit types means that when a type or method uses a template parameter to specify its dimensionality, that parameter will be a unit type.

容器类型

容器类型对应于根据某个单位确定尺寸的实际数量。也就是说,它们是实际包含数值的内容。容器类型是使用具有 “unit_t” 模板的单元类型构造的。大多数单位类型都有一个对应的容器类型,其名称后缀有 “_t” -例如,单元类型 “units :: meter” 对应于容器类型 “units :: meter_t”。

每当使用特定数量的单位 (作为变量或方法参数) 时,它将是容器类型的实例。默认情况下,容器类型会将实际值存储为 “double” -高级用户可以通过手动调用 “unit_t” 模板来更改此值。

A full list of unit and container types can be found in the documentation.

创建单位的实例

为了创建特定单元的实例,我们需要创建其容器类型的实例:

// The variable speed has a value of 5 meters per second.
units::meters_per_second_t speed{5.0};

Alternatively, the units library has type literals defined for some of the more common container types. These can be used in conjunction with type inference via auto to define a unit more succinctly:

// The variable speed has a value of 5 meters per second.
auto speed = 5_mps;

只要可以在另一个容器类型之间进行转换,单元也可以使用另一个容器类型的值来初始化。例如,可以从 “foot_t” 值创建 “meter_t” 值。

auto feet = 6_ft;
units::meter_t meters{feet};

实际上,代表可转换单位类型的所有容器类型都是 “隐式可转换的” 。因此,以下内容完全合法:

units::meter_t distance = 6_ft;

简而言之,我们可以在代码中的任何位置使用 任意 长度单位代替 任何其他 长度单位;单位库将自动为我们执行正确的转换。

执行含有单位的算术

容器类型支持其基础数据类型的所有普通算术运算,其附加条件是该运算必须是 的。因此,必须始终对两种兼容的容器类型执行添加:

// Add two meter_t values together
auto sum = 5_m + 7_m; // sum is 12_m
// Adds meters to feet; both are length, so this is fine
auto sum = 5_m + 7_ft;
// Tries to add a meter_t to a second_t, will throw a compile-time error
auto sum = 5_m + 7_s;

乘法可以对任何一对容器类型执行,并得出复合单元的容器类型:

备注

When a calculation yields a compound unit type, this type will only be checked for validity at the point of operation if the result type is specified explicitly. If auto is used, this check will not occur. For example, when we divide distance by time, we may want to ensure the result is, indeed, a velocity (i.e. units::meters_per_second_t). If the return type is declared as auto, this check will not be made.

// Multiply two meter_t values, result is square_meter_t
auto product = 5_m * 7_m; // product is 35_sq_m
// Divide a meter_t value by a second_t, result is a meter_per_second_t
units::meters_per_second_t speed = 6_m / 0.5_s; // speed is 12_mps

``<cmath>’’函数

一些 “std” 函数 (例如 clamp ) 被模板化以接受可以在其上执行算术运算的任何类型。以容器类型存储的数量可以使用这些功能而不会出现问题。

但是,其他``std`` 函数仅适用于普通数字类型 (例如 double )。单元库的 units :: math 命名空间包含一些接受单元的函数的包装。此类功能的示例包括 sqrt, pow 等。

auto area = 36_sq_m;
units::meter_t sideLength = units::math::sqrt(area);

去除 Unit Wrapper

To convert a container type to its underlying value, use the value() method. This serves as an escape hatch from the units type system, which should be used only when necessary.

units::meter_t distance = 6.5_m;
double distanceMeters = distance.value();

WPILib 代码中的单位库示例

WPILib 新功能中的函数的几个参数 (例如: kinematics <docs/software/kinematics-and-odometry/intro-and-chassis-speeds:What is kinematics?>) 使用单位库。这是对轨迹 <docs/software/advanced-controls/trajectories/manipulating-trajectories:Sampling the trajectory> 进行采样的示例。

// Sample the trajectory at 1.2 seconds. This represents where the robot
// should be after 1.2 seconds of traversal.
Trajectory::State point = trajectory.Sample(1.2_s);
// Since units of time are implicitly convertible, this is exactly equivalent to the above code
Trajectory::State point = trajectory.Sample(1200_ms);

某些 WPILib 类表示可以自然地与多种单位类型一起使用的对象 -例如,运动曲线可能会在线性距离 (例如米) 或角距离 (例如弧度) 上运行。对于这种类,必须将单位类型作为模板参数:

// Creates a new set of trapezoidal motion profile constraints
// Max velocity of 10 meters per second
// Max acceleration of 20 meters per second squared
frc::TrapezoidProfile<units::meters>::Constraints{10_mps, 20_mps_sq};
// Creates a new set of trapezoidal motion profile constraints
// Max velocity of 10 radians per second
// Max acceleration of 20 radians per second squared
frc::TrapezoidProfile<units::radians>::Constraints{10_rad_per_s, 20__rad_per_s / 1_s};

For more detailed documentation, please visit the official GitHub page for the units library.