/*----------------------------------------------------------------------------*/ /* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ /*----------------------------------------------------------------------------*/ #include "frc/drive/MecanumDrive.h" #include #include #include #include #include "frc/SpeedController.h" #include "frc/drive/Vector2d.h" #include "frc/smartdashboard/SendableBuilder.h" #include "frc/smartdashboard/SendableRegistry.h" using namespace frc; MecanumDrive::MecanumDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor, SpeedController& frontRightMotor, SpeedController& rearRightMotor) : m_frontLeftMotor(frontLeftMotor), m_rearLeftMotor(rearLeftMotor), m_frontRightMotor(frontRightMotor), m_rearRightMotor(rearRightMotor) { auto& registry = SendableRegistry::GetInstance(); registry.AddChild(this, &m_frontLeftMotor); registry.AddChild(this, &m_rearLeftMotor); registry.AddChild(this, &m_frontRightMotor); registry.AddChild(this, &m_rearRightMotor); static int instances = 0; ++instances; registry.AddLW(this, "MecanumDrive", instances); } void MecanumDrive::DriveCartesian(double ySpeed, double xSpeed, double zRotation, double gyroAngle) { if (!reported) { HAL_Report(HALUsageReporting::kResourceType_RobotDrive, HALUsageReporting::kRobotDrive2_MecanumCartesian, 4); reported = true; } ySpeed = std::clamp(ySpeed, -1.0, 1.0); ySpeed = ApplyDeadband(ySpeed, m_deadband); xSpeed = std::clamp(xSpeed, -1.0, 1.0); xSpeed = ApplyDeadband(xSpeed, m_deadband); // Compensate for gyro angle. Vector2d input{ySpeed, xSpeed}; input.Rotate(-gyroAngle); double wheelSpeeds[4]; wheelSpeeds[kFrontLeft] = input.x + input.y + zRotation; wheelSpeeds[kFrontRight] = -input.x + input.y - zRotation; wheelSpeeds[kRearLeft] = -input.x + input.y + zRotation; wheelSpeeds[kRearRight] = input.x + input.y - zRotation; Normalize(wheelSpeeds); m_frontLeftMotor.Set(wheelSpeeds[kFrontLeft] * m_maxOutput); m_frontRightMotor.Set(wheelSpeeds[kFrontRight] * m_maxOutput * m_rightSideInvertMultiplier); m_rearLeftMotor.Set(wheelSpeeds[kRearLeft] * m_maxOutput); m_rearRightMotor.Set(wheelSpeeds[kRearRight] * m_maxOutput * m_rightSideInvertMultiplier); Feed(); } void MecanumDrive::DrivePolar(double magnitude, double angle, double zRotation) { if (!reported) { HAL_Report(HALUsageReporting::kResourceType_RobotDrive, HALUsageReporting::kRobotDrive2_MecanumPolar, 4); reported = true; } DriveCartesian(magnitude * std::sin(angle * (wpi::math::pi / 180.0)), magnitude * std::cos(angle * (wpi::math::pi / 180.0)), zRotation, 0.0); } bool MecanumDrive::IsRightSideInverted() const { return m_rightSideInvertMultiplier == -1.0; } void MecanumDrive::SetRightSideInverted(bool rightSideInverted) { m_rightSideInvertMultiplier = rightSideInverted ? -1.0 : 1.0; } void MecanumDrive::StopMotor() { m_frontLeftMotor.StopMotor(); m_frontRightMotor.StopMotor(); m_rearLeftMotor.StopMotor(); m_rearRightMotor.StopMotor(); Feed(); } void MecanumDrive::GetDescription(wpi::raw_ostream& desc) const { desc << "MecanumDrive"; } void MecanumDrive::InitSendable(SendableBuilder& builder) { builder.SetSmartDashboardType("MecanumDrive"); builder.SetActuator(true); builder.SetSafeState([=] { StopMotor(); }); builder.AddDoubleProperty("Front Left Motor Speed", [=]() { return m_frontLeftMotor.Get(); }, [=](double value) { m_frontLeftMotor.Set(value); }); builder.AddDoubleProperty( "Front Right Motor Speed", [=]() { return m_frontRightMotor.Get() * m_rightSideInvertMultiplier; }, [=](double value) { m_frontRightMotor.Set(value * m_rightSideInvertMultiplier); }); builder.AddDoubleProperty("Rear Left Motor Speed", [=]() { return m_rearLeftMotor.Get(); }, [=](double value) { m_rearLeftMotor.Set(value); }); builder.AddDoubleProperty( "Rear Right Motor Speed", [=]() { return m_rearRightMotor.Get() * m_rightSideInvertMultiplier; }, [=](double value) { m_rearRightMotor.Set(value * m_rightSideInvertMultiplier); }); }