owned this note
owned this note
Published
Linked with GitHub
###### tags: `程式組教程`
# Mecanum Drive Kinematics
The **MecanumDriveKinematics** class 45 is a useful tool that ==converts== between a **ChassisSpeeds** object and a **MecanumDriveWheelSpeeds** object, which contains ==velocities== for each of the four wheels on a mecanum drive.
---
:::spoiler Chinese
> converts ➨ 轉換
> velocities ➨ 速度
:::
---
# ==Constructing== the Kinematics Object
The **MecanumDriveKinematics** class accepts four ==constructor== ==arguments==, with each argument being the location of a wheel relative to the robot center(as a **Translation2d**). The ==order== for the arguments is front left, front right, back left, and back right. The locations for the wheels must be ==relative to== the center of the robot. Positive x values ==represent== moving toward the front of the robot ==whereas== positive y values ==represent== moving toward the left of the robot.
---
:::spoiler Chinese
> Constructing ➨ 建構
> constructor ➨ 構造函數
> arguments ➨ 參數
> order ➨ 指令
> relative to ➨ 關係到;連接到
> represent ➨ 代表
> whereas ➨ 然而
>
:::
---
==**API**==
```
Constructor and Description:
Translation2d( double x, double y )
Explanation:
The X and Y values are derived from
their respective relative distances from the chassis
i.e. Assume the center of the site as the origin
----------
Constructor:
MecanumDriveKinematics(
Translation2d frontLeftWheelMeters,
Translation2d frontRightWheelMeters,
Translation2d rearLeftWheelMeters,
Translation2d rearRightWheelMeters
)
Description:
Constructs a mecanum drive kinematics object.
```
==**JAVA**==
```java=
// Locations of the wheels relative to the robot center.
Translation2d m_frontLeftLocation = new Translation2d(0.381, 0.381);
Translation2d m_frontRightLocation = new Translation2d(0.381, -0.381);
Translation2d m_backLeftLocation = new Translation2d(-0.381, 0.381);
Translation2d m_backRightLocation = new Translation2d(-0.381, -0.381);
// Creating my kinematics object using the wheel locations.
MecanumDriveKinematics m_kinematics = new MecanumDriveKinematics(
m_frontLeftLocation,
m_frontRightLocation,
m_backLeftLocation,
m_backRightLocation
);
```
==**C++**==
```cpp=
// Locations of the wheels relative to the robot center.
frc::Translation2d m_frontLeftLocation{0.381_m, 0.381_m};
frc::Translation2d m_frontRightLocation{0.381_m, -0.381_m};
frc::Translation2d m_backLeftLocation{-0.381_m, 0.381_m};
frc::Translation2d m_backRightLocation{-0.381_m, -0.381_m};
// Creating my kinematics object using the wheel locations.
frc::MecanumDriveKinematics m_kinematics{
m_frontLeftLocation,
m_frontRightLocation,
m_backLeftLocation,
m_backRightLocation
};
```
# Converting Chassis Speeds to Wheel Speeds
The **toWheelSpeeds(ChassisSpeeds speed)**(Java) / **ToWheelSpeeds(ChassisSpeeds speeds)** (C++) method should be used to ==convert== a **ChassisSpeeds** object to a **MecanumDriveWheelSpeeds** object. This is useful in ==situations== where you have to convert a forward velocity, sideways velocity, and an ==angular velocity== into ==individual== wheel speeds.
---
:::spoiler Chinese
> convert ➨ 改變;轉變
> situations ➨ 情況
> angular velocity ➨ 角速度
> individual ➨ 單一的
:::
---
==**API**==
```
Constructor:
ChassisSpeeds(
double vxMetersPerSecond,
double vyMetersPerSecond,
double omegaRadiansPerSecond
)
Description:
Constructs a ChassisSpeeds object.
```
==**JAVA**==
```java=
// Example chassis speeds:
// 1 meter per second forward, 3 meters per second to the left,
// and rotation at 1.5 radians per second counterclockwise.
ChassisSpeeds speeds = new ChassisSpeeds(1.0, 3.0, 1.5);
// Convert to wheel speeds
MecanumDriveWheelSpeeds wheelSpeeds = kinematics.toWheelSpeeds(speeds);
// Get the individual wheel speeds
double frontLeft = wheelSpeeds.frontLeftMetersPerSecond
double frontRight = wheelSpeeds.frontRightMetersPerSecond
double backLeft = wheelSpeeds.rearLeftMetersPerSecond
double backRight = wheelSpeeds.rearRightMetersPerSecond
```
==**C++**==
```cpp=
// Example chassis speeds:
// 1 meter per second forward, 3 meters per second to the left,
// and rotation at 1.5 radians per second counterclockwise.
frc::ChassisSpeeds speeds{ 1_mps, 3_mps, 1.5_rad_per_s };
// Convert to wheel speeds.
// Here, we can use C++17's structuredbindings feature
// to automatically split up the MecanumDriveWheelSpeeds
// struct into it's individual components
auto [fl, fr, bl, br] = kinematics.ToWheelSpeeds(speeds);
```
# Field-oriented drive
[Recall](https://hackmd.io/@FRC-7130-4th/rkgRtJHeq) that a **ChassisSpeeds** object can be created from a set of ==desired== ==field-oriented== speeds. This feature can be used to get wheel speeds from ==a set of== desired field-oriented speeds.
---
:::spoiler Chinese
> desired ➨ 所需的
> field-oriented ➨ 向量控制
> a set of ➨ 一系列的
:::
---
==**API**==
```
Modifier and Type:
static ChassisSpeeds
Method:
fromFieldRelativeSpeeds(
double vxMetersPerSecond,
double vyMetersPerSecond,
double omegaRadiansPerSecond,
Rotation2d robotAngle
)
Description:
Constructs a ChassisSpeeds object.
```
==**JAVA**==
```java=
// The desired field relative speed here is:
// 2 meters per second toward the opponent's alliance station wall,
// and 2 meters per second toward the left field boundary.
// The desired rotation is
// a quarter of a rotation per second counterclockwise.
// The current robot angle is 45 degrees.
ChassisSpeeds speeds = ChassisSpeeds.fromFieldRelativeSpeeds(
2.0, 2.0, Math.PI / 2.0, Rotation2d.fromDegrees(45.0));
// Now use this in our kinematics
MecanumDriveWheelSpeeds wheelSpeeds = kinematics.toWheelSpeeds(speeds);
```
==**C++**==
```cpp=
// The desired field relative speed here is:
// 2 meters per second toward the opponent's alliance station wall,
// and 2 meters per second toward the left field boundary.
// The desired rotation is
// a quarter of a rotation per second counterclockwise.
// The current robot angle is 45 degrees.
frc::ChassisSpeeds speeds = frc::ChassisSpeeds::FromFieldRelativeSpeeds(
2_mps, 2_mps,
units::radians_per_second_t(wpi::math::pi / 2.0),
Rotation2d(45_deg)
);
// Now use this in our kinematics
auto [fl, fr, bl, br] = kinematics.ToWheelSpeeds(speeds);
```
# Using custom centers of rotation
Sometimes, ==rotating== around one ==specific== corner might be ==desirable== for certain ==evasive maneuvers==. This type of ==behavior== is also ==supported by== the WPILib classes. The same **ToWheelSpeeds()** method accepts a second ==parameter== for the center of rotation (as a **Translation2d**). Just like the wheel locations, the **Translation2d** ==representing== the center of ==rotation== should be ==relative to== the robot center.
:::info
**Note:**
Because all robots are a ==rigid frame==, the ==provided== **vx** and **vy** velocities from the **ChassisSpeeds** object will still ==apply for== the ==entirety== of the robot. However, the **omega** from the **ChassisSpeeds** object will be measured from the center of rotation.
:::
For example, one can set the center of rotation on a certain wheel and if the ==provided== **ChassisSpeeds** object has a **vx** and **vy** of zero and a ==non-zero== **omega**, the robot will ==appear to== rotate around that ==particular== wheel.
---
:::spoiler Chinese
> rotating ➨ 旋轉
> specific ➨ 特定的
> desirable ➨ 可取的
> evasive maneuvers ➨ 規避動作
> behavior ➨ 行為
> supported by ➨ 支持
> parameter ➨ 範圍
> representing ➨ 代表
> rotation ➨ 旋轉
> relative to ➨ 相對於
> rigid frame ➨ 難以調整的框架
> provided ➨ 提供
> apply for ➨ 適用於
> entirety ➨ 整體的;整個的
> provided ➨ 提供
> non-zero ➨ 非零的
> appear to ➨ 可能
> particular ➨ 特定的
:::
---
# Converting wheel speeds to chassis speeds
One can also use the kinematics object to convert a **MecanumDriveWheelSpeeds** object to a ==singular== **ChassisSpeeds** object. The **toChassisSpeeds(MecanumDriveWheelSpeeds speeds)** (Java) / **ToChassisSpeeds(MecanumDriveWheelSpeeds speeds)** (C++) method can be used to ==achieve== this.
---
:::spoiler Chinese
> singular ➨ 單數的
> achieve ➨ 實現
:::
---
==**API**==
```
Constructor:
MecanumDriveWheelSpeeds(
frontLeftMetersPerSecond,
frontRightMetersPerSecond,
rearLeftMetersPerSecond,
rearRightMetersPerSecond
)
```
==**JAVA**==
```java=
// Example wheel speeds
var wheelSpeeds = new MecanumDriveWheelSpeeds(-17.67, 20.51, -13.44, 16.26);
// Convert to chassis speeds
ChassisSpeeds chassisSpeeds = kinematics.toChassisSpeeds(wheelSpeeds);
// Getting individual speeds
double forward = chassisSpeeds.vxMetersPerSecond;
double sideways = chassisSpeeds.vyMetersPerSecond;
double angular = chassisSpeeds.omegaRadiansPerSecond;
```
==**C++**==
```cpp=
// Example wheel speeds
frc::MecanumDriveWheelSpeeds wheelSpeeds{
-17.67_mps,
20.51_mps,
-13.44_mps,
16.26_mps
};
// Convert to chassis speeds. Here, we can use C++17's structured bindings
// feature to automatically break up the ChassisSpeeds struct into its
// three components.
auto [forward, sideways, angular] = kinematics.ToChassisSpeeds(wheelSpeeds);
```
# Original link and Reference website
* [FRC Official - Mecanum Drive Kinematics](https://docs.wpilib.org/en/stable/docs/software/kinematics-and-odometry/mecanum-drive-kinematics.html)
* [API - Translation2d](https://www.team2052.com/KnightLib/index.html?com/first/team2052/lib/vec/Translation2d.html)
* [API - ChassisSpeeds](https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/math/kinematics/ChassisSpeeds.html)
* [API - MecanumDriveKinematics](https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/math/kinematics/MecanumDriveKinematics.html)
* [Hackmd(Moyu) - Introduction to Kinematics and The Chassis Speeds Class](https://hackmd.io/@Mo-Yu/HJfJHxZxc)
* [Hackmd(7130) - Introduction to Kinematics and The Chassis Speeds Class](https://hackmd.io/@FRC-7130-4th/rkgRtJHeq)