From 1069019fd2f99bad702da89ce47980c2f8e518a0 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Fri, 23 Oct 2020 20:18:49 -0700 Subject: [PATCH] [wpilib] Add DutyCycleEncoderSim (#2798) --- .../src/main/native/cpp/DutyCycleEncoder.cpp | 7 +++ .../cpp/simulation/DutyCycleEncoderSim.cpp | 33 +++++++++++++ .../native/include/frc/DutyCycleEncoder.h | 8 +++ .../frc/simulation/DutyCycleEncoderSim.h | 49 +++++++++++++++++++ .../wpi/first/wpilibj/DutyCycleEncoder.java | 15 ++++++ .../simulation/DutyCycleEncoderSim.java | 46 +++++++++++++++++ 6 files changed, 158 insertions(+) create mode 100644 wpilibc/src/main/native/cpp/simulation/DutyCycleEncoderSim.cpp create mode 100644 wpilibc/src/main/native/include/frc/simulation/DutyCycleEncoderSim.h create mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/DutyCycleEncoderSim.java diff --git a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp index 03224ab282..2028a9f27d 100644 --- a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp +++ b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp @@ -58,6 +58,8 @@ void DutyCycleEncoder::Init() { if (m_simDevice) { m_simPosition = m_simDevice.CreateDouble("Position", false, 0.0); + m_simDistancePerRotation = + m_simDevice.CreateDouble("DistancePerRotation", false, 1.0); m_simIsConnected = m_simDevice.CreateBoolean("Connected", false, true); } else { m_analogTrigger = std::make_unique(m_dutyCycle.get()); @@ -98,6 +100,7 @@ units::turn_t DutyCycleEncoder::Get() const { void DutyCycleEncoder::SetDistancePerRotation(double distancePerRotation) { m_distancePerRotation = distancePerRotation; + m_simDistancePerRotation.Set(distancePerRotation); } double DutyCycleEncoder::GetDistancePerRotation() const { @@ -129,6 +132,10 @@ void DutyCycleEncoder::SetConnectedFrequencyThreshold(int frequency) { m_frequencyThreshold = frequency; } +int DutyCycleEncoder::GetSourceChannel() const { + return m_dutyCycle->GetSourceChannel(); +} + void DutyCycleEncoder::InitSendable(SendableBuilder& builder) { builder.SetSmartDashboardType("AbsoluteEncoder"); builder.AddDoubleProperty( diff --git a/wpilibc/src/main/native/cpp/simulation/DutyCycleEncoderSim.cpp b/wpilibc/src/main/native/cpp/simulation/DutyCycleEncoderSim.cpp new file mode 100644 index 0000000000..dd1c6c3cba --- /dev/null +++ b/wpilibc/src/main/native/cpp/simulation/DutyCycleEncoderSim.cpp @@ -0,0 +1,33 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 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/simulation/DutyCycleEncoderSim.h" + +#include +#include + +#include "frc/DutyCycleEncoder.h" +#include "frc/simulation/SimDeviceSim.h" + +using namespace frc::sim; + +DutyCycleEncoderSim::DutyCycleEncoderSim(const frc::DutyCycleEncoder& encoder) { + wpi::SmallString<128> fullname; + wpi::raw_svector_ostream os(fullname); + os << "DutyCycleEncoder" << '[' << encoder.GetSourceChannel() << ']'; + frc::sim::SimDeviceSim deviceSim{fullname.c_str()}; + m_simPosition = deviceSim.GetDouble("Position"); + m_simDistancePerRotation = deviceSim.GetDouble("DistancePerRotation"); +} + +void DutyCycleEncoderSim::Set(units::turn_t turns) { + m_simPosition.Set(turns.to()); +} + +void DutyCycleEncoderSim::SetDistance(double distance) { + m_simPosition.Set(distance / m_simDistancePerRotation.Get()); +} diff --git a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h index 73db9bb99d..e9d4f44bb2 100644 --- a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h +++ b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h @@ -154,6 +154,13 @@ class DutyCycleEncoder : public ErrorBase, */ double GetDistance() const; + /** + * Get the channel of the source. + * + * @return the source channel + */ + int GetSourceChannel() const; + void InitSendable(SendableBuilder& builder) override; private: @@ -169,6 +176,7 @@ class DutyCycleEncoder : public ErrorBase, hal::SimDevice m_simDevice; hal::SimDouble m_simPosition; + hal::SimDouble m_simDistancePerRotation; hal::SimBoolean m_simIsConnected; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/simulation/DutyCycleEncoderSim.h b/wpilibc/src/main/native/include/frc/simulation/DutyCycleEncoderSim.h new file mode 100644 index 0000000000..5d9a039111 --- /dev/null +++ b/wpilibc/src/main/native/include/frc/simulation/DutyCycleEncoderSim.h @@ -0,0 +1,49 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 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. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +namespace frc { + +class DutyCycleEncoder; + +namespace sim { + +/** + * Class to control a simulated duty cycle encoder. + */ +class DutyCycleEncoderSim { + public: + /** + * Constructs from a DutyCycleEncoder object. + * + * @param dutyCycleEncoder DutyCycleEncoder to simulate + */ + explicit DutyCycleEncoderSim(const DutyCycleEncoder& encoder); + + /** + * Set the position tin turns. + * + * @param turns The position. + */ + void Set(units::turn_t turns); + + /** + * Set the position. + */ + void SetDistance(double distance); + + private: + hal::SimDouble m_simPosition; + hal::SimDouble m_simDistancePerRotation; +}; + +} // namespace sim +} // namespace frc diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java index 07b2878908..dc6d5c7152 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java @@ -32,6 +32,7 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { protected SimDevice m_simDevice; protected SimDouble m_simPosition; + protected SimDouble m_simDistancePerRotation; protected SimBoolean m_simIsConnected; /** @@ -72,6 +73,7 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { if (m_simDevice != null) { m_simPosition = m_simDevice.createDouble("Position", false, 0.0); + m_simDistancePerRotation = m_simDevice.createDouble("DistancePerRotation", false, 1.0); m_simIsConnected = m_simDevice.createBoolean("Connected", false, true); } else { m_counter = new Counter(); @@ -140,6 +142,10 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { */ public void setDistancePerRotation(double distancePerRotation) { m_distancePerRotation = distancePerRotation; + + if (m_simDistancePerRotation != null) { + m_simDistancePerRotation.set(distancePerRotation); + } } /** @@ -230,6 +236,15 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { } } + /** + * Get the channel of the source. + * + * @return the source channel + */ + public int getSourceChannel() { + return m_dutyCycle.getSourceChannel(); + } + @Override public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("AbsoluteEncoder"); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/DutyCycleEncoderSim.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/DutyCycleEncoderSim.java new file mode 100644 index 0000000000..c7842f16b1 --- /dev/null +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/DutyCycleEncoderSim.java @@ -0,0 +1,46 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 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. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.simulation; + +import edu.wpi.first.hal.SimDouble; +import edu.wpi.first.wpilibj.DutyCycleEncoder; + +/** + * Class to control a simulated duty cycle encoder. + */ +public class DutyCycleEncoderSim { + private final SimDouble m_simPosition; + private final SimDouble m_simDistancePerRotation; + + /** + * Constructs from an DutyCycleEncoder object. + * + * @param encoder DutyCycleEncoder to simulate + */ + public DutyCycleEncoderSim(DutyCycleEncoder encoder) { + SimDeviceSim wrappedSimDevice = new SimDeviceSim("DutyCycleEncoder" + "[" + encoder.getSourceChannel() + "]"); + m_simPosition = wrappedSimDevice.getDouble("Position"); + m_simDistancePerRotation = wrappedSimDevice.getDouble("DistancePerRotation"); + } + + /** + * Set the position in turns. + * + * @param turns The position. + */ + public void set(double turns) { + m_simPosition.set(turns); + } + + /** + * Set the position. + */ + public void setDistance(double distance) { + m_simPosition.set(distance / m_simDistancePerRotation.get()); + } +}