Files
allwpilib/wpilibc/src/main/native/cpp/ExpansionHubServo.cpp

122 lines
3.6 KiB
C++
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
2025-11-07 19:56:21 -05:00
#include "wpi/ExpansionHubServo.hpp"
2025-11-07 19:56:21 -05:00
#include "wpi/system/Errors.hpp"
#include "wpi/system/SystemServer.hpp"
2025-11-07 20:00:05 -05:00
using namespace wpi;
ExpansionHubServo::ExpansionHubServo(int usbId, int channel)
: m_hub{usbId}, m_channel{channel} {
2025-11-07 20:00:43 -05:00
WPILIB_AssertMessage(channel >= 0 && channel < ExpansionHub::NumServoPorts,
"ExHub Servo Channel {} out of range", channel);
if (!m_hub.CheckAndReserveServo(channel)) {
2025-11-07 20:00:43 -05:00
throw WPILIB_MakeError(err::ResourceAlreadyAllocated, "Channel {}", channel);
}
m_hub.ReportUsage(fmt::format("ExHubServo[{}]", channel), "ExHubServo");
auto systemServer = SystemServer::GetSystemServer();
2025-11-07 20:00:05 -05:00
wpi::nt::PubSubOptions options;
options.sendAll = true;
options.keepDuplicates = true;
options.periodic = 0.005;
m_pulseWidthPublisher =
systemServer
.GetIntegerTopic(
fmt::format("/rhsp/{}/servo{}/pulseWidth", usbId, channel))
.Publish(options);
m_pulseWidthPublisher.Set(1500);
m_framePeriodPublisher =
systemServer
.GetIntegerTopic(
fmt::format("/rhsp/{}/servo{}/framePeriod", usbId, channel))
.Publish(options);
m_framePeriodPublisher.Set(20000);
m_enabledPublisher = systemServer
.GetBooleanTopic(fmt::format(
"/rhsp/{}/servo{}/enabled", usbId, channel))
.Publish(options);
}
ExpansionHubServo::~ExpansionHubServo() noexcept {
m_hub.UnreserveServo(m_channel);
}
void ExpansionHubServo::Set(double value) {
if (m_continousMode) {
value = std::clamp(value, -1.0, 1.0);
value = (value + 1.0) / 2.0;
}
value = std::clamp(value, 0.0, 1.0);
if (m_reversed) {
value = 1.0 - value;
}
auto rawValue = ((value * GetFullRangeScaleFactor()) + m_minPwm);
SetPulseWidth(rawValue);
}
2025-11-07 20:00:05 -05:00
void ExpansionHubServo::SetAngle(wpi::units::degree_t angle) {
angle = std::clamp(angle, m_minServoAngle, m_maxServoAngle);
// NOLINTNEXTLINE(bugprone-integer-division)
Set((angle - m_minServoAngle) / GetServoAngleRange());
}
2025-11-07 20:00:05 -05:00
void ExpansionHubServo::SetPulseWidth(wpi::units::microsecond_t pulseWidth) {
m_pulseWidthPublisher.Set(pulseWidth.to<double>());
}
void ExpansionHubServo::SetEnabled(bool enabled) {
m_enabledPublisher.Set(enabled);
}
2025-11-07 20:00:05 -05:00
void ExpansionHubServo::SetFramePeriod(wpi::units::microsecond_t framePeriod) {
m_framePeriodPublisher.Set(framePeriod.to<double>());
}
2025-11-07 20:00:05 -05:00
wpi::units::microsecond_t ExpansionHubServo::GetFullRangeScaleFactor() {
return m_maxPwm - m_minPwm;
}
2025-11-07 20:00:05 -05:00
wpi::units::degree_t ExpansionHubServo::GetServoAngleRange() {
return m_maxServoAngle - m_minServoAngle;
}
2025-11-07 20:00:05 -05:00
void ExpansionHubServo::SetPWMRange(wpi::units::microsecond_t minPwm,
wpi::units::microsecond_t maxPwm) {
if (maxPwm <= minPwm) {
2025-11-07 20:00:43 -05:00
throw WPILIB_MakeError(err::ParameterOutOfRange,
"Max PWM must be greater than Min PWM");
}
m_minPwm = minPwm;
m_maxPwm = maxPwm;
}
void ExpansionHubServo::SetReversed(bool reversed) {}
2025-11-07 20:00:05 -05:00
void ExpansionHubServo::SetAngleRange(wpi::units::degree_t minAngle,
wpi::units::degree_t maxAngle) {
if (maxAngle <= minAngle) {
2025-11-07 20:00:43 -05:00
throw WPILIB_MakeError(err::ParameterOutOfRange,
"Max angle must be greater than Min angle");
}
m_minServoAngle = minAngle;
m_maxServoAngle = maxAngle;
}
void ExpansionHubServo::SetContinousRotationMode(bool enable) {
m_continousMode = enable;
}