From 272eaf184ff3fbb0b4d57009342bb8db0e7e4e1d Mon Sep 17 00:00:00 2001 From: Joshua Shannon Date: Fri, 20 Mar 2020 16:32:52 -0500 Subject: [PATCH] DutyCycleEncoder: Fix simulation support (#2387) The DutyCycleEncoder class initializes AnalogTrigger, which is not supported in simulation. To avoid this, do not use AnalogTrigger (or Counter) in simulation mode. Fixes #2367 Co-authored-by: Peter Johnson --- .../src/main/native/cpp/DutyCycleEncoder.cpp | 50 +++++++------------ .../native/include/frc/DutyCycleEncoder.h | 6 +-- .../wpi/first/wpilibj/DutyCycleEncoder.java | 27 ++++++---- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp index ea054ce790..114b81c2d7 100644 --- a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp +++ b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-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. */ @@ -18,51 +18,37 @@ using namespace frc; DutyCycleEncoder::DutyCycleEncoder(int channel) : m_dutyCycle{std::make_shared( - std::make_shared(channel))}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + std::make_shared(channel))} { Init(); } DutyCycleEncoder::DutyCycleEncoder(DutyCycle& dutyCycle) - : m_dutyCycle{&dutyCycle, NullDeleter{}}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{&dutyCycle, NullDeleter{}} { Init(); } DutyCycleEncoder::DutyCycleEncoder(DutyCycle* dutyCycle) - : m_dutyCycle{dutyCycle, NullDeleter{}}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{dutyCycle, NullDeleter{}} { Init(); } DutyCycleEncoder::DutyCycleEncoder(std::shared_ptr dutyCycle) - : m_dutyCycle{std::move(dutyCycle)}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{std::move(dutyCycle)} { Init(); } DutyCycleEncoder::DutyCycleEncoder(DigitalSource& digitalSource) - : m_dutyCycle{std::make_shared(digitalSource)}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{std::make_shared(digitalSource)} { Init(); } DutyCycleEncoder::DutyCycleEncoder(DigitalSource* digitalSource) - : m_dutyCycle{std::make_shared(digitalSource)}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{std::make_shared(digitalSource)} { Init(); } DutyCycleEncoder::DutyCycleEncoder(std::shared_ptr digitalSource) - : m_dutyCycle{std::make_shared(digitalSource)}, - m_analogTrigger{m_dutyCycle.get()}, - m_counter{} { + : m_dutyCycle{std::make_shared(digitalSource)} { Init(); } @@ -72,14 +58,16 @@ void DutyCycleEncoder::Init() { if (m_simDevice) { m_simPosition = m_simDevice.CreateDouble("Position", false, 0.0); m_simIsConnected = m_simDevice.CreateBoolean("Connected", false, true); + } else { + m_analogTrigger = std::make_unique(m_dutyCycle.get()); + m_analogTrigger->SetLimitsDutyCycle(0.25, 0.75); + m_counter = std::make_unique(); + m_counter->SetUpSource( + m_analogTrigger->CreateOutput(AnalogTriggerType::kRisingPulse)); + m_counter->SetDownSource( + m_analogTrigger->CreateOutput(AnalogTriggerType::kFallingPulse)); } - m_analogTrigger.SetLimitsDutyCycle(0.25, 0.75); - m_counter.SetUpSource( - m_analogTrigger.CreateOutput(AnalogTriggerType::kRisingPulse)); - m_counter.SetDownSource( - m_analogTrigger.CreateOutput(AnalogTriggerType::kFallingPulse)); - SendableRegistry::GetInstance().AddLW(this, "DutyCycle Encoder", m_dutyCycle->GetSourceChannel()); } @@ -90,9 +78,9 @@ units::turn_t DutyCycleEncoder::Get() const { // As the values are not atomic, keep trying until we get 2 reads of the same // value If we don't within 10 attempts, error for (int i = 0; i < 10; i++) { - auto counter = m_counter.Get(); + auto counter = m_counter->Get(); auto pos = m_dutyCycle->GetOutput(); - auto counter2 = m_counter.Get(); + auto counter2 = m_counter->Get(); auto pos2 = m_dutyCycle->GetOutput(); if (counter == counter2 && pos == pos2) { units::turn_t turns{counter + pos - m_positionOffset}; @@ -124,7 +112,7 @@ int DutyCycleEncoder::GetFrequency() const { } void DutyCycleEncoder::Reset() { - m_counter.Reset(); + if (m_counter) m_counter->Reset(); m_positionOffset = m_dutyCycle->GetOutput(); } diff --git a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h index 92864a8ccc..847cd8568d 100644 --- a/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h +++ b/wpilibc/src/main/native/include/frc/DutyCycleEncoder.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-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. */ @@ -160,8 +160,8 @@ class DutyCycleEncoder : public ErrorBase, void Init(); std::shared_ptr m_dutyCycle; - AnalogTrigger m_analogTrigger; - Counter m_counter; + std::unique_ptr m_analogTrigger; + std::unique_ptr m_counter; int m_frequencyThreshold = 100; double m_positionOffset = 0; double m_distancePerRotation = 1.0; 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 b2040f4998..0cc00d60c6 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-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. */ @@ -65,20 +65,19 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { } private void init() { - m_analogTrigger = new AnalogTrigger(m_dutyCycle); - m_counter = new Counter(); - m_simDevice = SimDevice.create("DutyCycleEncoder", m_dutyCycle.getFPGAIndex()); if (m_simDevice != null) { m_simPosition = m_simDevice.createDouble("Position", false, 0.0); m_simIsConnected = m_simDevice.createBoolean("Connected", false, true); + } else { + m_counter = new Counter(); + m_analogTrigger = new AnalogTrigger(m_dutyCycle); + m_analogTrigger.setLimitsDutyCycle(0.25, 0.75); + m_counter.setUpSource(m_analogTrigger, AnalogTriggerType.kRisingPulse); + m_counter.setDownSource(m_analogTrigger, AnalogTriggerType.kFallingPulse); } - m_analogTrigger.setLimitsDutyCycle(0.25, 0.75); - m_counter.setUpSource(m_analogTrigger, AnalogTriggerType.kRisingPulse); - m_counter.setDownSource(m_analogTrigger, AnalogTriggerType.kFallingPulse); - SendableRegistry.addLW(this, "DutyCycle Encoder", m_dutyCycle.getSourceChannel()); } @@ -173,7 +172,9 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { * Reset the Encoder distance to zero. */ public void reset() { - m_counter.reset(); + if (m_counter != null) { + m_counter.reset(); + } m_positionOffset = m_dutyCycle.getOutput(); } @@ -209,8 +210,12 @@ public class DutyCycleEncoder implements Sendable, AutoCloseable { @Override public void close() { - m_counter.close(); - m_analogTrigger.close(); + if (m_counter != null) { + m_counter.close(); + } + if (m_analogTrigger != null) { + m_analogTrigger.close(); + } if (m_ownsDutyCycle) { m_dutyCycle.close(); }