Compare commits

...

38 Commits

Author SHA1 Message Date
Prateek Machiraju
45590eea22 [wpigui] Hardcode window scale to 1 on macOS (#3135)
This fixes an issue with scaling on Retina displays where the frame
buffer size was double that of the window size, resulting in a content
scale factor of 2. This scale factor caused elements to appear too
large, even on the smallest zoom setting.

This change does not affect external monitors on macOS because the
reported content scale was 1 anyway.
2021-01-28 21:52:13 -08:00
Prateek Machiraju
834a64920b [build] Publish libglass and libglassnt to Maven (#3127) 2021-01-25 21:42:38 -08:00
Tyler Veness
2c2ccb3618 [wpimath] Fix Rotation2d equality operator (#3128) 2021-01-25 21:41:34 -08:00
Prateek Machiraju
fb5c8c39ae [wpigui] clang-tidy: readability-braces-around-statements 2021-01-25 09:25:39 -08:00
Prateek Machiraju
f7d39193a4 [wpigui] Fix copyright in pfd and wpigui_metal.mm 2021-01-25 09:25:39 -08:00
Tyler Veness
aec796b212 [ntcore] Fix conditional jump on uninitialized value (#3125)
`m_last_flush` should be initialized before it's used at
Dispatcher.cpp:243.
2021-01-25 08:15:08 -08:00
Peter Johnson
fb13bb2393 [sim] GUI: Add right click popup for keyboard joystick settings (#3119) 2021-01-23 09:10:58 -08:00
Prateek Machiraju
c517ec6779 [build] Update thirdparty-imgui to 1.79-2 (#3118) 2021-01-22 19:48:49 -08:00
David Vo
e8cbf2a717 [wpimath] Fix typo in SwerveDrivePoseEstimator doc (NFC) (#3112) 2021-01-21 09:31:37 -08:00
Prateek Machiraju
e9c86df468 [wpimath] Add tests for swerve module optimization (#3100) 2021-01-20 20:44:37 -08:00
Modelmat
6ba8c289c5 [examples] Remove negative of ArcadeDrive(fwd, ..) in the C++ Getting Started Example (#3102) 2021-01-20 20:43:34 -08:00
Peter Johnson
3f1672e89f [hal] Add SimDevice createInt() and createLong() (#3110) 2021-01-20 20:42:39 -08:00
Prateek Machiraju
15be5cbf1f [examples] Fix segfault in GearsBot C++ example (#3111)
This fixes a dangling this pointer in the DriveStraight and
SetDistanceToBox commands by directly capturing the
drivetrain pointer by value instead.
2021-01-20 20:38:45 -08:00
Evan Pratten
4cf0e5e6db Add quick links to API documentation in README (#3082) 2021-01-19 23:00:54 -08:00
Tyler Veness
6b1898f12e Fix RT priority docs (NFC) (#3098)
The ranges and which value was specified as highest were incorrect on
some of them. On Linux, the range is 1 to 99 with 99 being highest.

From `man 7 sched`:
```
Processes scheduled under one of the real-time policies (SCHED_FIFO,
SCHED_RR) have a sched_priority value in the range 1 (low) to 99 (high).
```

Also clean up the relevant javadoc and doxygen comments.
2021-01-19 22:59:18 -08:00
David Vo
b3426e9c0d [wpimath] Fix missing whitespace in pose estimator doc (#3097) 2021-01-19 22:58:08 -08:00
Modelmat
38c1a1f3e0 [examples] Fix feildRelative -> fieldRelative typo in XControllerCommand examples (#3104)
* MecanumControllerCommand
* SwerveControllerCommand
2021-01-19 22:57:41 -08:00
Peter Johnson
4488e25f16 [glass] Shorten SmartDashboard window names (#3096)
Instead of "/SmartDashboard/name" they now default to "name (SmartDashboard)".
This allows for smaller windows while preserving the name without requiring
user customization.
2021-01-17 20:33:42 -08:00
CoolSpy3
cfdb3058ee [wpilibj] Update SimDeviceSimTest (#3095) 2021-01-17 13:48:25 -08:00
Mark Vedder
64adff5fea [examples] Fix typo in ArcadeDrive constructor parameter name (#3092)
Removed extra 'p' in "Supplier" in the parameter name `zaxisRotateSuppplier` of the  ArcadeDrive constructor of the Romi Reference example.
2021-01-16 20:27:29 -08:00
Thad House
6efc58e3db [build] Fix issues with build on windows, deprecations, and native utils (#3090) 2021-01-16 20:26:52 -08:00
Tyler Veness
f393989a5b [wpimath, wpiutil] Add wpi::array for compile time size checking (#3087)
The wpimath APIs use std::array, which doesn't do size checking. Passing
an array with the wrong size can result in uninitialized elements
instead of a compilation error.

This is a breaking change but is worthwhile to avoid hard-to-debug errors.
2021-01-16 20:26:17 -08:00
Prateek Machiraju
d6ed20c1e4 [build] Set macOS deployment target to 10.14 (#3088) 2021-01-14 21:20:38 -08:00
Tyler Veness
7c524014c8 [hal] Add [[nodiscard]] to HAL_WaitForNotifierAlarm() (#3085)
As this is a C-compatible header, add a WPI_NODISCARD macro for
compiler-specific C-compatible nodiscard attributes.
2021-01-14 20:00:55 -08:00
Matt
406d055f07 [wpilib] Fixup wouldHitLowerLimit in elevator and arm simulation classes. (#3076)
Closes #3050.
2021-01-14 00:28:00 -08:00
sciencewhiz
04a90b5dd1 [examples] Don't continually set setpoint in PotentiometerPID Examples (#3084) 2021-01-13 20:09:08 -08:00
Prateek Machiraju
8c5bfa0132 [sim] GUI: Add max value setting for keyboard joysticks (#3083) 2021-01-12 19:57:04 -08:00
Peter Johnson
bc80c55353 [hal] Add SimValue reset() function (#3064)
This enables correct behavior for resetting incremental sensor values like
encoder counts or gyro accumulated angle with WebSockets.
2021-01-12 00:38:58 -08:00
Peter Johnson
9c3b51ca0f [wpilib] Document simulation APIs (#3079)
- Remove sim checkstyle suppression
- Add [[nodiscard]] to C++ register callback functions
- Add a couple of missing sim functions

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
Co-authored-by: Starlight220 <yotamshlomi@gmail.com>
2021-01-11 21:55:45 -08:00
Prateek Machiraju
26584ff145 [wpimath] Add model description to LinearSystemId Javadocs (#3080) 2021-01-11 20:08:55 -08:00
Prateek Machiraju
42c3d52863 [examples] Sync Java and C++ trajectories in sim example (#3081)
This also shifts the trajectory up and to the right so that the robot is
always visible in the Field GUI during traversal. Some drive constants
and trajectory constraints were also synced between the two languages.
2021-01-11 20:08:22 -08:00
Dustin Spicuzza
64e72f7103 [wpilibc] Add missing function RoboRioSim::ResetData (#3073) 2021-01-10 22:50:25 -08:00
Matt
e955037980 [wpimath] Add optimize() to SwerveModuleState (#3065)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-01-10 22:49:46 -08:00
Peter Johnson
fb99910c23 [hal] Add SimInt and SimLong wrappers for int/long SimValue (#3066) 2021-01-09 23:26:19 -08:00
CoolSpy3
e620bd4d3f [doc] Add machine-readable websocket specification (#3059)
Co-authored-by: Vasista Vovveti <vasistavovveti@gmail.com>
2021-01-09 23:24:57 -08:00
Peter Johnson
a44e761d9e [glass] Add support for plot Y axis labels 2021-01-08 11:37:35 -08:00
Peter Johnson
ea1974d576 [wpigui] Update imgui and implot to latest 2021-01-08 11:37:35 -08:00
Matt
85a0bd43c2 [wpimath] Add RKF45 integration (#3047)
This is more stable than Runge-Kutta for systems with large elements in their A or B matrices.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-01-06 21:40:25 -08:00
183 changed files with 7188 additions and 778 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
*.gradle text eol=lf
*.java text eol=lf
*.md text eol=lf
*.xml text eol=lf

View File

@@ -38,6 +38,8 @@ jobs:
path: build/allOutputs
build-host:
env:
MACOSX_DEPLOYMENT_TARGET: 10.14
strategy:
fail-fast: false
matrix:

View File

@@ -1,6 +1,6 @@
{
"enableCppIntellisense": true,
"currentLanguage": "cpp",
"projectYear": "2020",
"projectYear": "2021",
"teamNumber": 0
}

View File

@@ -1,6 +1,8 @@
# WPILib Project
![CI](https://github.com/wpilibsuite/allwpilib/workflows/CI/badge.svg)
[![C++ Documentation](https://img.shields.io/badge/documentation-c%2B%2B-blue)](https://first.wpi.edu/wpilib/allwpilib/docs/development/cpp/)
[![Java Documentation](https://img.shields.io/badge/documentation-java-orange)](https://first.wpi.edu/wpilib/allwpilib/docs/development/java/)
Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WPILibC projects. These are the core libraries for creating robot programs for the roboRIO.

View File

@@ -5,5 +5,5 @@ repositories {
}
}
dependencies {
implementation "edu.wpi.first:native-utils:2021.1.0"
implementation "edu.wpi.first:native-utils:2021.1.1"
}

View File

@@ -4,9 +4,65 @@ def baseArtifactId = 'Glass'
def artifactGroupId = 'edu.wpi.first.tools'
def zipBaseName = '_GROUP_edu_wpi_first_tools_ID_Glass_CLS'
def libBaseArtifactId = 'libglass'
def libArtifactGroupId = 'edu.wpi.first.glass'
def libZipBaseName = '_GROUP_edu_wpi_first_glass_ID_libglass_CLS'
def libntBaseArtifactId = 'libglassnt'
def libntArtifactGroupId = 'edu.wpi.first.glass'
def libntZipBaseName = '_GROUP_edu_wpi_first_glass_ID_libglassnt_CLS'
def outputsFolder = file("$project.buildDir/outputs")
task libCppSourcesZip(type: Zip) {
destinationDirectory = outputsFolder
archiveBaseName = libZipBaseName
classifier = "sources"
from(licenseFile) { into '/' }
from('src/lib/native/cpp') { into '/' }
}
task libCppHeadersZip(type: Zip) {
destinationDirectory = outputsFolder
archiveBaseName = libZipBaseName
classifier = "headers"
from(licenseFile) { into '/' }
from('src/lib/native/include') { into '/' }
}
task libntCppSourcesZip(type: Zip) {
destinationDirectory = outputsFolder
archiveBaseName = libntZipBaseName
classifier = "sources"
from(licenseFile) { into '/' }
from('src/libnt/native/cpp') { into '/' }
}
task libntCppHeadersZip(type: Zip) {
destinationDirectory = outputsFolder
archiveBaseName = libntZipBaseName
classifier = "headers"
from(licenseFile) { into '/' }
from('src/libnt/native/include') { into '/' }
}
build.dependsOn libCppHeadersZip
build.dependsOn libCppSourcesZip
build.dependsOn libntCppHeadersZip
build.dependsOn libntCppSourcesZip
addTaskToCopyAllOutputs(libCppHeadersZip)
addTaskToCopyAllOutputs(libCppSourcesZip)
addTaskToCopyAllOutputs(libntCppHeadersZip)
addTaskToCopyAllOutputs(libntCppSourcesZip)
model {
publishing {
def tasks = []
def glassAppTaskList = []
$.components.each { component ->
component.binaries.each { binary ->
if (binary in NativeExecutableBinarySpec && binary.component.name.contains("glassApp")) {
@@ -50,10 +106,9 @@ model {
}
// Create the ZIP.
def outputsFolder = file("$project.buildDir/outputs")
def task = project.tasks.create("copyGlassExecutable", Zip) {
description("Copies the Glass executable to the outputs directory.")
destinationDir(outputsFolder)
destinationDirectory = outputsFolder
archiveBaseName = '_M_' + zipBaseName
duplicatesStrategy = 'exclude'
@@ -73,7 +128,7 @@ model {
}
task.dependsOn binary.tasks.link
tasks.add(task)
glassAppTaskList.add(task)
project.build.dependsOn task
project.artifacts { task }
addTaskToCopyAllOutputs(task)
@@ -82,13 +137,37 @@ model {
}
}
def libGlassTaskList = createComponentZipTasks($.components, ['glass'], libZipBaseName, Zip, project, includeStandardZipFormat)
def libGlassntTaskList = createComponentZipTasks($.components, ['glassnt'], libntZipBaseName, Zip, project, includeStandardZipFormat)
publications {
cpp(MavenPublication) {
tasks.each { artifact it }
glassApp(MavenPublication) {
glassAppTaskList.each { artifact it }
artifactId = baseArtifactId
groupId = artifactGroupId
version wpilibVersioning.version.get()
}
libglass(MavenPublication) {
libGlassTaskList.each { artifact it }
artifact libCppHeadersZip
artifact libCppSourcesZip
artifactId = libBaseArtifactId
groupId = libArtifactGroupId
version wpilibVersioning.version.get()
}
libglassnt(MavenPublication) {
libGlassntTaskList.each { artifact it }
artifact libntCppHeadersZip
artifact libntCppSourcesZip
artifactId = libntBaseArtifactId
groupId = libntArtifactGroupId
version wpilibVersioning.version.get()
}
}
}
}

View File

@@ -50,7 +50,8 @@ void Window::Display() {
char label[128];
std::snprintf(label, sizeof(label), "%s###%s",
m_name.empty() ? m_id.c_str() : m_name.c_str(), m_id.c_str());
m_name.empty() ? m_defaultName.c_str() : m_name.c_str(),
m_id.c_str());
if (Begin(label, &m_visible, m_flags)) {
if (m_renamePopupEnabled) {

View File

@@ -119,7 +119,7 @@ class Plot {
std::string m_name;
bool m_visible = true;
bool m_showPause = true;
unsigned int m_plotFlags = ImPlotFlags_Default;
unsigned int m_plotFlags = ImPlotFlags_None;
bool m_lockPrevX = false;
bool m_paused = false;
float m_viewTime = 10;
@@ -131,6 +131,7 @@ class Plot {
bool lockMax = false;
bool apply = false;
};
std::string m_axisLabel[3];
PlotRange m_axisRange[3];
ImPlotRange m_xaxisRange; // read from plot, used for lockPrevX
};
@@ -348,13 +349,13 @@ PlotSeries::Action PlotSeries::EmitPlot(PlotView& view, double now, size_t i,
if (IsDigital()) {
ImPlot::PushStyleVar(ImPlotStyleVar_DigitalBitHeight, m_digitalBitHeight);
ImPlot::PushStyleVar(ImPlotStyleVar_DigitalBitGap, m_digitalBitGap);
ImPlot::PlotDigital(label, getter, &getterData, size + 1);
ImPlot::PlotDigitalG(label, getter, &getterData, size + 1);
ImPlot::PopStyleVar();
ImPlot::PopStyleVar();
} else {
ImPlot::SetPlotYAxis(m_yAxis);
ImPlot::SetNextMarkerStyle(m_marker - 1);
ImPlot::PlotLine(label, getter, &getterData, size + 1);
ImPlot::PlotLineG(label, getter, &getterData, size + 1);
}
// DND source for PlotSeries
@@ -492,9 +493,9 @@ bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) {
return true;
}
if (num == 0) {
m_plotFlags &= ~ImPlotFlags_Legend;
m_plotFlags |= ImPlotFlags_NoLegend;
} else {
m_plotFlags |= ImPlotFlags_Legend;
m_plotFlags &= ~ImPlotFlags_NoLegend;
}
return true;
} else if (name == "yaxis2") {
@@ -570,6 +571,9 @@ bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) {
}
m_axisRange[yAxis].lockMax = num != 0;
return true;
} else if (yName == "label") {
m_axisLabel[yAxis] = value;
return true;
}
}
return false;
@@ -580,16 +584,18 @@ void Plot::WriteIni(ImGuiTextBuffer* out) {
"name=%s\nvisible=%d\nshowPause=%d\nlockPrevX=%d\nlegend=%d\n"
"yaxis2=%d\nyaxis3=%d\nviewTime=%d\nheight=%d\n",
m_name.c_str(), m_visible ? 1 : 0, m_showPause ? 1 : 0,
m_lockPrevX ? 1 : 0, (m_plotFlags & ImPlotFlags_Legend) ? 1 : 0,
m_lockPrevX ? 1 : 0, (m_plotFlags & ImPlotFlags_NoLegend) ? 0 : 1,
(m_plotFlags & ImPlotFlags_YAxis2) ? 1 : 0,
(m_plotFlags & ImPlotFlags_YAxis3) ? 1 : 0,
static_cast<int>(m_viewTime * 1000), m_height);
for (int i = 0; i < 3; ++i) {
out->appendf("y%d_min=%d\ny%d_max=%d\ny%d_lockMin=%d\ny%d_lockMax=%d\n", i,
static_cast<int>(m_axisRange[i].min * 1000), i,
static_cast<int>(m_axisRange[i].max * 1000), i,
m_axisRange[i].lockMin ? 1 : 0, i,
m_axisRange[i].lockMax ? 1 : 0);
out->appendf(
"y%d_min=%d\ny%d_max=%d\ny%d_lockMin=%d\ny%d_lockMax=%d\n"
"y%d_label=%s\n",
i, static_cast<int>(m_axisRange[i].min * 1000), i,
static_cast<int>(m_axisRange[i].max * 1000), i,
m_axisRange[i].lockMin ? 1 : 0, i, m_axisRange[i].lockMax ? 1 : 0, i,
m_axisLabel[i].c_str());
}
}
@@ -658,9 +664,9 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
(paused || m_paused) ? ImGuiCond_Once : ImGuiCond_Always);
}
ImPlotAxisFlags yFlags[3] = {ImPlotAxisFlags_Default,
ImPlotAxisFlags_Auxiliary,
ImPlotAxisFlags_Auxiliary};
ImPlotAxisFlags yFlags[3] = {ImPlotAxisFlags_None,
ImPlotAxisFlags_NoGridLines,
ImPlotAxisFlags_NoGridLines};
for (int i = 0; i < 3; ++i) {
ImPlot::SetNextPlotLimitsY(
m_axisRange[i].min, m_axisRange[i].max,
@@ -674,9 +680,13 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
}
}
if (ImPlot::BeginPlot(label, nullptr, nullptr, ImVec2(-1, m_height),
m_plotFlags, ImPlotAxisFlags_Default, yFlags[0],
yFlags[1], yFlags[2])) {
if (ImPlot::BeginPlot(
label, nullptr,
m_axisLabel[0].empty() ? nullptr : m_axisLabel[0].c_str(),
ImVec2(-1, m_height), m_plotFlags, ImPlotAxisFlags_None, yFlags[0],
yFlags[1], yFlags[2],
m_axisLabel[1].empty() ? nullptr : m_axisLabel[1].c_str(),
m_axisLabel[2].empty() ? nullptr : m_axisLabel[2].c_str())) {
for (size_t j = 0; j < m_series.size(); ++j) {
ImGui::PushID(j);
switch (m_series[j]->EmitPlot(view, now, j, i)) {
@@ -708,6 +718,8 @@ void Plot::EmitSettingsLimits(int axis) {
ImGui::Indent();
ImGui::PushID(axis);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10);
ImGui::InputText("Label", &m_axisLabel[axis]);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 3.5);
ImGui::InputDouble("Min", &m_axisRange[axis].min, 0, 0, "%.3f");
ImGui::SameLine();
@@ -733,7 +745,7 @@ void Plot::EmitSettings(size_t i) {
ImGui::InputText("##editname", &m_name);
ImGui::Checkbox("Visible", &m_visible);
ImGui::Checkbox("Show Pause Button", &m_showPause);
ImGui::CheckboxFlags("Show Legend", &m_plotFlags, ImPlotFlags_Legend);
ImGui::CheckboxFlags("Hide Legend", &m_plotFlags, ImPlotFlags_NoLegend);
if (i != 0) {
ImGui::Checkbox("Lock X-axis to previous plot", &m_lockPrevX);
}

View File

@@ -160,7 +160,7 @@ bool DeleteButton(ImGuiID id, const ImVec2& pos) {
bool HeaderDeleteButton(const char* label) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiItemHoveredDataBackup last_item_backup;
ImGuiLastItemDataBackup last_item_backup;
ImGuiID id = window->GetID(label);
float button_size = g.FontSize;
float button_x = ImMax(window->DC.LastItemRect.Min.x,

View File

@@ -23,7 +23,7 @@ namespace glass {
class Window {
public:
Window() = default;
explicit Window(wpi::StringRef id) : m_id{id} {}
explicit Window(wpi::StringRef id) : m_id{id}, m_defaultName{id} {}
wpi::StringRef GetId() const { return m_id; }
@@ -44,6 +44,7 @@ class Window {
void SetFlags(ImGuiWindowFlags flags) { m_flags = flags; }
void SetName(const wpi::Twine& name) { m_name = name.str(); }
void SetDefaultName(const wpi::Twine& name) { m_defaultName = name.str(); }
/**
* Normally windows provide a right-click popup menu on the title bar to
@@ -115,6 +116,7 @@ class Window {
private:
std::string m_id;
std::string m_name;
std::string m_defaultName;
std::unique_ptr<View> m_view;
ImGuiWindowFlags m_flags = 0;
bool m_visible = true;

View File

@@ -153,6 +153,10 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
if (!window) {
return;
}
if (wpi::StringRef{entry->name}.startswith("/SmartDashboard/")) {
window->SetDefaultName(wpi::StringRef{entry->name}.drop_front(16) +
" (SmartDashboard)");
}
entry->window = window;
// create view

View File

@@ -4,7 +4,17 @@
package edu.wpi.first.hal;
/** A wrapper around a simulator device handle. */
/**
* A wrapper around a simulator device handle.
*
* <p>Teams: if you are using this class, you are likely confusing it for {@link
* edu.wpi.first.wpilibj.simulation.SimDeviceSim}.
*
* <p>Vendors: This class should be used from inside the device class to define the
* properties/fields of the device. Use {@link #create} to get a SimDevice object, then use {@link
* #createDouble(String, Direction, double)} or similar to define the device's fields. See {@link
* edu.wpi.first.wpilibj.ADXRS450_Gyro} for an example implementation.
*/
public class SimDevice implements AutoCloseable {
public enum Direction {
kInput(SimDeviceJNI.kInput),
@@ -130,6 +140,42 @@ public class SimDevice implements AutoCloseable {
return new SimValue(handle);
}
/**
* Creates an int value on the simulated device.
*
* <p>Returns null if not in simulation.
*
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated double value object
*/
public SimInt createInt(String name, Direction direction, int initialValue) {
int handle = SimDeviceJNI.createSimValueInt(m_handle, name, direction.m_value, initialValue);
if (handle <= 0) {
return null;
}
return new SimInt(handle);
}
/**
* Creates a long value on the simulated device.
*
* <p>Returns null if not in simulation.
*
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated double value object
*/
public SimLong createLong(String name, Direction direction, long initialValue) {
int handle = SimDeviceJNI.createSimValueLong(m_handle, name, direction.m_value, initialValue);
if (handle <= 0) {
return null;
}
return new SimLong(handle);
}
/**
* Creates a double value on the simulated device.
*

View File

@@ -81,6 +81,36 @@ public class SimDeviceJNI extends JNIWrapper {
initialValue.getNativeDouble());
}
/**
* Creates an int value on a simulated device.
*
* <p>Returns 0 if not in simulation; this can be used to avoid calls to Set/Get functions.
*
* @param device simulated device handle
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated value handle
*/
public static int createSimValueInt(int device, String name, int direction, int initialValue) {
return createSimValueNative(device, name, direction, HALValue.kInt, initialValue, 0.0);
}
/**
* Creates a long value on a simulated device.
*
* <p>Returns 0 if not in simulation; this can be used to avoid calls to Set/Get functions.
*
* @param device simulated device handle
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated value handle
*/
public static int createSimValueLong(int device, String name, int direction, long initialValue) {
return createSimValueNative(device, name, direction, HALValue.kLong, initialValue, 0.0);
}
/**
* Creates a double value on a simulated device.
*
@@ -221,6 +251,22 @@ public class SimDeviceJNI extends JNIWrapper {
*/
public static native HALValue getSimValue(int handle);
/**
* Gets a simulated value (int).
*
* @param handle simulated value handle
* @return The current value
*/
public static native int getSimValueInt(int handle);
/**
* Gets a simulated value (long).
*
* @param handle simulated value handle
* @return The current value
*/
public static native long getSimValueLong(int handle);
/**
* Gets a simulated value (double).
*
@@ -257,6 +303,26 @@ public class SimDeviceJNI extends JNIWrapper {
setSimValueNative(handle, value.getType(), value.getNativeLong(), value.getNativeDouble());
}
/**
* Sets a simulated value (int).
*
* @param handle simulated value handle
* @param value the value to set
*/
public static void setSimValueInt(int handle, int value) {
setSimValueNative(handle, HALValue.kInt, value, 0.0);
}
/**
* Sets a simulated value (long).
*
* @param handle simulated value handle
* @param value the value to set
*/
public static void setSimValueLong(int handle, long value) {
setSimValueNative(handle, HALValue.kLong, value, 0.0);
}
/**
* Sets a simulated value (double).
*
@@ -286,4 +352,13 @@ public class SimDeviceJNI extends JNIWrapper {
public static void setSimValueBoolean(int handle, boolean value) {
setSimValueNative(handle, HALValue.kBoolean, value ? 1 : 0, 0.0);
}
/**
* Resets a simulated double or integral value to 0. Has no effect on other value types. Use this
* instead of Set(0) for resetting incremental sensor values like encoder counts or gyro
* accumulated angle to ensure correct behavior in a distributed system (e.g. WebSockets).
*
* @param handle simulated value handle
*/
public static native void resetSimValue(int handle);
}

View File

@@ -32,4 +32,13 @@ public class SimDouble extends SimValue {
public void set(double value) {
SimDeviceJNI.setSimValueDouble(m_handle, value);
}
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting incremental sensor
* values like encoder counts or gyro accumulated angle to ensure correct behavior in a
* distributed system (e.g. WebSockets).
*/
public void reset() {
SimDeviceJNI.resetSimValue(m_handle);
}
}

View File

@@ -0,0 +1,44 @@
// 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.
package edu.wpi.first.hal;
/** A wrapper around a simulator int value handle. */
public class SimInt extends SimValue {
/**
* Wraps a simulated value handle as returned by SimDeviceJNI.createSimValueInt().
*
* @param handle simulated value handle
*/
public SimInt(int handle) {
super(handle);
}
/**
* Gets the simulated value.
*
* @return The current value
*/
public int get() {
return SimDeviceJNI.getSimValueInt(m_handle);
}
/**
* Sets the simulated value.
*
* @param value the value to set
*/
public void set(int value) {
SimDeviceJNI.setSimValueInt(m_handle, value);
}
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting incremental sensor
* values like encoder counts or gyro accumulated angle to ensure correct behavior in a
* distributed system (e.g. WebSockets).
*/
public void reset() {
SimDeviceJNI.resetSimValue(m_handle);
}
}

View File

@@ -0,0 +1,44 @@
// 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.
package edu.wpi.first.hal;
/** A wrapper around a simulator long value handle. */
public class SimLong extends SimValue {
/**
* Wraps a simulated value handle as returned by SimDeviceJNI.createSimValueLong().
*
* @param handle simulated value handle
*/
public SimLong(int handle) {
super(handle);
}
/**
* Gets the simulated value.
*
* @return The current value
*/
public long get() {
return SimDeviceJNI.getSimValueLong(m_handle);
}
/**
* Sets the simulated value.
*
* @param value the value to set
*/
public void set(long value) {
SimDeviceJNI.setSimValueLong(m_handle, value);
}
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting incremental sensor
* values like encoder counts or gyro accumulated angle to ensure correct behavior in a
* distributed system (e.g. WebSockets).
*/
public void reset() {
SimDeviceJNI.resetSimValue(m_handle);
}
}

View File

@@ -7,13 +7,17 @@ package edu.wpi.first.hal.simulation;
import edu.wpi.first.hal.JNIWrapper;
public class RoboRioDataJNI extends JNIWrapper {
@SuppressWarnings("AbbreviationAsWordInName")
public static native int registerFPGAButtonCallback(
NotifyCallback callback, boolean initialNotify);
@SuppressWarnings("AbbreviationAsWordInName")
public static native void cancelFPGAButtonCallback(int uid);
@SuppressWarnings("AbbreviationAsWordInName")
public static native boolean getFPGAButton();
@SuppressWarnings("AbbreviationAsWordInName")
public static native void setFPGAButton(boolean fPGAButton);
public static native int registerVInVoltageCallback(

View File

@@ -29,6 +29,7 @@ public class SimDeviceDataJNI extends JNIWrapper {
public static native int getSimValueDeviceHandle(int handle);
public static class SimDeviceInfo {
@SuppressWarnings("JavadocMethod")
public SimDeviceInfo(String name, int handle) {
this.name = name;
this.handle = handle;
@@ -59,9 +60,23 @@ public class SimDeviceDataJNI extends JNIWrapper {
public static native void cancelSimValueChangedCallback(int uid);
/**
* Register a callback for SimDeviceJNI.resetSimValue(). The callback is called with the old
* value.
*
* @param handle simulated value handle
* @param callback callback
* @param initialNotify ignored (present for consistency)
*/
public static native int registerSimValueResetCallback(
int handle, SimValueCallback2 callback, boolean initialNotify);
public static native void cancelSimValueResetCallback(int uid);
public static native int getSimValueHandle(int device, String name);
public static class SimValueInfo {
@SuppressWarnings("JavadocMethod")
public SimValueInfo(
String name, int handle, int direction, int type, long value1, double value2) {
this.name = name;

View File

@@ -40,6 +40,8 @@ void HAL_GetSimValue(HAL_SimValueHandle handle, struct HAL_Value* value) {
void HAL_SetSimValue(HAL_SimValueHandle handle, const struct HAL_Value* value) {
}
void HAL_ResetSimValue(HAL_SimValueHandle handle) {}
hal::SimDevice::SimDevice(const char* name, int index) {}
hal::SimDevice::SimDevice(const char* name, int index, int channel) {}

View File

@@ -32,8 +32,8 @@ int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime,
return sch.sched_priority;
} else {
*isRealTime = false;
// 0 is the only suppored priority for non-realtime, so scale to 1
return 1;
// 0 is the only supported priority for non-real-time
return 0;
}
}

View File

@@ -63,6 +63,15 @@ int32_t HALSIM_RegisterSimValueChangedCallback(HAL_SimValueHandle handle,
void HALSIM_CancelSimValueChangedCallback(int32_t uid) {}
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify) {
return 0;
}
void HALSIM_CancelSimValueResetCallback(int32_t uid) {}
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name) {
return 0;

View File

@@ -153,6 +153,30 @@ Java_edu_wpi_first_hal_SimDeviceJNI_getSimValue
return hal::CreateHALValue(env, HAL_GetSimValue(handle));
}
/*
* Class: edu_wpi_first_hal_SimDeviceJNI
* Method: getSimValueInt
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_SimDeviceJNI_getSimValueInt
(JNIEnv*, jclass, jint handle)
{
return HAL_GetSimValueInt(handle);
}
/*
* Class: edu_wpi_first_hal_SimDeviceJNI
* Method: getSimValueLong
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_first_hal_SimDeviceJNI_getSimValueLong
(JNIEnv*, jclass, jint handle)
{
return HAL_GetSimValueLong(handle);
}
/*
* Class: edu_wpi_first_hal_SimDeviceJNI
* Method: getSimValueDouble
@@ -201,4 +225,16 @@ Java_edu_wpi_first_hal_SimDeviceJNI_setSimValueNative
HAL_SetSimValue(handle, ValueFromJava(type, value1, value2));
}
/*
* Class: edu_wpi_first_hal_SimDeviceJNI
* Method: resetSimValue
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_SimDeviceJNI_resetSimValue
(JNIEnv*, jclass, jint handle)
{
HAL_ResetSimValue(handle);
}
} // extern "C"

View File

@@ -600,6 +600,32 @@ Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueChangedCallback
FreeValueCallback(env, uid, &HALSIM_CancelSimValueChangedCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: registerSimValueResetCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimValueResetCallback
(JNIEnv* env, jclass, jint handle, jobject callback, jboolean initialNotify)
{
return AllocateValueCallback(env, static_cast<HAL_SimValueHandle>(handle),
callback, true, initialNotify,
&HALSIM_RegisterSimValueResetCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: cancelSimValueResetCallback
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueResetCallback
(JNIEnv* env, jclass, jint uid)
{
FreeValueCallback(env, uid, &HALSIM_CancelSimValueResetCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: getSimValueHandle

View File

@@ -6,6 +6,8 @@
#include <stdint.h>
#include <wpi/nodiscard.h>
#include "hal/Types.h"
/**
@@ -80,11 +82,14 @@ void HAL_CancelNotifierAlarm(HAL_NotifierHandle notifierHandle,
* Waits for the next alarm for the specific notifier.
*
* This is a blocking call until either the time elapses or HAL_StopNotifier
* gets called.
* gets called. If the latter occurs, this function will return zero and any
* loops using this function should exit. Failing to do so can lead to
* use-after-frees.
*
* @param notifierHandle the notifier handle
* @return the FPGA time the notifier returned
*/
WPI_NODISCARD
uint64_t HAL_WaitForNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status);

View File

@@ -94,6 +94,46 @@ inline HAL_SimValueHandle HAL_CreateSimValue(HAL_SimDeviceHandle device,
} // extern "C++"
#endif
/**
* Creates an int value on a simulated device.
*
* Returns 0 if not in simulation; this can be used to avoid calls
* to Set/Get functions.
*
* @param device simulated device handle
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated value handle
*/
inline HAL_SimValueHandle HAL_CreateSimValueInt(HAL_SimDeviceHandle device,
const char* name,
int32_t direction,
int32_t initialValue) {
struct HAL_Value v = HAL_MakeInt(initialValue);
return HAL_CreateSimValue(device, name, direction, &v);
}
/**
* Creates a long value on a simulated device.
*
* Returns 0 if not in simulation; this can be used to avoid calls
* to Set/Get functions.
*
* @param device simulated device handle
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated value handle
*/
inline HAL_SimValueHandle HAL_CreateSimValueLong(HAL_SimDeviceHandle device,
const char* name,
int32_t direction,
int64_t initialValue) {
struct HAL_Value v = HAL_MakeLong(initialValue);
return HAL_CreateSimValue(device, name, direction, &v);
}
/**
* Creates a double value on a simulated device.
*
@@ -196,6 +236,30 @@ inline HAL_Value HAL_GetSimValue(HAL_SimValueHandle handle) {
} // extern "C++"
#endif
/**
* Gets a simulated value (int).
*
* @param handle simulated value handle
* @return The current value
*/
inline int32_t HAL_GetSimValueInt(HAL_SimValueHandle handle) {
struct HAL_Value v;
HAL_GetSimValue(handle, &v);
return v.type == HAL_INT ? v.data.v_int : 0;
}
/**
* Gets a simulated value (long).
*
* @param handle simulated value handle
* @return The current value
*/
inline int64_t HAL_GetSimValueLong(HAL_SimValueHandle handle) {
struct HAL_Value v;
HAL_GetSimValue(handle, &v);
return v.type == HAL_LONG ? v.data.v_long : 0;
}
/**
* Gets a simulated value (double).
*
@@ -248,6 +312,28 @@ inline void HAL_SetSimValue(HAL_SimValueHandle handle, const HAL_Value& value) {
} // extern "C++"
#endif
/**
* Sets a simulated value (int).
*
* @param handle simulated value handle
* @param value the value to set
*/
inline void HAL_SetSimValueInt(HAL_SimValueHandle handle, int value) {
struct HAL_Value v = HAL_MakeInt(value);
HAL_SetSimValue(handle, &v);
}
/**
* Sets a simulated value (long).
*
* @param handle simulated value handle
* @param value the value to set
*/
inline void HAL_SetSimValueLong(HAL_SimValueHandle handle, int64_t value) {
struct HAL_Value v = HAL_MakeLong(value);
HAL_SetSimValue(handle, &v);
}
/**
* Sets a simulated value (double).
*
@@ -281,6 +367,17 @@ inline void HAL_SetSimValueBoolean(HAL_SimValueHandle handle, HAL_Bool value) {
HAL_SetSimValue(handle, &v);
}
/**
* Resets a simulated double or integral value to 0.
* Has no effect on other value types.
* Use this instead of Set(0) for resetting incremental sensor values like
* encoder counts or gyro accumulated angle to ensure correct behavior in a
* distributed system (e.g. WebSockets).
*
* @param handle simulated value handle
*/
void HAL_ResetSimValue(HAL_SimValueHandle handle);
/** @} */
#ifdef __cplusplus
@@ -342,6 +439,88 @@ class SimValue {
HAL_SimValueHandle m_handle = HAL_kInvalidHandle;
};
/**
* C++ wrapper around a HAL simulator int value handle.
*/
class SimInt : public SimValue {
public:
/**
* Default constructor that results in an "empty" object that is false in
* a boolean context.
*/
SimInt() = default;
/**
* Wraps a simulated value handle as returned by HAL_CreateSimValueInt().
*
* @param handle simulated value handle
*/
/*implicit*/ SimInt(HAL_SimValueHandle val) // NOLINT
: SimValue(val) {}
/**
* Gets the simulated value.
*
* @return The current value
*/
int32_t Get() const { return HAL_GetSimValueInt(m_handle); }
/**
* Sets the simulated value.
*
* @param value the value to set
*/
void Set(int32_t value) { HAL_SetSimValueInt(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**
* C++ wrapper around a HAL simulator long value handle.
*/
class SimLong : public SimValue {
public:
/**
* Default constructor that results in an "empty" object that is false in
* a boolean context.
*/
SimLong() = default;
/**
* Wraps a simulated value handle as returned by HAL_CreateSimValueLong().
*
* @param handle simulated value handle
*/
/*implicit*/ SimLong(HAL_SimValueHandle val) // NOLINT
: SimValue(val) {}
/**
* Gets the simulated value.
*
* @return The current value
*/
int64_t Get() const { return HAL_GetSimValueLong(m_handle); }
/**
* Sets the simulated value.
*
* @param value the value to set
*/
void Set(int64_t value) { HAL_SetSimValueLong(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**
* C++ wrapper around a HAL simulator double value handle.
*/
@@ -374,6 +553,13 @@ class SimDouble : public SimValue {
* @param value the value to set
*/
void Set(double value) { HAL_SetSimValueDouble(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**
@@ -562,6 +748,37 @@ class SimDevice {
return HAL_CreateSimValue(m_handle, name, direction, &initialValue);
}
/**
* Creates an int value on the simulated device.
*
* If not in simulation, results in an "empty" object that evaluates to false
* in a boolean context.
*
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated double value object
*/
SimInt CreateInt(const char* name, int32_t direction, int32_t initialValue) {
return HAL_CreateSimValueInt(m_handle, name, direction, initialValue);
}
/**
* Creates a long value on the simulated device.
*
* If not in simulation, results in an "empty" object that evaluates to false
* in a boolean context.
*
* @param name value name
* @param direction input/output/bidir (from perspective of user code)
* @param initialValue initial value
* @return simulated double value object
*/
SimLong CreateLong(const char* name, int32_t direction,
int64_t initialValue) {
return HAL_CreateSimValueLong(m_handle, name, direction, initialValue);
}
/**
* Creates a double value on the simulated device.
*

View File

@@ -21,11 +21,13 @@ extern "C" {
/**
* Gets the thread priority for the specified thread.
*
* @param handle Native handle pointer to the thread to get the priority for
* @param isRealTime Set to true if thread is realtime, otherwise false
* @param status Error status variable. 0 on success
* @return The current thread priority. Scaled 1-99, with 1 being
* highest.
* @param handle Native handle pointer to the thread to get the priority
* for.
* @param isRealTime Set to true if thread is real-time, otherwise false.
* @param status Error status variable. 0 on success.
* @return The current thread priority. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is 0. See
* "man 7 sched" for details.
*/
int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime,
int32_t* status);
@@ -34,23 +36,25 @@ int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime,
* Gets the thread priority for the current thread.
*
* @param handle Native handle pointer to the thread to get the priority for
* @param isRealTime Set to true if thread is realtime, otherwise false
* @param status Error status variable. 0 on success
* @return The current thread priority. Scaled 1-99, with 1 being
* highest.
* @param isRealTime Set to true if thread is real-time, otherwise false.
* @param status Error status variable. 0 on success.
* @return The current thread priority. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is 0. See
* "man 7 sched" for details.
*/
int32_t HAL_GetCurrentThreadPriority(HAL_Bool* isRealTime, int32_t* status);
/**
* Sets the thread priority for the specified thread.
*
* @param thread Reference to the thread to set the priority of
* @param realTime Set to true to set a realtime priority, false for standard
* priority
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest
* @param status Error status variable. 0 on success
* @return The success state of setting the priority
* @param thread Reference to the thread to set the priority of.
* @param realTime Set to true to set a real-time priority, false for standard
* priority.
* @param priority Priority to set the thread to. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is forced to
* 0. See "man 7 sched" for more details.
* @param status Error status variable. 0 on success.
* @return True on success.
*/
HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime,
int32_t priority, int32_t* status);
@@ -58,13 +62,14 @@ HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime,
/**
* Sets the thread priority for the current thread.
*
* @param thread Reference to the thread to set the priority of
* @param realTime Set to true to set a realtime priority, false for standard
* priority
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest
* @param status Error status variable. 0 on success
* @return The success state of setting the priority
* @param thread Reference to the thread to set the priority of.
* @param realTime Set to true to set a real-time priority, false for standard
* priority.
* @param priority Priority to set the thread to. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is forced to
* 0. See "man 7 sched" for more details.
* @param status Error status variable. 0 on success.
* @return True on success.
*/
HAL_Bool HAL_SetCurrentThreadPriority(HAL_Bool realTime, int32_t priority,
int32_t* status);

View File

@@ -57,6 +57,21 @@ int32_t HALSIM_RegisterSimValueChangedCallback(HAL_SimValueHandle handle,
void HALSIM_CancelSimValueChangedCallback(int32_t uid);
/**
* Register a callback for HAL_SimValueReset(). The callback is called with
* the old value.
*
* @param handle simulated value handle
* @param callback callback
* @param initialNotify ignored (present for consistency)
*/
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify);
void HALSIM_CancelSimValueResetCallback(int32_t uid);
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name);

View File

@@ -61,6 +61,10 @@ void HAL_SetSimValue(HAL_SimValueHandle handle, const struct HAL_Value* value) {
SimSimDeviceData->SetValue(handle, *value);
}
void HAL_ResetSimValue(HAL_SimValueHandle handle) {
SimSimDeviceData->ResetValue(handle);
}
hal::SimDevice::SimDevice(const char* name, int index) {
wpi::SmallString<128> fullname;
wpi::raw_svector_ostream os(fullname);

View File

@@ -220,6 +220,47 @@ void SimDeviceData::SetValue(HAL_SimValueHandle handle,
valueImpl->direction, &value);
}
void SimDeviceData::ResetValue(HAL_SimValueHandle handle) {
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(handle);
if (!valueImpl) {
return;
}
// don't notify reset if we aren't going to actually reset anything
switch (valueImpl->value.type) {
case HAL_INT:
case HAL_LONG:
case HAL_DOUBLE:
break;
default:
return;
}
// notify reset callbacks (done here so they're called with the old value)
valueImpl->reset(valueImpl->name.c_str(), valueImpl->handle,
valueImpl->direction, &valueImpl->value);
// set user-facing value to 0
switch (valueImpl->value.type) {
case HAL_INT:
valueImpl->value.data.v_int = 0;
break;
case HAL_LONG:
valueImpl->value.data.v_long = 0;
break;
case HAL_DOUBLE:
valueImpl->value.data.v_double = 0;
break;
default:
return;
}
// notify changed callbacks
valueImpl->changed(valueImpl->name.c_str(), valueImpl->handle,
valueImpl->direction, &valueImpl->value);
}
int32_t SimDeviceData::RegisterDeviceCreatedCallback(
const char* prefix, void* param, HALSIM_SimDeviceCallback callback,
bool initialNotify) {
@@ -368,6 +409,35 @@ void SimDeviceData::CancelValueChangedCallback(int32_t uid) {
valueImpl->changed.Cancel(uid & 0x7f);
}
int32_t SimDeviceData::RegisterValueResetCallback(
HAL_SimValueHandle handle, void* param, HALSIM_SimValueCallback callback,
bool initialNotify) {
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(handle);
if (!valueImpl) {
return -1;
}
// register callback
int32_t index = valueImpl->reset.Register(callback, param);
// encode device and value into uid
return (((handle >> 16) & 0xfff) << 19) | ((handle & 0xfff) << 7) |
(index & 0x7f);
}
void SimDeviceData::CancelValueResetCallback(int32_t uid) {
if (uid <= 0) {
return;
}
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(((uid >> 19) << 16) | ((uid >> 7) & 0xfff));
if (!valueImpl) {
return;
}
valueImpl->reset.Cancel(uid & 0x7f);
}
HAL_SimValueHandle SimDeviceData::GetValueHandle(HAL_SimDeviceHandle device,
const char* name) {
std::scoped_lock lock(m_mutex);
@@ -517,6 +587,18 @@ void HALSIM_CancelSimValueChangedCallback(int32_t uid) {
SimSimDeviceData->CancelValueChangedCallback(uid);
}
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify) {
return SimSimDeviceData->RegisterValueResetCallback(handle, param, callback,
initialNotify);
}
void HALSIM_CancelSimValueResetCallback(int32_t uid) {
SimSimDeviceData->CancelValueResetCallback(uid);
}
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name) {
return SimSimDeviceData->GetValueHandle(device, name);

View File

@@ -150,6 +150,7 @@ class SimDeviceData {
std::vector<const char*> cstrEnumOptions;
std::vector<double> enumOptionValues;
impl::SimUnnamedCallbackRegistry<HALSIM_SimValueCallback> changed;
impl::SimUnnamedCallbackRegistry<HALSIM_SimValueCallback> reset;
};
struct Device {
@@ -188,6 +189,7 @@ class SimDeviceData {
const HAL_Value& initialValue);
HAL_Value GetValue(HAL_SimValueHandle handle);
void SetValue(HAL_SimValueHandle handle, const HAL_Value& value);
void ResetValue(HAL_SimValueHandle handle);
int32_t RegisterDeviceCreatedCallback(const char* prefix, void* param,
HALSIM_SimDeviceCallback callback,
@@ -218,6 +220,12 @@ class SimDeviceData {
void CancelValueChangedCallback(int32_t uid);
int32_t RegisterValueResetCallback(HAL_SimValueHandle handle, void* param,
HALSIM_SimValueCallback callback,
bool initialNotify);
void CancelValueResetCallback(int32_t uid);
HAL_SimValueHandle GetValueHandle(HAL_SimDeviceHandle device,
const char* name);

View File

@@ -5,7 +5,7 @@ project(imgui-download NONE)
include(ExternalProject)
ExternalProject_Add(glfw3
GIT_REPOSITORY https://github.com/glfw/glfw.git
GIT_TAG 63af05c41961c238c2f891e2c923e1b89c1271b6
GIT_TAG 2a5ac9a6d6cbe9f4113c0f17158cb13ab7f263bf
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/glfw-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/glfw-build"
CONFIGURE_COMMAND ""
@@ -23,7 +23,7 @@ ExternalProject_Add(gl3w
)
ExternalProject_Add(imgui
GIT_REPOSITORY https://github.com/ocornut/imgui.git
GIT_TAG v1.76
GIT_TAG v1.79
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/imgui-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/imgui-build"
CONFIGURE_COMMAND ""
@@ -33,7 +33,7 @@ ExternalProject_Add(imgui
)
ExternalProject_Add(implot
GIT_REPOSITORY https://github.com/epezent/implot.git
GIT_TAG 90693cca1bd0ca5f0d49bc9cb8187d56b0b8f289
GIT_TAG a6bab98517b1baa3116db52518dda1eb2d7eaab7
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/implot-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/implot-build"
CONFIGURE_COMMAND ""

View File

@@ -112,7 +112,7 @@ class DispatcherBase : public IDispatcher {
// Condition variable for forced dispatch wakeup (flush)
wpi::mutex m_flush_mutex;
wpi::condition_variable m_flush_cv;
uint64_t m_last_flush;
uint64_t m_last_flush = 0;
bool m_do_flush = false;
// Condition variable for client reconnect (uses user mutex)

View File

@@ -11,7 +11,7 @@ nativeUtils {
niLibVersion = "2020.10.1"
opencvVersion = "3.4.7-5"
googleTestVersion = "1.9.0-5-437e100-1"
imguiVersion = "1.76-10"
imguiVersion = "1.79-2"
wpimathVersion = "-1"
}
}

View File

@@ -8,6 +8,7 @@
#include <glass/support/ExtraGuiWidgets.h>
#include <glass/support/IniSaverInfo.h>
#include <algorithm>
#include <atomic>
#include <cstring>
#include <memory>
@@ -122,6 +123,7 @@ class KeyboardJoystick : public SystemJoystick {
int decKey = -1;
float keyRate = 0.05f;
float decayRate = 0.05f;
float maxAbsValue = 1.0f;
};
AxisConfig m_axisConfig[HAL_kMaxJoystickAxes];
@@ -712,6 +714,12 @@ void KeyboardJoystick::SettingsDisplay() {
EditKey("Decrease", &m_axisConfig[i].decKey);
ImGui::InputFloat("Key Rate", &m_axisConfig[i].keyRate);
ImGui::InputFloat("Decay Rate", &m_axisConfig[i].decayRate);
float maxAbsValue = m_axisConfig[i].maxAbsValue;
if (ImGui::InputFloat("Max Absolute Value", &maxAbsValue)) {
m_axisConfig[i].maxAbsValue = std::clamp(maxAbsValue, -1.0f, 1.0f);
}
ImGui::TreePop();
}
}
@@ -786,8 +794,8 @@ void KeyboardJoystick::Update() {
// increase/decrease while key held down (to saturation); decay back to 0
if (config.incKey >= 0 && io.KeysDown[config.incKey]) {
axisValue += config.keyRate;
if (axisValue > 1.0) {
axisValue = 1.0;
if (axisValue > config.maxAbsValue) {
axisValue = config.maxAbsValue;
}
} else if (axisValue > 0) {
if (axisValue < config.decayRate) {
@@ -799,8 +807,8 @@ void KeyboardJoystick::Update() {
if (config.decKey >= 0 && io.KeysDown[config.decKey]) {
axisValue -= config.keyRate;
if (axisValue < -1.0) {
axisValue = -1.0;
if (axisValue < -config.maxAbsValue) {
axisValue = -config.maxAbsValue;
}
} else if (axisValue < 0) {
if (axisValue > -config.decayRate) {
@@ -937,6 +945,8 @@ void KeyboardJoystick::ReadIni(wpi::StringRef name, wpi::StringRef value) {
std::sscanf(value.data(), "%f", &m_axisConfig[index].keyRate);
} else if (name == "decayRate") {
std::sscanf(value.data(), "%f", &m_axisConfig[index].decayRate);
} else if (name == "maxAbsValue") {
std::sscanf(value.data(), "%f", &m_axisConfig[index].maxAbsValue);
}
} else if (name.startswith("button")) {
name = name.drop_front(6);
@@ -1010,8 +1020,9 @@ void KeyboardJoystick::WriteIni(ImGuiTextBuffer* out_buf) const {
auto& c = m_axisConfig[i];
out_buf->appendf(
"axis%dincKey=%d\naxis%ddecKey=%d\naxis%dkeyRate=%f\n"
"axis%ddecayRate=%f\n",
i, c.incKey, i, c.decKey, i, c.keyRate, i, c.decayRate);
"axis%ddecayRate=%f\naxis%dmaxAbsValue=%f\n",
i, c.incKey, i, c.decKey, i, c.keyRate, i, c.decayRate, i,
c.maxAbsValue);
}
for (int i = 0; i < m_data.buttons.count; ++i) {
out_buf->appendf("button%d=%d\n", i, m_buttonKey[i]);
@@ -1337,7 +1348,19 @@ static void DisplaySystemJoysticks() {
DisplaySystemJoystick(*gGlfwJoysticks[i], i);
}
for (size_t i = 0; i < gKeyboardJoysticks.size(); ++i) {
DisplaySystemJoystick(*gKeyboardJoysticks[i], i + GLFW_JOYSTICK_LAST + 1);
auto joy = gKeyboardJoysticks[i].get();
DisplaySystemJoystick(*joy, i + GLFW_JOYSTICK_LAST + 1);
if (ImGui::BeginPopupContextItem()) {
char buf[64];
std::snprintf(buf, sizeof(buf), "%s Settings", joy->GetName());
if (ImGui::MenuItem(buf)) {
if (auto win = DriverStationGui::dsManager.GetWindow(buf)) {
win->SetVisible(true);
}
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
}

View File

@@ -0,0 +1,516 @@
asyncapi: 2.0.0
info:
title: WPILib WebSocket Remote Endpoint API
version: "1.0.0"
description: |
API to route WPILib HAL calls over WebSockets.
license:
name: WPILib BSD
channels:
wpilibws:
description: General channel for WPILib WebSocket messages
publish:
operationId: wpilibwsPublish
message:
$ref: "#/components/messages/wpilibwsMsg"
subscribe:
operationId: wpilibwsSubscribe
message:
$ref: "#/components/messages/wpilibwsMsg"
components:
messages:
wpilibwsMsg:
title: WPILib WebSocket Message
summary: Message envelope. Note that the "data" field contains a diff of the current state of a particular device. E.g. If only the "value" changes for a DIO device, then only the "<>value" field will be sent.
contentType: application/json
examples:
- payload:
type: PWM
device: "1"
data:
"<speed": 0.5
- payload:
type: DIO
device: "3"
data:
"<init": true
payload:
type: object
oneOf:
- $ref: "#/components/schemas/accelData"
- $ref: "#/components/schemas/aiData"
- $ref: "#/components/schemas/dioData"
- $ref: "#/components/schemas/dpwmData"
- $ref: "#/components/schemas/driverstationData"
- $ref: "#/components/schemas/dutycycleData"
- $ref: "#/components/schemas/encoderData"
- $ref: "#/components/schemas/gyroData"
- $ref: "#/components/schemas/joystickData"
- $ref: "#/components/schemas/pwmData"
- $ref: "#/components/schemas/relayData"
- $ref: "#/components/schemas/solenoidData"
- $ref: "#/components/schemas/roborioData"
schemas:
accelData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Accel
device:
type: string
description: Arbitrary device name
data:
type: object
description: "Accelerometer Data (type: Accelerometer, device: channel number)"
properties:
<init:
type: boolean
description: "If accelerometer is initialized in the robot program"
<range:
type: number
description: "Desired range in Gs"
">x":
type: number
description: "Acceleration in Gs "
">y":
type: number
description: "Acceleration in Gs "
">z":
type: number
description: "Acceleration in Gs "
aiData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: AI
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Analog Input Data (type: AI, device: channel number)"
properties:
<init:
type: boolean
description: "If analog input is initialized in the robot program"
">voltage":
type: number
description: "Input voltage, in volts"
dioData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: DIO
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Digital Input/Output Data (type: DIO, device: channel number)"
properties:
<init:
type: boolean
description: "If DIO is initialized in the robot program"
<input:
type: boolean
description: "True if input, false if output"
<>value:
type: boolean
description: "Input or output state"
dpwmData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: dPWM
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Duty Cycle Output Data (type: dPWM, device: channel number)"
properties:
<init:
type: boolean
description: "If output is initialized in the robot program"
<duty_cycle:
type: number
description: "Duty cycle %"
minimum: 0.0
maximum: 1.0
<dio_pin:
type: integer
description: "DIO pin number"
driverstationData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: DriverStation
device:
type: string
description: Should be left blank
data:
type: object
description: "Driver Station Data (type: DriverStation)"
properties:
">new_data":
type: boolean
description: "One shot. If set to true in a message, notifies the robot program that new DS and Joystick data is available."
">enabled":
type: boolean
description: "True to enable the robot program"
">autonomous":
type: boolean
description: "True for autonomous mode; false for teleoperated mode"
">test":
type: boolean
description: "True for test mode; false for other modes"
">estop":
type: boolean
description: "True to emergency stop (no motor outputs)"
">fms":
type: boolean
description: "True if the DS is connected to a Field Management System (FMS)"
">ds":
type: boolean
description: "True if a DS application is connected"
">station":
type: string
description: "Station color and number; supported values are 'red1', 'red2', 'red3', 'blue1', 'blue2', 'blue3'."
">match_time":
type: number
description: "Match time countdown, in seconds, for each match period (e.g. for 15 second period, starts at 15 and counts down to 0). If not in a match, -1."
">game_data":
type: string
description: "Game-specific data; arbitrary string contents"
dutycycleData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: DutyCycle
device:
type: string
description: Arbitrary device name
data:
type: object
description: "Duty Cycle Input Data (type: DutyCycle, device: channel number)"
properties:
">connected":
type: boolean
description: "True if the encoder is connected"
">position":
type: number
description: "The position in rotations"
encoderData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Encoder
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Quadrature Encoder Data (type: Encoder, device: channel number)"
properties:
<init:
type: boolean
description: "If encoder is initialized in the robot program"
<channel_a:
type: integer
description: "Digital channel number for 'A' phase"
<channel_b:
type: integer
description: "Digital channel number for 'B' phase"
<samples_to_avg:
type: integer
description: "Number of samples to average for period measurement"
">count":
type: integer
description: "Accumulated count (pulses)"
">period":
type: number
description: "Period between pulses in seconds"
gyroData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Gyro
device:
type: string
description: Arbitrary device name
data:
type: object
description: "Gyro Data (type: Gyro, device: channel number)"
properties:
<init:
type: boolean
description: "If gyro is initialized in the robot program"
<range:
type: number
description: "Gyro range in degrees/second (optional)"
">connected":
type: boolean
description: "True if the gyro is connected"
">angle_x":
type: number
description: "The gyro angle in degrees"
">angle_y":
type: number
description: "The gyro angle in degrees"
">angle_z":
type: number
description: "The gyro angle in degrees"
">rate_x":
type: number
description: "The current gyro angular rate of change in degrees/second"
">rate_y":
type: number
description: "The current gyro angular rate of change in degrees/second"
">rate_z":
type: number
description: "The current gyro angular rate of change in degrees/second"
joystickData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Joystick
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Joystick Data (type: Joystick, device: channel number)"
properties:
">axes":
type: array
items:
type: number
description: "Value of an individual axis on this joystick"
minimum: -1.0
maximum: 1.0
">povs":
type: array
description: "One array element per POV; value is a"
items:
type: integer
description: "State of all POV switches on this joystick; an angle in degrees of the POV (e.g. 0, 90, 315) if pressed, or -1 if the POV is not pressed"
">buttons":
type: array
description: State of all buttons on this joystick
items:
type: boolean
description: Pressed state of an individual button
<rumble_left:
type: number
description: "Left rumble"
minimum: 0.0
maximum: 1.0
<rumble_right:
type: number
description: "Right rumble"
minimum: 0.0
maximum: 1.0
pwmData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: PWM
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "PWM Output Data (type: PWM, device: channel number)"
properties:
<init:
type: boolean
description: "If PWM is initialized in the robot program"
<speed:
type: number
description: "Speed"
minimum: -1.0
maximum: 1.0
<position:
type: number
description: "Servo position"
minimum: 0.0
maximum: 1.0
relayData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Relay
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Relay Output Data (type: Relay, device: channel number)"
properties:
<init_fwd:
type: boolean
description: "If relay forward direction is initialized in the robot program"
<init_rev:
type: boolean
description: "If relay reverse direction is initialized in the robot program"
<fwd:
type: boolean
description: "True if forward direction is enabled"
<rev:
type: boolean
description: "True if reverse direction is enabled"
solenoidData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: Solenoid
device:
type: string
description: Device Identifier (usually channel)
data:
type: object
description: "Solenoid Data (type: Solenoid, device: channel number)"
properties:
<init:
type: boolean
description: "If Solenoid is initialized in the robot program"
<output:
type: boolean
description: "The state of the solenoid"
roborioData:
type: object
required:
- type
- device
properties:
type:
type: string
description: Device Type (e.g. DIO/AI/PWM/Encoder etc)
const: RoboRIO
device:
type: string
description: Should be left blank
data:
type: object
description: "RoboRIO Data (type: RoboRIO)"
properties:
">fpga_button":
type: boolean
description: "FPGA button state"
">vin_voltage":
type: number
description: "Vin rail voltage"
">vin_current":
type: number
description: "Vin rail current"
">6v_voltage":
type: number
description: "6V rail voltage"
">6v_current":
type: number
description: "6V rail current"
">6v_active":
type: boolean
description: "True if 6V rail active, false if inactive"
">6v_faults":
type: integer
description: "Number of faults on 6V rail"
">5v_voltage":
type: number
description: "5V rail voltage"
">5v_current":
type: number
description: "5V rail current"
">5v_active":
type: boolean
description: "True if 5V rail active, false if inactive"
">5v_faults":
type: integer
description: "Number of faults on 5V rail"
">3v3_voltage":
type: number
description: "3.3V rail voltage"
">3v3_current":
type: number
description: "3.3V rail current"
">3v3_active":
type: boolean
description: "True if 3.3V rail active, false if inactive"
">3v3_faults":
type: integer
description: "Number of faults on 3.3V rail"

View File

@@ -71,6 +71,7 @@ void HALSimWSProviderSimDevice::OnNetValueChanged(const wpi::json& json) {
break;
case HAL_DOUBLE:
value.data.v_double = it.value();
value.data.v_double -= vd->second->doubleOffset;
break;
case HAL_ENUM: {
if (it->is_string()) {
@@ -97,9 +98,11 @@ void HALSimWSProviderSimDevice::OnNetValueChanged(const wpi::json& json) {
}
case HAL_INT:
value.data.v_int = it.value();
value.data.v_int -= vd->second->intOffset;
break;
case HAL_LONG:
value.data.v_long = it.value();
value.data.v_long -= vd->second->intOffset;
break;
default:
break;
@@ -186,7 +189,8 @@ void HALSimWSProviderSimDevice::OnValueChanged(SimDeviceValueData* valueData,
ProcessHalCallback({{valueData->key, value->data.v_boolean}});
break;
case HAL_DOUBLE:
ProcessHalCallback({{valueData->key, value->data.v_double}});
ProcessHalCallback(
{{valueData->key, value->data.v_double + valueData->doubleOffset}});
break;
case HAL_ENUM: {
int v = value->data.v_enum;
@@ -198,10 +202,12 @@ void HALSimWSProviderSimDevice::OnValueChanged(SimDeviceValueData* valueData,
break;
}
case HAL_INT:
ProcessHalCallback({{valueData->key, value->data.v_int}});
ProcessHalCallback(
{{valueData->key, value->data.v_int + valueData->intOffset}});
break;
case HAL_LONG:
ProcessHalCallback({{valueData->key, value->data.v_long}});
ProcessHalCallback(
{{valueData->key, value->data.v_long + valueData->intOffset}});
break;
default:
break;
@@ -209,6 +215,33 @@ void HALSimWSProviderSimDevice::OnValueChanged(SimDeviceValueData* valueData,
}
}
void HALSimWSProviderSimDevice::OnValueResetStatic(
const char* name, void* param, HAL_SimValueHandle handle, int32_t direction,
const struct HAL_Value* value) {
auto valueData = (reinterpret_cast<SimDeviceValueData*>(param));
valueData->device->OnValueReset(valueData, value);
}
void HALSimWSProviderSimDevice::OnValueReset(SimDeviceValueData* valueData,
const struct HAL_Value* value) {
switch (value->type) {
case HAL_BOOLEAN:
case HAL_ENUM:
break;
case HAL_DOUBLE:
valueData->doubleOffset += value->data.v_double;
break;
case HAL_INT:
valueData->intOffset += value->data.v_int;
break;
case HAL_LONG:
valueData->intOffset += value->data.v_long;
break;
default:
break;
}
}
void HALSimWSProviderSimDevice::ProcessHalCallback(const wpi::json& payload) {
auto ws = m_ws.lock();
if (ws) {

View File

@@ -28,6 +28,8 @@ struct SimDeviceValueData {
std::vector<std::string> options;
std::vector<double> optionValues;
HAL_Type valueType;
double doubleOffset = 0;
int64_t intOffset = 0;
};
class HALSimWSProviderSimDevice : public HALSimWSBaseProvider {
@@ -63,6 +65,12 @@ class HALSimWSProviderSimDevice : public HALSimWSBaseProvider {
void OnValueChanged(SimDeviceValueData* valueData,
const struct HAL_Value* value);
static void OnValueResetStatic(const char* name, void* param,
HAL_SimValueHandle handle, int32_t direction,
const struct HAL_Value* value);
void OnValueReset(SimDeviceValueData* valueData,
const struct HAL_Value* value);
void CancelCallbacks();
wpi::StringMap<std::unique_ptr<SimDeviceValueData>> m_valueHandles;

View File

@@ -3,8 +3,6 @@
suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files=".*sim.*"
checks="(LineLength|EmptyLineSeparator|ParameterName|ImportOrder|AbbreviationAsWordInName|JavadocMethod|NoFinalizer)" />
<suppress files=".*test.*" checks="MissingJavadocMethod" />
<suppress files=".*wpilibjIntegrationTests.*"
checks="MissingJavadocMethod" />

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
// 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.
//
// Portable File Dialogs

View File

@@ -193,9 +193,11 @@ bool gui::Initialize(const char* title, int width, int height) {
}
if (!gContext->loadedWidthHeight) {
#ifndef __APPLE__
if (windowScale == 1.0) {
glfwGetWindowContentScale(gContext->window, &windowScale, nullptr);
}
#endif
// force user scale if window scale is smaller
if (windowScale <= 0.5) {
gContext->userScale = 0;
@@ -284,7 +286,9 @@ void gui::CommonRenderFrame() {
// Scale based on OS window content scaling
float windowScale = 1.0;
#ifndef __APPLE__
glfwGetWindowContentScale(gContext->window, &windowScale, nullptr);
#endif
// map to closest font size: 0 = 0.5x, 1 = 0.75x, 2 = 1.0x, 3 = 1.25x,
// 4 = 1.5x, 5 = 1.75x, 6 = 2x
gContext->fontScale = std::clamp(
@@ -394,12 +398,14 @@ void gui::ConfigurePlatformSaveFile(const std::string& name) {
gContext->iniPath = name;
#if defined(_MSC_VER)
const char* env = std::getenv("APPDATA");
if (env)
if (env) {
gContext->iniPath = env + std::string("/" + name);
}
#elif defined(__APPLE__)
const char* env = std::getenv("HOME");
if (env)
if (env) {
gContext->iniPath = env + std::string("/Library/Preferences/" + name);
}
#else
const char* xdg = std::getenv("XDG_CONFIG_HOME");
const char* env = std::getenv("HOME");

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
// 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.
#define GLFW_INCLUDE_NONE
#define GLFW_EXPOSE_NATIVE_COCOA

View File

@@ -31,7 +31,7 @@ class SwerveControllerCommandTest : public ::testing::Test {
frc2::Timer m_timer;
frc::Rotation2d m_angle{0_rad};
std::array<frc::SwerveModuleState, 4> m_moduleStates{
wpi::array<frc::SwerveModuleState, 4> m_moduleStates{
frc::SwerveModuleState{}, frc::SwerveModuleState{},
frc::SwerveModuleState{}, frc::SwerveModuleState{}};
@@ -60,7 +60,7 @@ class SwerveControllerCommandTest : public ::testing::Test {
void TearDown() override { frc::sim::ResumeTiming(); }
std::array<frc::SwerveModuleState, 4> getCurrentWheelSpeeds() {
wpi::array<frc::SwerveModuleState, 4> getCurrentWheelSpeeds() {
return m_moduleStates;
}

View File

@@ -114,10 +114,7 @@ double ADXRS450_Gyro::GetRate() const {
void ADXRS450_Gyro::Reset() {
if (m_simAngle) {
m_simAngle.Set(0.0);
}
if (m_simRate) {
m_simRate.Set(0.0);
m_simAngle.Reset();
}
m_spi.ResetAccumulator();
}

View File

@@ -9,7 +9,7 @@
#include <utility>
#include "frc/RobotController.h"
#include "frc/system/RungeKutta.h"
#include "frc/system/NumericalIntegration.h"
using namespace frc;
using namespace frc::sim;
@@ -56,8 +56,7 @@ void DifferentialDrivetrainSim::SetGearing(double newGearing) {
}
void DifferentialDrivetrainSim::Update(units::second_t dt) {
m_x = RungeKutta([this](auto& x, auto& u) { return Dynamics(x, u); }, m_x,
m_u, dt);
m_x = RK4([this](auto& x, auto& u) { return Dynamics(x, u); }, m_x, m_u, dt);
m_y = m_x + frc::MakeWhiteNoiseVector<7>(m_measurementStdDevs);
}

View File

@@ -7,7 +7,7 @@
#include <wpi/MathExtras.h>
#include "frc/StateSpaceUtil.h"
#include "frc/system/RungeKutta.h"
#include "frc/system/NumericalIntegration.h"
#include "frc/system/plant/LinearSystemId.h"
using namespace frc;
@@ -39,12 +39,20 @@ ElevatorSim::ElevatorSim(const DCMotor& gearbox, double gearing,
m_maxHeight(maxHeight),
m_gearing(gearing) {}
bool ElevatorSim::HasHitLowerLimit(const Eigen::Matrix<double, 2, 1>& x) const {
return x(0) < m_minHeight.to<double>();
bool ElevatorSim::WouldHitLowerLimit(units::meter_t elevatorHeight) const {
return elevatorHeight < m_minHeight;
}
bool ElevatorSim::HasHitUpperLimit(const Eigen::Matrix<double, 2, 1>& x) const {
return x(0) > m_maxHeight.to<double>();
bool ElevatorSim::WouldHitUpperLimit(units::meter_t elevatorHeight) const {
return elevatorHeight > m_maxHeight;
}
bool ElevatorSim::HasHitLowerLimit() const {
return WouldHitLowerLimit(units::meter_t(m_y(0)));
}
bool ElevatorSim::HasHitUpperLimit() const {
return WouldHitUpperLimit(units::meter_t(m_y(0)));
}
units::meter_t ElevatorSim::GetPosition() const {
@@ -77,7 +85,7 @@ void ElevatorSim::SetInputVoltage(units::volt_t voltage) {
Eigen::Matrix<double, 2, 1> ElevatorSim::UpdateX(
const Eigen::Matrix<double, 2, 1>& currentXhat,
const Eigen::Matrix<double, 1, 1>& u, units::second_t dt) {
auto updatedXhat = RungeKutta(
auto updatedXhat = RKF45(
[&](const Eigen::Matrix<double, 2, 1>& x,
const Eigen::Matrix<double, 1, 1>& u_)
-> Eigen::Matrix<double, 2, 1> {
@@ -85,10 +93,10 @@ Eigen::Matrix<double, 2, 1> ElevatorSim::UpdateX(
},
currentXhat, u, dt);
// Check for collision after updating x-hat.
if (HasHitLowerLimit(updatedXhat)) {
if (WouldHitLowerLimit(units::meter_t(updatedXhat(0)))) {
return MakeMatrix<2, 1>(m_minHeight.to<double>(), 0.0);
}
if (HasHitUpperLimit(updatedXhat)) {
if (WouldHitUpperLimit(units::meter_t(updatedXhat(0)))) {
return MakeMatrix<2, 1>(m_maxHeight.to<double>(), 0.0);
}
return updatedXhat;

View File

@@ -267,6 +267,6 @@ void RoboRioSim::SetUserFaults3V3(int userFaults3V3) {
HALSIM_SetRoboRioUserFaults3V3(userFaults3V3);
}
void ResetData() {
void RoboRioSim::ResetData() {
HALSIM_ResetRoboRioData();
}

View File

@@ -20,6 +20,14 @@ hal::SimValue SimDeviceSim::GetValue(const char* name) const {
return HALSIM_GetSimValueHandle(m_handle, name);
}
hal::SimInt SimDeviceSim::GetInt(const char* name) const {
return HALSIM_GetSimValueHandle(m_handle, name);
}
hal::SimLong SimDeviceSim::GetLong(const char* name) const {
return HALSIM_GetSimValueHandle(m_handle, name);
}
hal::SimDouble SimDeviceSim::GetDouble(const char* name) const {
return HALSIM_GetSimValueHandle(m_handle, name);
}

View File

@@ -9,7 +9,7 @@
#include <units/voltage.h>
#include <wpi/MathExtras.h>
#include "frc/system/RungeKutta.h"
#include "frc/system/NumericalIntegration.h"
#include "frc/system/plant/LinearSystemId.h"
using namespace frc;
@@ -39,14 +39,20 @@ SingleJointedArmSim::SingleJointedArmSim(
gearbox, gearing, armLength, minAngle, maxAngle, mass,
simulateGravity, measurementStdDevs) {}
bool SingleJointedArmSim::HasHitLowerLimit(
const Eigen::Matrix<double, 2, 1>& x) const {
return x(0) < m_minAngle.to<double>();
bool SingleJointedArmSim::WouldHitLowerLimit(units::radian_t armAngle) const {
return armAngle < m_minAngle;
}
bool SingleJointedArmSim::HasHitUpperLimit(
const Eigen::Matrix<double, 2, 1>& x) const {
return x(0) > m_maxAngle.to<double>();
bool SingleJointedArmSim::WouldHitUpperLimit(units::radian_t armAngle) const {
return armAngle > m_maxAngle;
}
bool SingleJointedArmSim::HasHitLowerLimit() const {
return WouldHitLowerLimit(units::radian_t(m_y(0)));
}
bool SingleJointedArmSim::HasHitUpperLimit() const {
return WouldHitUpperLimit(units::radian_t(m_y(0)));
}
units::radian_t SingleJointedArmSim::GetAngle() const {
@@ -82,7 +88,7 @@ Eigen::Matrix<double, 2, 1> SingleJointedArmSim::UpdateX(
// We therefore find that f(x, u) = Ax + Bu + [[0] [m * g * r / I *
// std::cos(theta)]]
auto updatedXhat = RungeKutta(
Eigen::Matrix<double, 2, 1> updatedXhat = RKF45(
[&](const auto& x, const auto& u) -> Eigen::Matrix<double, 2, 1> {
Eigen::Matrix<double, 2, 1> xdot = m_plant.A() * x + m_plant.B() * u;
@@ -96,9 +102,9 @@ Eigen::Matrix<double, 2, 1> SingleJointedArmSim::UpdateX(
currentXhat, u, dt);
// Check for collisions.
if (HasHitLowerLimit(updatedXhat)) {
if (WouldHitLowerLimit(units::radian_t(updatedXhat(0)))) {
return MakeMatrix<2, 1>(m_minAngle.to<double>(), 0.0);
} else if (HasHitUpperLimit(updatedXhat)) {
} else if (WouldHitUpperLimit(units::radian_t(updatedXhat(0)))) {
return MakeMatrix<2, 1>(m_maxAngle.to<double>(), 0.0);
}
return updatedXhat;

View File

@@ -46,8 +46,9 @@ class Notifier : public ErrorBase {
* This is useful for reducing scheduling jitter on processes which are
* sensitive to timing variance, like model-based control.
*
* @param priority The FIFO real-time scheduler priority ([0..100] where a
* lower number represents higher priority).
* @param priority The FIFO real-time scheduler priority ([1..99] where a
* higher number represents higher priority). See "man 7
* sched" for more details.
* @param handler The handler is called at the notification time which is set
* using StartSingle or StartPeriodic.
*/

View File

@@ -12,16 +12,20 @@ namespace frc {
* Get the thread priority for the specified thread.
*
* @param thread Reference to the thread to get the priority for.
* @param isRealTime Set to true if thread is realtime, otherwise false.
* @return The current thread priority. Scaled 1-99, with 1 being highest.
* @param isRealTime Set to true if thread is real-time, otherwise false.
* @return The current thread priority. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is 0. See
* "man 7 sched" for details.
*/
int GetThreadPriority(std::thread& thread, bool* isRealTime);
/**
* Get the thread priority for the current thread
*
* @param isRealTime Set to true if thread is realtime, otherwise false.
* @return The current thread priority. Scaled 1-99.
* @param isRealTime Set to true if thread is real-time, otherwise false.
* @return The current thread priority. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is 0. See
* "man 7 sched" for details.
*/
int GetCurrentThreadPriority(bool* isRealTime);
@@ -29,26 +33,24 @@ int GetCurrentThreadPriority(bool* isRealTime);
* Sets the thread priority for the specified thread
*
* @param thread Reference to the thread to set the priority of.
* @param realTime Set to true to set a realtime priority, false for standard
* @param realTime Set to true to set a real-time priority, false for standard
* priority.
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest. On RoboRIO, priority is ignored for non realtime
* setting.
*
* @return The success state of setting the priority
* @param priority Priority to set the thread to. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is forced to
* 0. See "man 7 sched" for more details.
* @return True on success.
*/
bool SetThreadPriority(std::thread& thread, bool realTime, int priority);
/**
* Sets the thread priority for the current thread
*
* @param realTime Set to true to set a realtime priority, false for standard
* @param realTime Set to true to set a real-time priority, false for standard
* priority.
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest. On RoboRIO, priority is ignored for non realtime
* setting.
*
* @return The success state of setting the priority
* @param priority Priority to set the thread to. For real-time, this is 1-99
* with 99 being highest. For non-real-time, this is forced to
* 0. See "man 7 sched" for more details.
* @return True on success.
*/
bool SetCurrentThreadPriority(bool realTime, int priority);

View File

@@ -52,39 +52,130 @@ class AddressableLEDSim {
*/
static AddressableLEDSim CreateForIndex(int index);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback on the Initialized property.
*
* @param callback the callback that will be called whenever the Initialized
* property is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object storing this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Change the Initialized value of the LED strip.
*
* @param initialized the new value
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterOutputPortCallback(
/**
* Register a callback on the output port.
*
* @param callback the callback that will be called whenever the output port
* is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterOutputPortCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the output port.
*
* @return the output port
*/
int GetOutputPort() const;
/**
* Change the output port.
*
* @param outputPort the new output port
*/
void SetOutputPort(int outputPort);
std::unique_ptr<CallbackStore> RegisterLengthCallback(NotifyCallback callback,
bool initialNotify);
int GetLength() const;
void SetLength(int length);
std::unique_ptr<CallbackStore> RegisterRunningCallback(
/**
* Register a callback on the length.
*
* @param callback the callback that will be called whenever the length is
* changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterLengthCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the length of the LED strip.
*
* @return the length
*/
int GetLength() const;
/**
* Change the length of the LED strip.
*
* @param length the new value
*/
void SetLength(int length);
/**
* Register a callback on whether the LEDs are running.
*
* @param callback the callback that will be called whenever the LED state is
* changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterRunningCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the LEDs are running.
*
* @return true if they are
*/
int GetRunning() const;
/**
* Change whether the LEDs are active.
*
* @param running the new value
*/
void SetRunning(bool running);
std::unique_ptr<CallbackStore> RegisterDataCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback on the LED data.
*
* @param callback the callback that will be called whenever the LED data is
* changed
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterDataCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the LED data.
*
* @param data output parameter to fill with LED data
* @return the length of the LED data
*/
int GetData(struct HAL_AddressableLEDData* data) const;
/**
* Change the LED data.
*
* @param data the new data
* @param length the length of the LED data
*/
void SetData(struct HAL_AddressableLEDData* data, int length);
private:

View File

@@ -28,7 +28,7 @@ class AnalogEncoderSim {
explicit AnalogEncoderSim(const AnalogEncoder& encoder);
/**
* Set the position using an {@link Rotation2d}.
* Set the position using an Rotation2d.
*
* @param angle The angle.
*/
@@ -47,7 +47,7 @@ class AnalogEncoderSim {
units::turn_t GetTurns();
/**
* Get the position as a {@link Rotation2d}.
* Get the position as a Rotation2d.
*/
Rotation2d GetPosition();

View File

@@ -33,27 +33,82 @@ class AnalogGyroSim {
*/
explicit AnalogGyroSim(int channel);
std::unique_ptr<CallbackStore> RegisterAngleCallback(NotifyCallback callback,
bool initialNotify);
double GetAngle() const;
void SetAngle(double angle);
std::unique_ptr<CallbackStore> RegisterRateCallback(NotifyCallback callback,
bool initialNotify);
double GetRate() const;
void SetRate(double rate);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback on the angle.
*
* @param callback the callback that will be called whenever the angle changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterAngleCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the current angle of the gyro.
*
* @return the angle measured by the gyro
*/
double GetAngle() const;
/**
* Change the angle measured by the gyro.
*
* @param angle the new value
*/
void SetAngle(double angle);
/**
* Register a callback on the rate.
*
* @param callback the callback that will be called whenever the rate changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterRateCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the rate of angle change on this gyro.
*
* @return the rate
*/
double GetRate() const;
/**
* Change the rate of the gyro.
*
* @param rate the new rate
*/
void SetRate(double rate);
/**
* Register a callback on whether the gyro is initialized.
*
* @param callback the callback that will be called whenever the gyro is
* initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the gyro is initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Set whether this gyro is initialized.
*
* @param initialized the new value
*/
void SetInitialized(bool initialized);
/**
* Reset all simulation data for this object.
*/
void ResetData();
private:

View File

@@ -33,69 +33,237 @@ class AnalogInputSim {
*/
explicit AnalogInputSim(int channel);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback on whether the analog input is initialized.
*
* @param callback the callback that will be called whenever the analog input
* is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if this analog input has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Change whether this analog input has been initialized.
*
* @param initialized the new value
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterAverageBitsCallback(
/**
* Register a callback on the number of average bits.
*
* @param callback the callback that will be called whenever the number of
* average bits is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterAverageBitsCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the number of average bits.
*
* @return the number of average bits
*/
int GetAverageBits() const;
/**
* Change the number of average bits.
*
* @param averageBits the new value
*/
void SetAverageBits(int averageBits);
std::unique_ptr<CallbackStore> RegisterOversampleBitsCallback(
/**
* Register a callback on the amount of oversampling bits.
*
* @param callback the callback that will be called whenever the oversampling
* bits are changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterOversampleBitsCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the amount of oversampling bits.
*
* @return the amount of oversampling bits
*/
int GetOversampleBits() const;
/**
* Change the amount of oversampling bits.
*
* @param oversampleBits the new value
*/
void SetOversampleBits(int oversampleBits);
std::unique_ptr<CallbackStore> RegisterVoltageCallback(
/**
* Register a callback on the voltage.
*
* @param callback the callback that will be called whenever the voltage is
* changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterVoltageCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the voltage.
*
* @return the voltage
*/
double GetVoltage() const;
/**
* Change the voltage.
*
* @param voltage the new value
*/
void SetVoltage(double voltage);
std::unique_ptr<CallbackStore> RegisterAccumulatorInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on whether the accumulator is initialized.
*
* @param callback the callback that will be called whenever the accumulator
* is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterAccumulatorInitializedCallback(NotifyCallback callback,
bool initialNotify);
/**
* Check if the accumulator has been initialized.
*
* @return true if initialized
*/
bool GetAccumulatorInitialized() const;
/**
* Change whether the accumulator has been initialized.
*
* @param accumulatorInitialized the new value
*/
void SetAccumulatorInitialized(bool accumulatorInitialized);
std::unique_ptr<CallbackStore> RegisterAccumulatorValueCallback(
/**
* Register a callback on the accumulator value.
*
* @param callback the callback that will be called whenever the accumulator
* value is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterAccumulatorValueCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the accumulator value.
*
* @return the accumulator value
*/
int64_t GetAccumulatorValue() const;
/**
* Change the accumulator value.
*
* @param accumulatorValue the new value
*/
void SetAccumulatorValue(int64_t accumulatorValue);
std::unique_ptr<CallbackStore> RegisterAccumulatorCountCallback(
/**
* Register a callback on the accumulator count.
*
* @param callback the callback that will be called whenever the accumulator
* count is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterAccumulatorCountCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the accumulator count.
*
* @return the accumulator count.
*/
int64_t GetAccumulatorCount() const;
/**
* Change the accumulator count.
*
* @param accumulatorCount the new count.
*/
void SetAccumulatorCount(int64_t accumulatorCount);
std::unique_ptr<CallbackStore> RegisterAccumulatorCenterCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on the accumulator center.
*
* @param callback the callback that will be called whenever the accumulator
* center is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterAccumulatorCenterCallback(NotifyCallback callback,
bool initialNotify);
/**
* Get the accumulator center.
*
* @return the accumulator center
*/
int GetAccumulatorCenter() const;
/**
* Change the accumulator center.
*
* @param accumulatorCenter the new center
*/
void SetAccumulatorCenter(int accumulatorCenter);
std::unique_ptr<CallbackStore> RegisterAccumulatorDeadbandCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on the accumulator deadband.
*
* @param callback the callback that will be called whenever the accumulator
* deadband is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterAccumulatorDeadbandCallback(NotifyCallback callback,
bool initialNotify);
/**
* Get the accumulator deadband.
*
* @return the accumulator deadband
*/
int GetAccumulatorDeadband() const;
/**
* Change the accumulator deadband.
*
* @param accumulatorDeadband the new deadband
*/
void SetAccumulatorDeadband(int accumulatorDeadband);
/**
* Reset all simulation data for this object.
*/
void ResetData();
private:

View File

@@ -33,20 +33,57 @@ class AnalogOutputSim {
*/
explicit AnalogOutputSim(int channel);
std::unique_ptr<CallbackStore> RegisterVoltageCallback(
/**
* Register a callback to be run whenever the voltage changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterVoltageCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the analog output voltage.
*
* @return the voltage on this analog output
*/
double GetVoltage() const;
/**
* Set the analog output voltage.
*
* @param voltage the new voltage on this analog output
*/
void SetVoltage(double voltage);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when this analog output is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether this analog output has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether this analog output has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
/**
* Reset all simulation data on this object.
*/
void ResetData();
private:

View File

@@ -45,27 +45,86 @@ class AnalogTriggerSim {
*/
static AnalogTriggerSim CreateForIndex(int index);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback on whether the analog trigger is initialized.
*
* @param callback the callback that will be called whenever the analog
* trigger is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if this analog trigger has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Change whether this analog trigger has been initialized.
*
* @param initialized the new value
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterTriggerLowerBoundCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on the lower bound.
*
* @param callback the callback that will be called whenever the lower bound
* is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterTriggerLowerBoundCallback(NotifyCallback callback,
bool initialNotify);
/**
* Get the lower bound.
*
* @return the lower bound
*/
double GetTriggerLowerBound() const;
/**
* Change the lower bound.
*
* @param triggerLowerBound the new lower bound
*/
void SetTriggerLowerBound(double triggerLowerBound);
std::unique_ptr<CallbackStore> RegisterTriggerUpperBoundCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on the upper bound.
*
* @param callback the callback that will be called whenever the upper bound
* is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterTriggerUpperBoundCallback(NotifyCallback callback,
bool initialNotify);
/**
* Get the upper bound.
*
* @return the upper bound
*/
double GetTriggerUpperBound() const;
/**
* Change the upper bound.
*
* @param triggerUpperBound the new upper bound
*/
void SetTriggerUpperBound(double triggerUpperBound);
/**
* Reset all simulation data for this object.
*/
void ResetData();
private:

View File

@@ -33,41 +33,129 @@ class BuiltInAccelerometerSim {
*/
explicit BuiltInAccelerometerSim(const BuiltInAccelerometer& accel);
std::unique_ptr<CallbackStore> RegisterActiveCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run when this accelerometer activates.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterActiveCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the accelerometer is active.
*
* @return true if active
*/
bool GetActive() const;
/**
* Define whether this accelerometer is active.
*
* @param active the new state
*/
void SetActive(bool active);
std::unique_ptr<CallbackStore> RegisterRangeCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the range changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterRangeCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the range of this accelerometer.
*
* @return the accelerometer range
*/
HAL_AccelerometerRange GetRange() const;
/**
* Change the range of this accelerometer.
*
* @param range the new accelerometer range
*/
void SetRange(HAL_AccelerometerRange range);
std::unique_ptr<CallbackStore> RegisterXCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the X axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterXCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the X axis value.
*
* @return the X axis measurement
*/
double GetX() const;
/**
* Change the X axis value of the accelerometer.
*
* @param x the new reading of the X axis
*/
void SetX(double x);
std::unique_ptr<CallbackStore> RegisterYCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the Y axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterYCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the Y axis value.
*
* @return the Y axis measurement
*/
double GetY() const;
/**
* Change the Y axis value of the accelerometer.
*
* @param y the new reading of the Y axis
*/
void SetY(double y);
std::unique_ptr<CallbackStore> RegisterZCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the Z axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterZCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the Z axis value.
*
* @return the Z axis measurement
*/
double GetZ() const;
/**
* Change the Z axis value of the accelerometer.
*
* @param z the new reading of the Z axis
*/
void SetZ(double z);
/**
* Reset all simulation data of this object.
*/
void ResetData();
private:

View File

@@ -24,6 +24,9 @@ void ConstBufferCallbackStoreThunk(const char* name, void* param,
const unsigned char* buffer,
unsigned int count);
/**
* Manages simulation callbacks; each object is associated with a callback.
*/
class CallbackStore {
public:
CallbackStore(int32_t i, NotifyCallback cb, CancelCallbackNoIndexFunc ccf);

View File

@@ -41,41 +41,132 @@ class DIOSim {
*/
explicit DIOSim(int channel);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when this DIO is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether this DIO has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether this DIO has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterValueCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the DIO value changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterValueCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the value of the DIO port.
*
* @return the DIO value
*/
bool GetValue() const;
/**
* Change the DIO value.
*
* @param value the new value
*/
void SetValue(bool value);
std::unique_ptr<CallbackStore> RegisterPulseLengthCallback(
/**
* Register a callback to be run whenever the pulse length changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPulseLengthCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the pulse length.
*
* @return the pulse length of this DIO port
*/
double GetPulseLength() const;
/**
* Change the pulse length of this DIO port.
*
* @param pulseLength the new pulse length
*/
void SetPulseLength(double pulseLength);
std::unique_ptr<CallbackStore> RegisterIsInputCallback(
/**
* Register a callback to be run whenever this DIO changes to be an input.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterIsInputCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether this DIO port is currently an Input.
*
* @return true if Input
*/
bool GetIsInput() const;
/**
* Define whether this DIO port is an Input.
*
* @param isInput whether this DIO should be an Input
*/
void SetIsInput(bool isInput);
std::unique_ptr<CallbackStore> RegisterFilterIndexCallback(
/**
* Register a callback to be run whenever the filter index changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterFilterIndexCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the filter index.
*
* @return the filter index of this DIO port
*/
int GetFilterIndex() const;
/**
* Change the filter index of this DIO port.
*
* @param filterIndex the new filter index
*/
void SetFilterIndex(int filterIndex);
/**
* Reset all simulation data of this object.
*/
void ResetData();
private:

View File

@@ -47,27 +47,81 @@ class DigitalPWMSim {
*/
static DigitalPWMSim CreateForIndex(int index);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when this PWM output is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether this PWM output has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether this PWM output has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterDutyCycleCallback(
/**
* Register a callback to be run whenever the duty cycle value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterDutyCycleCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the duty cycle value.
*
* @return the duty cycle value of this PWM output
*/
double GetDutyCycle() const;
/**
* Set the duty cycle value of this PWM output.
*
* @param dutyCycle the new value
*/
void SetDutyCycle(double dutyCycle);
std::unique_ptr<CallbackStore> RegisterPinCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the pin changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPinCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the pin number.
*
* @return the pin number
*/
int GetPin() const;
/**
* Change the pin number.
*
* @param pin the new pin number
*/
void SetPin(int pin);
/**
* Reset all simulation data.
*/
void ResetData();
private:

View File

@@ -18,60 +18,205 @@ namespace frc::sim {
*/
class DriverStationSim {
public:
static std::unique_ptr<CallbackStore> RegisterEnabledCallback(
/**
* Register a callback on whether the DS is enabled.
*
* @param callback the callback that will be called whenever the enabled
* state is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore> RegisterEnabledCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the DS is enabled.
*
* @return true if enabled
*/
static bool GetEnabled();
/**
* Change whether the DS is enabled.
*
* @param enabled the new value
*/
static void SetEnabled(bool enabled);
static std::unique_ptr<CallbackStore> RegisterAutonomousCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on whether the DS is in autonomous mode.
*
* @param callback the callback that will be called on autonomous mode
* entrance/exit
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterAutonomousCallback(NotifyCallback callback, bool initialNotify);
/**
* Check if the DS is in autonomous.
*
* @return true if autonomous
*/
static bool GetAutonomous();
/**
* Change whether the DS is in autonomous.
*
* @param autonomous the new value
*/
static void SetAutonomous(bool autonomous);
static std::unique_ptr<CallbackStore> RegisterTestCallback(
/**
* Register a callback on whether the DS is in test mode.
*
* @param callback the callback that will be called whenever the test mode
* is entered or left
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore> RegisterTestCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the DS is in test.
*
* @return true if test
*/
static bool GetTest();
/**
* Change whether the DS is in test.
*
* @param test the new value
*/
static void SetTest(bool test);
static std::unique_ptr<CallbackStore> RegisterEStopCallback(
/**
* Register a callback on the eStop state.
*
* @param callback the callback that will be called whenever the eStop state
* changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore> RegisterEStopCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if eStop has been activated.
*
* @return true if eStopped
*/
static bool GetEStop();
/**
* Set whether eStop is active.
*
* @param eStop true to activate
*/
static void SetEStop(bool eStop);
static std::unique_ptr<CallbackStore> RegisterFmsAttachedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on whether the FMS is connected.
*
* @param callback the callback that will be called whenever the FMS
* connection changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterFmsAttachedCallback(NotifyCallback callback, bool initialNotify);
/**
* Check if the FMS is connected.
*
* @return true if FMS is connected
*/
static bool GetFmsAttached();
/**
* Change whether the FMS is connected.
*
* @param fmsAttached the new value
*/
static void SetFmsAttached(bool fmsAttached);
static std::unique_ptr<CallbackStore> RegisterDsAttachedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on whether the DS is connected.
*
* @param callback the callback that will be called whenever the DS
* connection changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterDsAttachedCallback(NotifyCallback callback, bool initialNotify);
/**
* Check if the DS is attached.
*
* @return true if attached
*/
static bool GetDsAttached();
/**
* Change whether the DS is attached.
*
* @param dsAttached the new value
*/
static void SetDsAttached(bool dsAttached);
static std::unique_ptr<CallbackStore> RegisterAllianceStationIdCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback on the alliance station ID.
*
* @param callback the callback that will be called whenever the alliance
* station changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterAllianceStationIdCallback(NotifyCallback callback,
bool initialNotify);
/**
* Get the alliance station ID (color + number).
*
* @return the alliance station color and number
*/
static HAL_AllianceStationID GetAllianceStationId();
/**
* Change the alliance station.
*
* @param allianceStationId the new alliance station
*/
static void SetAllianceStationId(HAL_AllianceStationID allianceStationId);
static std::unique_ptr<CallbackStore> RegisterMatchTimeCallback(
/**
* Register a callback on match time.
*
* @param callback the callback that will be called whenever match time
* changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore> RegisterMatchTimeCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the current value of the match timer.
*
* @return the current match time
*/
static double GetMatchTime();
/**
* Sets the match timer.
*
* @param matchTime the new match time
*/
static void SetMatchTime(double matchTime);
/**
@@ -238,6 +383,9 @@ class DriverStationSim {
*/
static void SetReplayNumber(int replayNumber);
/**
* Reset all simulation data for the Driver Station.
*/
static void ResetData();
};
} // namespace frc::sim

View File

@@ -44,27 +44,81 @@ class DutyCycleSim {
*/
static DutyCycleSim CreateForIndex(int index);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when this duty cycle input is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether this duty cycle input has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether this duty cycle input has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterFrequencyCallback(
/**
* Register a callback to be run whenever the frequency changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterFrequencyCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the frequency.
*
* @return the duty cycle frequency
*/
int GetFrequency() const;
/**
* Change the duty cycle frequency.
*
* @param frequency the new frequency
*/
void SetFrequency(int count);
std::unique_ptr<CallbackStore> RegisterOutputCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the output changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterOutputCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the output from this duty cycle port.
*
* @return the output value
*/
double GetOutput() const;
/**
* Change the duty cycle output.
*
* @param output the new output value
*/
void SetOutput(double period);
/**
* Reset all simulation data for the duty cycle output.
*/
void ResetData();
private:

View File

@@ -57,21 +57,35 @@ class ElevatorSim : public LinearSystemSim<2, 1, 1> {
units::meter_t minHeight, units::meter_t maxHeight,
const std::array<double, 1>& measurementStdDevs = {0.0});
/**
* Returns whether the elevator would hit the lower limit.
*
* @param elevatorHeight The elevator height.
* @return Whether the elevator would hit the lower limit.
*/
bool WouldHitLowerLimit(units::meter_t elevatorHeight) const;
/**
* Returns whether the elevator would hit the upper limit.
*
* @param elevatorHeight The elevator height.
* @return Whether the elevator would hit the upper limit.
*/
bool WouldHitUpperLimit(units::meter_t elevatorHeight) const;
/**
* Returns whether the elevator has hit the lower limit.
*
* @param x The current elevator state.
* @return Whether the elevator has hit the lower limit.
*/
bool HasHitLowerLimit(const Eigen::Matrix<double, 2, 1>& x) const;
bool HasHitLowerLimit() const;
/**
* Returns whether the elevator has hit the upper limit.
*
* @param x The current elevator state.
* @return Whether the elevator has hit the upper limit.
*/
bool HasHitUpperLimit(const Eigen::Matrix<double, 2, 1>& x) const;
bool HasHitUpperLimit() const;
/**
* Returns the position of the elevator.

View File

@@ -45,77 +45,261 @@ class EncoderSim {
*/
static EncoderSim CreateForIndex(int index);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback on the Initialized property of the encoder.
*
* @param callback the callback that will be called whenever the Initialized
* property is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the Initialized value of the encoder.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Change the Initialized value of the encoder.
*
* @param initialized the new value
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterCountCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback on the count property of the encoder.
*
* @param callback the callback that will be called whenever the count
* property is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterCountCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the count of the encoder.
*
* @return the count
*/
int GetCount() const;
/**
* Change the count of the encoder.
*
* @param count the new count
*/
void SetCount(int count);
std::unique_ptr<CallbackStore> RegisterPeriodCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback on the period of the encoder.
*
* @param callback the callback that will be called whenever the period is
* changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPeriodCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the period of the encoder.
*
* @return the encoder period
*/
double GetPeriod() const;
/**
* Change the encoder period.
*
* @param period the new period
*/
void SetPeriod(double period);
std::unique_ptr<CallbackStore> RegisterResetCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be called whenever the encoder is reset.
*
* @param callback the callback
* @param initialNotify whether to run the callback on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterResetCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the encoder has been reset.
*
* @return true if reset
*/
bool GetReset() const;
/**
* Change the reset property of the encoder.
*
* @param reset the new value
*/
void SetReset(bool reset);
std::unique_ptr<CallbackStore> RegisterMaxPeriodCallback(
/**
* Register a callback to be run whenever the max period of the encoder is
* changed.
*
* @param callback the callback
* @param initialNotify whether to run the callback on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterMaxPeriodCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the max period of the encoder.
*
* @return the max period of the encoder
*/
double GetMaxPeriod() const;
/**
* Change the max period of the encoder.
*
* @param maxPeriod the new value
*/
void SetMaxPeriod(double maxPeriod);
std::unique_ptr<CallbackStore> RegisterDirectionCallback(
/**
* Register a callback on the direction of the encoder.
*
* @param callback the callback that will be called whenever the direction
* is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterDirectionCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the direction of the encoder.
*
* @return the direction of the encoder
*/
bool GetDirection() const;
/**
* Set the direction of the encoder.
*
* @param direction the new direction
*/
void SetDirection(bool direction);
std::unique_ptr<CallbackStore> RegisterReverseDirectionCallback(
/**
* Register a callback on the reverse direction.
*
* @param callback the callback that will be called whenever the reverse
* direction is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterReverseDirectionCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the reverse direction of the encoder.
*
* @return the reverse direction of the encoder
*/
bool GetReverseDirection() const;
/**
* Set the reverse direction.
*
* @param reverseDirection the new value
*/
void SetReverseDirection(bool reverseDirection);
std::unique_ptr<CallbackStore> RegisterSamplesToAverageCallback(
/**
* Register a callback on the samples-to-average value of this encoder.
*
* @param callback the callback that will be called whenever the
* samples-to-average is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterSamplesToAverageCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the samples-to-average value.
*
* @return the samples-to-average value
*/
int GetSamplesToAverage() const;
/**
* Set the samples-to-average value.
*
* @param samplesToAverage the new value
*/
void SetSamplesToAverage(int samplesToAverage);
std::unique_ptr<CallbackStore> RegisterDistancePerPulseCallback(
/**
* Register a callback on the distance per pulse value of this encoder.
*
* @param callback the callback that will be called whenever the
* distance per pulse is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterDistancePerPulseCallback(
NotifyCallback callback, bool initialNotify);
/**
* Read the distance per pulse of the encoder.
*
* @return the encoder distance per pulse
*/
double GetDistancePerPulse() const;
/**
* Change the encoder distance per pulse.
*
* @param distancePerPulse the new distance per pulse
*/
void SetDistancePerPulse(double distancePerPulse);
/**
* Resets all simulation data for this encoder.
*/
void ResetData();
/**
* Change the encoder distance.
*
* @param distance the new distance
*/
void SetDistance(double distance);
/**
* Read the distance of the encoder.
*
* @return the encoder distance
*/
double GetDistance();
/**
* Change the rate of the encoder.
*
* @param rate the new rate
*/
void SetRate(double rate);
/**
* Get the rate of the encoder.
*
* @return the rate of change
*/
double GetRate();
private:

View File

@@ -38,30 +38,101 @@ class GenericHIDSim {
*/
void NotifyNewData();
/**
* Set the value of a given button.
*
* @param button the button to set
* @param value the new value
*/
void SetRawButton(int button, bool value);
/**
* Set the value of a given axis.
*
* @param axis the axis to set
* @param value the new value
*/
void SetRawAxis(int axis, double value);
/**
* Set the value of a given POV.
*
* @param pov the POV to set
* @param value the new value
*/
void SetPOV(int pov, int value);
/**
* Set the value of the default POV (port 0).
*
* @param value the new value
*/
void SetPOV(int value);
/**
* Set the axis count of this device.
*
* @param count the new axis count
*/
void SetAxisCount(int count);
/**
* Set the POV count of this device.
*
* @param count the new POV count
*/
void SetPOVCount(int count);
/**
* Set the button count of this device.
*
* @param count the new button count
*/
void SetButtonCount(int count);
/**
* Set the type of this device.
*
* @param type the new device type
*/
void SetType(GenericHID::HIDType type);
/**
* Set the name of this device.
*
* @param name the new device name
*/
void SetName(const char* name);
/**
* Set the type of an axis.
*
* @param axis the axis
* @param type the type
*/
void SetAxisType(int axis, int type);
/**
* Read the output of a button.
*
* @param outputNumber the button number
* @return the value of the button (true = pressed)
*/
bool GetOutput(int outputNumber);
/**
* Get the encoded 16-bit integer that passes button values.
*
* @return the button values
*/
int64_t GetOutputs();
/**
* Get the joystick rumble.
*
* @param type the rumble to read
* @return the rumble value
*/
double GetRumble(GenericHID::RumbleType type);
protected:

View File

@@ -31,18 +31,53 @@ class JoystickSim : public GenericHIDSim {
*/
explicit JoystickSim(int port);
/**
* Set the X value of the joystick.
*
* @param value the new X value
*/
void SetX(double value);
/**
* Set the Y value of the joystick.
*
* @param value the new Y value
*/
void SetY(double value);
/**
* Set the Z value of the joystick.
*
* @param value the new Z value
*/
void SetZ(double value);
/**
* Set the twist value of the joystick.
*
* @param value the new twist value
*/
void SetTwist(double value);
/**
* Set the throttle value of the joystick.
*
* @param value the new throttle value
*/
void SetThrottle(double value);
/**
* Set the trigger value of the joystick.
*
* @param state the new value
*/
void SetTrigger(bool state);
/**
* Set the top state of the joystick.
*
* @param state the new state
*/
void SetTop(bool state);
private:

View File

@@ -38,59 +38,204 @@ class PCMSim {
*/
explicit PCMSim(const Compressor& compressor);
std::unique_ptr<CallbackStore> RegisterSolenoidInitializedCallback(
int channel, NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run when a solenoid is initialized on a channel.
*
* @param channel the channel to monitor
* @param callback the callback
* @param initialNotify should the callback be run with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterSolenoidInitializedCallback(int channel, NotifyCallback callback,
bool initialNotify);
/**
* Check if a solenoid has been initialized on a specific channel.
*
* @param channel the channel to check
* @return true if initialized
*/
bool GetSolenoidInitialized(int channel) const;
/**
* Define whether a solenoid has been initialized on a specific channel.
*
* @param channel the channel
* @param solenoidInitialized is there a solenoid initialized on that channel
*/
void SetSolenoidInitialized(int channel, bool solenoidInitialized);
std::unique_ptr<CallbackStore> RegisterSolenoidOutputCallback(
/**
* Register a callback to be run when the solenoid output on a channel
* changes.
*
* @param channel the channel to monitor
* @param callback the callback
* @param initialNotify should the callback be run with the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterSolenoidOutputCallback(
int channel, NotifyCallback callback, bool initialNotify);
/**
* Check the solenoid output on a specific channel.
*
* @param channel the channel to check
* @return the solenoid output
*/
bool GetSolenoidOutput(int channel) const;
/**
* Change the solenoid output on a specific channel.
*
* @param channel the channel to check
* @param solenoidOutput the new solenoid output
*/
void SetSolenoidOutput(int channel, bool solenoidOutput);
std::unique_ptr<CallbackStore> RegisterCompressorInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run when the compressor is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterCompressorInitializedCallback(NotifyCallback callback,
bool initialNotify);
/**
* Check whether the compressor has been initialized.
*
* @return true if initialized
*/
bool GetCompressorInitialized() const;
/**
* Define whether the compressor has been initialized.
*
* @param compressorInitialized whether the compressor is initialized
*/
void SetCompressorInitialized(bool compressorInitialized);
std::unique_ptr<CallbackStore> RegisterCompressorOnCallback(
/**
* Register a callback to be run when the compressor activates.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterCompressorOnCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check if the compressor is on.
*
* @return true if the compressor is active
*/
bool GetCompressorOn() const;
/**
* Set whether the compressor is active.
*
* @param compressorOn the new value
*/
void SetCompressorOn(bool compressorOn);
std::unique_ptr<CallbackStore> RegisterClosedLoopEnabledCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the closed loop state changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterClosedLoopEnabledCallback(NotifyCallback callback,
bool initialNotify);
/**
* Check whether the closed loop compressor control is active.
*
* @return true if active
*/
bool GetClosedLoopEnabled() const;
/**
* Turn on/off the closed loop control of the compressor.
*
* @param closedLoopEnabled whether the control loop is active
*/
void SetClosedLoopEnabled(bool closedLoopEnabled);
std::unique_ptr<CallbackStore> RegisterPressureSwitchCallback(
/**
* Register a callback to be run whenever the pressure switch value changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPressureSwitchCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the value of the pressure switch.
*
* @return the pressure switch value
*/
bool GetPressureSwitch() const;
/**
* Set the value of the pressure switch.
*
* @param pressureSwitch the new value
*/
void SetPressureSwitch(bool pressureSwitch);
std::unique_ptr<CallbackStore> RegisterCompressorCurrentCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the compressor current changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterCompressorCurrentCallback(NotifyCallback callback,
bool initialNotify);
/**
* Read the compressor current.
*
* @return the current of the compressor connected to this module
*/
double GetCompressorCurrent() const;
/**
* Set the compressor current.
*
* @param compressorCurrent the new compressor current
*/
void SetCompressorCurrent(double compressorCurrent);
/**
* Get the current value of all solenoid outputs.
*
* @return the solenoid outputs (1 bit per output)
*/
uint8_t GetAllSolenoidOutputs() const;
/**
* Change all of the solenoid outputs.
*
* @param outputs the new solenoid outputs (1 bit per output)
*/
void SetAllSolenoidOutputs(uint8_t outputs);
/**
* Reset all simulation data for this object.
*/
void ResetData();
private:

View File

@@ -33,38 +33,125 @@ class PDPSim {
*/
explicit PDPSim(const PowerDistributionPanel& pdp);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when the PDP is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the PDP has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether the PDP has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterTemperatureCallback(
/**
* Register a callback to be run whenever the PDP temperature changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterTemperatureCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the temperature of the PDP.
*
* @return the PDP temperature
*/
double GetTemperature() const;
/**
* Define the PDP temperature.
*
* @param temperature the new PDP temperature
*/
void SetTemperature(double temperature);
std::unique_ptr<CallbackStore> RegisterVoltageCallback(
/**
* Register a callback to be run whenever the PDP voltage changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterVoltageCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the PDP voltage.
*
* @return the PDP voltage.
*/
double GetVoltage() const;
/**
* Set the PDP voltage.
*
* @param voltage the new PDP voltage
*/
void SetVoltage(double voltage);
std::unique_ptr<CallbackStore> RegisterCurrentCallback(
/**
* Register a callback to be run whenever the current of a specific channel
* changes.
*
* @param channel the channel
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterCurrentCallback(
int channel, NotifyCallback callback, bool initialNotify);
/**
* Read the current in one of the PDP channels.
*
* @param channel the channel to check
* @return the current in the given channel
*/
double GetCurrent(int channel) const;
/**
* Change the current in the given channel.
*
* @param channel the channel to edit
* @param current the new current for the channel
*/
void SetCurrent(int channel, double current);
/**
* Read the current of all of the PDP channels.
*
* @param currents output array; set to the current in each channel. The
* array must be big enough to hold all the PDP channels
*/
void GetAllCurrents(double* currents) const;
/**
* Change the current in all of the PDP channels.
*
* @param currents array containing the current values for each channel. The
* array must be big enough to hold all the PDP channels
*/
void SetAllCurrents(const double* currents);
/**
* Reset all PDP simulation data.
*/
void ResetData();
private:

View File

@@ -33,48 +33,153 @@ class PWMSim {
*/
explicit PWMSim(int channel);
std::unique_ptr<CallbackStore> RegisterInitializedCallback(
/**
* Register a callback to be run when the PWM is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterInitializedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the PWM has been initialized.
*
* @return true if initialized
*/
bool GetInitialized() const;
/**
* Define whether the PWM has been initialized.
*
* @param initialized whether this object is initialized
*/
void SetInitialized(bool initialized);
std::unique_ptr<CallbackStore> RegisterRawValueCallback(
/**
* Register a callback to be run when the PWM raw value changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterRawValueCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the PWM raw value.
*
* @return the PWM raw value
*/
int GetRawValue() const;
/**
* Set the PWM raw value.
*
* @param rawValue the PWM raw value
*/
void SetRawValue(int rawValue);
std::unique_ptr<CallbackStore> RegisterSpeedCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run when the PWM speed changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterSpeedCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the PWM speed.
*
* @return the PWM speed (-1.0 to 1.0)
*/
double GetSpeed() const;
/**
* Set the PWM speed.
*
* @param speed the PWM speed (-1.0 to 1.0)
*/
void SetSpeed(double speed);
std::unique_ptr<CallbackStore> RegisterPositionCallback(
/**
* Register a callback to be run when the PWM position changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPositionCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the PWM position.
*
* @return the PWM position (0.0 to 1.0)
*/
double GetPosition() const;
/**
* Set the PWM position.
*
* @param position the PWM position (0.0 to 1.0)
*/
void SetPosition(double position);
std::unique_ptr<CallbackStore> RegisterPeriodScaleCallback(
/**
* Register a callback to be run when the PWM period scale changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterPeriodScaleCallback(
NotifyCallback callback, bool initialNotify);
/**
* Get the PWM period scale.
*
* @return the PWM period scale
*/
int GetPeriodScale() const;
/**
* Set the PWM period scale.
*
* @param periodScale the PWM period scale
*/
void SetPeriodScale(int periodScale);
std::unique_ptr<CallbackStore> RegisterZeroLatchCallback(
/**
* Register a callback to be run when the PWM zero latch state changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterZeroLatchCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the PWM is zero latched.
*
* @return true if zero latched
*/
bool GetZeroLatch() const;
/**
* Define whether the PWM has been zero latched.
*
* @param zeroLatch true to indicate zero latched
*/
void SetZeroLatch(bool zeroLatch);
/**
* Reset all simulation data.
*/
void ResetData();
private:

View File

@@ -33,34 +33,107 @@ class RelaySim {
*/
explicit RelaySim(int channel);
std::unique_ptr<CallbackStore> RegisterInitializedForwardCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run when the forward direction is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterInitializedForwardCallback(NotifyCallback callback,
bool initialNotify);
/**
* Check whether the forward direction has been initialized.
*
* @return true if initialized
*/
bool GetInitializedForward() const;
/**
* Define whether the forward direction has been initialized.
*
* @param initializedForward whether this object is initialized
*/
void SetInitializedForward(bool initializedForward);
std::unique_ptr<CallbackStore> RegisterInitializedReverseCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run when the reverse direction is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore>
RegisterInitializedReverseCallback(NotifyCallback callback,
bool initialNotify);
/**
* Check whether the reverse direction has been initialized.
*
* @return true if initialized
*/
bool GetInitializedReverse() const;
/**
* Define whether the reverse direction has been initialized.
*
* @param initializedReverse whether this object is initialized
*/
void SetInitializedReverse(bool initializedReverse);
std::unique_ptr<CallbackStore> RegisterForwardCallback(
/**
* Register a callback to be run when the forward direction changes state.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterForwardCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the forward direction is active.
*
* @return true if active
*/
bool GetForward() const;
/**
* Set whether the forward direction is active.
*
* @param forward true to make active
*/
void SetForward(bool forward);
std::unique_ptr<CallbackStore> RegisterReverseCallback(
/**
* Register a callback to be run when the reverse direction changes state.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterReverseCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the reverse direction is active.
*
* @return true if active
*/
bool GetReverse() const;
/**
* Set whether the reverse direction is active.
*
* @param reverse true to make active
*/
void SetReverse(bool reverse);
/**
* Reset all simulation data.
*/
void ResetData();
private:

View File

@@ -18,111 +18,385 @@ namespace frc::sim {
*/
class RoboRioSim {
public:
static std::unique_ptr<CallbackStore> RegisterFPGAButtonCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run when the FPGA button state changes.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterFPGAButtonCallback(NotifyCallback callback, bool initialNotify);
/**
* Query the state of the FPGA button.
*
* @return the FPGA button state
*/
static bool GetFPGAButton();
/**
* Define the state of the FPGA button.
*
* @param fpgaButton the new state
*/
static void SetFPGAButton(bool fPGAButton);
static std::unique_ptr<CallbackStore> RegisterVInVoltageCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the Vin voltage changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterVInVoltageCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the Vin voltage.
*
* @return the Vin voltage
*/
static units::volt_t GetVInVoltage();
/**
* Define the Vin voltage.
*
* @param vInVoltage the new voltage
*/
static void SetVInVoltage(units::volt_t vInVoltage);
static std::unique_ptr<CallbackStore> RegisterVInCurrentCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the Vin current changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterVInCurrentCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the Vin current.
*
* @return the Vin current
*/
static units::ampere_t GetVInCurrent();
/**
* Define the Vin current.
*
* @param vInCurrent the new current
*/
static void SetVInCurrent(units::ampere_t vInCurrent);
static std::unique_ptr<CallbackStore> RegisterUserVoltage6VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 6V rail voltage changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserVoltage6VCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 6V rail voltage.
*
* @return the 6V rail voltage
*/
static units::volt_t GetUserVoltage6V();
/**
* Define the 6V rail voltage.
*
* @param userVoltage6V the new voltage
*/
static void SetUserVoltage6V(units::volt_t userVoltage6V);
static std::unique_ptr<CallbackStore> RegisterUserCurrent6VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 6V rail current changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserCurrent6VCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 6V rail current.
*
* @return the 6V rail current
*/
static units::ampere_t GetUserCurrent6V();
/**
* Define the 6V rail current.
*
* @param userCurrent6V the new current
*/
static void SetUserCurrent6V(units::ampere_t userCurrent6V);
static std::unique_ptr<CallbackStore> RegisterUserActive6VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 6V rail active state changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserActive6VCallback(NotifyCallback callback, bool initialNotify);
/**
* Get the 6V rail active state.
*
* @return true if the 6V rail is active
*/
static bool GetUserActive6V();
/**
* Set the 6V rail active state.
*
* @param userActive6V true to make rail active
*/
static void SetUserActive6V(bool userActive6V);
static std::unique_ptr<CallbackStore> RegisterUserVoltage5VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 5V rail voltage changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserVoltage5VCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 5V rail voltage.
*
* @return the 5V rail voltage
*/
static units::volt_t GetUserVoltage5V();
/**
* Define the 5V rail voltage.
*
* @param userVoltage5V the new voltage
*/
static void SetUserVoltage5V(units::volt_t userVoltage5V);
static std::unique_ptr<CallbackStore> RegisterUserCurrent5VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 5V rail current changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserCurrent5VCallback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 5V rail current.
*
* @return the 5V rail current
*/
static units::ampere_t GetUserCurrent5V();
/**
* Define the 5V rail current.
*
* @param userCurrent5V the new current
*/
static void SetUserCurrent5V(units::ampere_t userCurrent5V);
static std::unique_ptr<CallbackStore> RegisterUserActive5VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 5V rail active state changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserActive5VCallback(NotifyCallback callback, bool initialNotify);
/**
* Get the 5V rail active state.
*
* @return true if the 5V rail is active
*/
static bool GetUserActive5V();
/**
* Set the 5V rail active state.
*
* @param userActive5V true to make rail active
*/
static void SetUserActive5V(bool userActive5V);
static std::unique_ptr<CallbackStore> RegisterUserVoltage3V3Callback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 3.3V rail voltage changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserVoltage3V3Callback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 3.3V rail voltage.
*
* @return the 3.3V rail voltage
*/
static units::volt_t GetUserVoltage3V3();
/**
* Define the 3.3V rail voltage.
*
* @param userVoltage3V3 the new voltage
*/
static void SetUserVoltage3V3(units::volt_t userVoltage3V3);
static std::unique_ptr<CallbackStore> RegisterUserCurrent3V3Callback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 3.3V rail current changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserCurrent3V3Callback(NotifyCallback callback, bool initialNotify);
/**
* Measure the 3.3V rail current.
*
* @return the 3.3V rail current
*/
static units::ampere_t GetUserCurrent3V3();
/**
* Define the 3.3V rail current.
*
* @param userCurrent3V3 the new current
*/
static void SetUserCurrent3V3(units::ampere_t userCurrent3V3);
static std::unique_ptr<CallbackStore> RegisterUserActive3V3Callback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 3.3V rail active state changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserActive3V3Callback(NotifyCallback callback, bool initialNotify);
/**
* Get the 3.3V rail active state.
*
* @return true if the 3.3V rail is active
*/
static bool GetUserActive3V3();
/**
* Set the 3.3V rail active state.
*
* @param userActive3V3 true to make rail active
*/
static void SetUserActive3V3(bool userActive3V3);
static std::unique_ptr<CallbackStore> RegisterUserFaults6VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 6V rail number of faults
* changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserFaults6VCallback(NotifyCallback callback, bool initialNotify);
/**
* Get the 6V rail number of faults.
*
* @return number of faults
*/
static int GetUserFaults6V();
/**
* Set the 6V rail number of faults.
*
* @param userFaults6V number of faults
*/
static void SetUserFaults6V(int userFaults6V);
static std::unique_ptr<CallbackStore> RegisterUserFaults5VCallback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 5V rail number of faults
* changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserFaults5VCallback(NotifyCallback callback, bool initialNotify);
/**
* Get the 5V rail number of faults.
*
* @return number of faults
*/
static int GetUserFaults5V();
/**
* Set the 5V rail number of faults.
*
* @param userFaults5V number of faults
*/
static void SetUserFaults5V(int userFaults5V);
static std::unique_ptr<CallbackStore> RegisterUserFaults3V3Callback(
NotifyCallback callback, bool initialNotify);
/**
* Register a callback to be run whenever the 3.3V rail number of faults
* changes.
*
* @param callback the callback
* @param initialNotify whether the callback should be called with the
* initial value
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] static std::unique_ptr<CallbackStore>
RegisterUserFaults3V3Callback(NotifyCallback callback, bool initialNotify);
/**
* Get the 3.3V rail number of faults.
*
* @return number of faults
*/
static int GetUserFaults3V3();
/**
* Set the 3.3V rail number of faults.
*
* @param userFaults3V3 number of faults
*/
static void SetUserFaults3V3(int userFaults3V3);
/**
* Reset all simulation data.
*/
static void ResetData();
};
} // namespace frc::sim

View File

@@ -11,43 +11,136 @@
namespace frc::sim {
class SPIAccelerometerSim {
public:
/**
* Construct a new simulation object.
*
* @param index the HAL index of the accelerometer
*/
explicit SPIAccelerometerSim(int index);
std::unique_ptr<CallbackStore> RegisterActiveCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run when this accelerometer activates.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterActiveCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check whether the accelerometer is active.
*
* @return true if active
*/
bool GetActive() const;
/**
* Define whether this accelerometer is active.
*
* @param active the new state
*/
void SetActive(bool active);
std::unique_ptr<CallbackStore> RegisterRangeCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the range changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterRangeCallback(
NotifyCallback callback, bool initialNotify);
/**
* Check the range of this accelerometer.
*
* @return the accelerometer range
*/
int GetRange() const;
/**
* Change the range of this accelerometer.
*
* @param range the new accelerometer range
*/
void SetRange(int range);
std::unique_ptr<CallbackStore> RegisterXCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the X axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterXCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the X axis value.
*
* @return the X axis measurement
*/
double GetX() const;
/**
* Change the X axis value of the accelerometer.
*
* @param x the new reading of the X axis
*/
void SetX(double x);
std::unique_ptr<CallbackStore> RegisterYCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the Y axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterYCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the Y axis value.
*
* @return the Y axis measurement
*/
double GetY() const;
/**
* Change the Y axis value of the accelerometer.
*
* @param y the new reading of the Y axis
*/
void SetY(double y);
std::unique_ptr<CallbackStore> RegisterZCallback(NotifyCallback callback,
bool initialNotify);
/**
* Register a callback to be run whenever the Z axis value changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the CallbackStore object associated with this callback
*/
[[nodiscard]] std::unique_ptr<CallbackStore> RegisterZCallback(
NotifyCallback callback, bool initialNotify);
/**
* Measure the Z axis value.
*
* @return the Z axis measurement
*/
double GetZ() const;
/**
* Change the Z axis value of the accelerometer.
*
* @param z the new reading of the Z axis
*/
void SetZ(double z);
/**
* Reset all simulation data of this object.
*/
void ResetData();
private:

View File

@@ -25,28 +25,92 @@ class SimDeviceSim {
*/
explicit SimDeviceSim(const char* name);
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimValue GetValue(const char* name) const;
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimInt GetInt(const char* name) const;
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimLong GetLong(const char* name) const;
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimDouble GetDouble(const char* name) const;
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimEnum GetEnum(const char* name) const;
/**
* Get the property object with the given name.
*
* @param name the property name
* @return the property object
*/
hal::SimBoolean GetBoolean(const char* name) const;
/**
* Get all options for the given enum.
*
* @param val the enum
* @return names of the different values for that enum
*/
static std::vector<std::string> GetEnumOptions(hal::SimEnum val);
/**
* Get all properties.
*
* @param callback callback called for each property (SimValue). Signature
* of the callback must be const char*, HAL_SimValueHandle,
* int, const HAL_Value*
*/
template <typename F>
void EnumerateValues(F callback) const {
return HALSIM_EnumerateSimValues(
m_handle, &callback,
[](const char* name, void* param, HAL_SimValueHandle handle,
HAL_Bool readonly, const struct HAL_Value* value) {
std::invoke(*static_cast<F*>(param), name, handle, readonly, value);
int direction, const struct HAL_Value* value) {
std::invoke(*static_cast<F*>(param), name, handle, direction, value);
});
}
/**
* Get the raw handle of this object.
*
* @return the handle used to refer to this object
*/
operator HAL_SimDeviceHandle() const { return m_handle; } // NOLINT
/**
* Get all sim devices with the given prefix.
*
* @param prefix the prefix to filter sim devices
* @param callback callback function to call for each sim device
*/
template <typename F>
static void EnumerateDevices(const char* prefix, F callback) {
return HALSIM_EnumerateSimDevices(
@@ -56,6 +120,9 @@ class SimDeviceSim {
});
}
/**
* Reset all SimDevice data.
*/
static void ResetData();
private:

View File

@@ -11,6 +11,11 @@
namespace frc::sim {
/**
* Override the HAL runtime type (simulated/real).
*
* @param type runtime type
*/
void SetRuntimeType(HAL_RuntimeType type);
void WaitForProgramStart();
@@ -19,16 +24,40 @@ void SetProgramStarted();
bool GetProgramStarted();
/**
* Restart the simulator time.
*/
void RestartTiming();
/**
* Pause the simulator time.
*/
void PauseTiming();
/**
* Resume the simulator time.
*/
void ResumeTiming();
/**
* Check if the simulator time is paused.
*
* @return true if paused
*/
bool IsTimingPaused();
/**
* Advance the simulator time and wait for all notifiers to run.
*
* @param deltaSeconds the amount to advance (in seconds)
*/
void StepTiming(units::second_t delta);
/**
* Advance the simulator time and return immediately.
*
* @param deltaSeconds the amount to advance (in seconds)
*/
void StepTimingAsync(units::second_t delta);
} // namespace frc::sim

View File

@@ -62,21 +62,35 @@ class SingleJointedArmSim : public LinearSystemSim<2, 1, 1> {
bool simulateGravity,
const std::array<double, 1>& measurementStdDevs = {0.0});
/**
* Returns whether the arm would hit the lower limit.
*
* @param armAngle The arm height.
* @return Whether the arm would hit the lower limit.
*/
bool WouldHitLowerLimit(units::radian_t armAngle) const;
/**
* Returns whether the arm would hit the upper limit.
*
* @param armAngle The arm height.
* @return Whether the arm would hit the upper limit.
*/
bool WouldHitUpperLimit(units::radian_t armAngle) const;
/**
* Returns whether the arm has hit the lower limit.
*
* @param x The current arm state.
* @return Whether the arm has hit the lower limit.
*/
bool HasHitLowerLimit(const Eigen::Matrix<double, 2, 1>& x) const;
bool HasHitLowerLimit() const;
/**
* Returns whether the arm has hit the upper limit.
*
* @param x The current arm state.
* @return Whether the arm has hit the upper limit.
*/
bool HasHitUpperLimit(const Eigen::Matrix<double, 2, 1>& x) const;
bool HasHitUpperLimit() const;
/**
* Returns the current arm angle.
@@ -100,7 +114,7 @@ class SingleJointedArmSim : public LinearSystemSim<2, 1, 1> {
units::ampere_t GetCurrentDraw() const override;
/**
* Sets the input voltage for the elevator.
* Sets the input voltage for the arm.
*
* @param voltage The input voltage.
*/

View File

@@ -31,26 +31,86 @@ class XboxControllerSim : public GenericHIDSim {
*/
explicit XboxControllerSim(int port);
/**
* Change the X value of the joystick.
*
* @param hand the joystick hand
* @param value the new value
*/
void SetX(GenericHID::JoystickHand hand, double value);
/**
* Change the Y value of the joystick.
*
* @param hand the joystick hand
* @param value the new value
*/
void SetY(GenericHID::JoystickHand hand, double value);
/**
* Change the value of a trigger axis on the joystick.
*
* @param hand the joystick hand
* @param value the new value
*/
void SetTriggerAxis(GenericHID::JoystickHand hand, double value);
/**
* Change the value of a bumper on the joystick.
*
* @param hand the joystick hand
* @param state the new value
*/
void SetBumper(GenericHID::JoystickHand hand, bool state);
/**
* Change the value of a button on the joystick.
*
* @param hand the joystick hand
* @param state the new value
*/
void SetStickButton(GenericHID::JoystickHand hand, bool state);
/**
* Change the value of the A button.
*
* @param state the new value
*/
void SetAButton(bool state);
/**
* Change the value of the B button.
*
* @param state the new value
*/
void SetBButton(bool state);
/**
* Change the value of the X button.
*
* @param state the new value
*/
void SetXButton(bool state);
/**
* Change the value of the Y button.
*
* @param state the new value
*/
void SetYButton(bool state);
/**
* Change the value of the Back button.
*
* @param state the new value
*/
void SetBackButton(bool state);
/**
* Change the value of the Start button.
*
* @param state the new value
*/
void SetStartButton(bool state);
};

View File

@@ -10,7 +10,7 @@
#include "frc/controller/RamseteController.h"
#include "frc/kinematics/DifferentialDriveKinematics.h"
#include "frc/simulation/DifferentialDrivetrainSim.h"
#include "frc/system/RungeKutta.h"
#include "frc/system/NumericalIntegration.h"
#include "frc/system/plant/DCMotor.h"
#include "frc/system/plant/LinearSystemId.h"
#include "frc/trajectory/TrajectoryGenerator.h"
@@ -57,7 +57,7 @@ TEST(DifferentialDriveSim, Convergence) {
sim.Update(20_ms);
// Update ground truth.
groundTruthX = frc::RungeKutta(
groundTruthX = frc::RK4(
[&sim](const auto& x, const auto& u) -> Eigen::Matrix<double, 7, 1> {
return sim.Dynamics(x, u);
},

View File

@@ -13,6 +13,7 @@
#include "frc/controller/PIDController.h"
#include "frc/simulation/ElevatorSim.h"
#include "frc/simulation/EncoderSim.h"
#include "frc/system/NumericalIntegration.h"
#include "frc/system/plant/DCMotor.h"
#include "frc/system/plant/LinearSystemId.h"
#include "gtest/gtest.h"
@@ -64,3 +65,28 @@ TEST(ElevatorSim, MinMax) {
EXPECT_TRUE(height < 1.05_m);
}
}
TEST(ElevatorSim, Stability) {
static constexpr double kElevatorGearing = 100.0;
static constexpr units::meter_t kElevatorDrumRadius = 0.5_in;
static constexpr units::kilogram_t kCarriageMass = 4.0_kg;
frc::DCMotor m_elevatorGearbox = frc::DCMotor::Vex775Pro(4);
frc::LinearSystem<2, 1, 1> system = frc::LinearSystemId::ElevatorSystem(
m_elevatorGearbox, kCarriageMass, kElevatorDrumRadius, kElevatorGearing);
Eigen::Matrix<double, 2, 1> x0 = frc::MakeMatrix<2, 1>(0.0, 0.0);
Eigen::Matrix<double, 1, 1> u0 = frc::MakeMatrix<1, 1>(12.0);
Eigen::Matrix<double, 2, 1> x1 = frc::MakeMatrix<2, 1>(0.0, 0.0);
for (size_t i = 0; i < 50; i++) {
x1 = frc::RKF45(
[&](Eigen::Matrix<double, 2, 1> x,
Eigen::Matrix<double, 1, 1> u) -> Eigen::Matrix<double, 2, 1> {
return system.A() * x + system.B() * u;
},
x1, u0, 0.020_s);
}
EXPECT_NEAR(x1(0), system.CalculateX(x0, u0, 1_s)(0), 0.1);
}

View File

@@ -11,8 +11,8 @@
DriveStraight::DriveStraight(double distance, DriveTrain* drivetrain)
: frc2::CommandHelper<frc2::PIDCommand, DriveStraight>(
frc2::PIDController(4, 0, 0),
[this]() { return m_drivetrain->GetDistance(); }, distance,
[this](double output) { m_drivetrain->Drive(output, output); },
[drivetrain] { return drivetrain->GetDistance(); }, distance,
[drivetrain](double output) { drivetrain->Drive(output, output); },
{drivetrain}),
m_drivetrain(drivetrain) {
m_controller.SetTolerance(0.01);

View File

@@ -11,8 +11,9 @@
SetDistanceToBox::SetDistanceToBox(double distance, DriveTrain* drivetrain)
: frc2::CommandHelper<frc2::PIDCommand, SetDistanceToBox>(
frc2::PIDController(-2, 0, 0),
[this]() { return m_drivetrain->GetDistanceToObstacle(); }, distance,
[this](double output) { m_drivetrain->Drive(output, output); },
[drivetrain] { return drivetrain->GetDistanceToObstacle(); },
distance,
[drivetrain](double output) { drivetrain->Drive(output, output); },
{drivetrain}),
m_drivetrain(drivetrain) {
m_controller.SetTolerance(0.01);

View File

@@ -25,7 +25,7 @@ class Robot : public frc::TimedRobot {
// Drive for 2 seconds
if (m_timer.Get() < 2.0) {
// Drive forwards half speed
m_robotDrive.ArcadeDrive(-0.5, 0.0);
m_robotDrive.ArcadeDrive(0.5, 0.0);
} else {
// Stop robot
m_robotDrive.ArcadeDrive(0.0, 0.0);

View File

@@ -48,8 +48,8 @@ void DriveSubsystem::Periodic() {
}
void DriveSubsystem::Drive(double xSpeed, double ySpeed, double rot,
bool feildRelative) {
if (feildRelative) {
bool fieldRelative) {
if (fieldRelative) {
m_drive.DriveCartesian(ySpeed, xSpeed, rot, -m_gyro.GetAngle());
} else {
m_drive.DriveCartesian(ySpeed, xSpeed, rot);

View File

@@ -39,7 +39,7 @@ class DriveSubsystem : public frc2::SubsystemBase {
* @param fieldRelative Whether the provided x and y speeds are relative to
* the field.
*/
void Drive(double xSpeed, double ySpeed, double rot, bool feildRelative);
void Drive(double xSpeed, double ySpeed, double rot, bool fieldRelative);
/**
* Resets the drive encoders to currently read a position of 0.

View File

@@ -17,6 +17,10 @@
*/
class Robot : public frc::TimedRobot {
public:
void RobotInit() override {
m_pidController.SetSetpoint(kSetPoints[m_index]);
}
void TeleopPeriodic() override {
// When the button is pressed once, the selected elevator setpoint is
// incremented.
@@ -24,10 +28,10 @@ class Robot : public frc::TimedRobot {
if (currentButtonValue && !m_previousButtonValue) {
// Index of the elevator setpoint wraps around
m_index = (m_index + 1) % (sizeof(kSetPoints) / 8);
m_pidController.SetSetpoint(kSetPoints[m_index]);
}
m_previousButtonValue = currentButtonValue;
m_pidController.SetSetpoint(kSetPoints[m_index]);
double output =
m_pidController.Calculate(m_potentiometer.GetAverageVoltage());
m_elevatorMotor.Set(output);

View File

@@ -69,12 +69,12 @@ frc2::Command* RobotContainer::GetAutonomousCommand() {
// An example trajectory to follow. All units in meters.
auto exampleTrajectory = frc::TrajectoryGenerator::GenerateTrajectory(
// Start at the origin facing the +X direction
frc::Pose2d(),
// Start at (1, 2) facing the +X direction
frc::Pose2d(1_m, 2_m, 0_deg),
// Pass through these two interior waypoints, making an 's' curve path
{frc::Translation2d(1_m, 1_m), frc::Translation2d(2_m, -1_m)},
{frc::Translation2d(2_m, 3_m), frc::Translation2d(3_m, 1_m)},
// End 3 meters straight ahead of where we started, facing forward
frc::Pose2d(3_m, 0_m, 0_deg),
frc::Pose2d(4_m, 2_m, 0_deg),
// Pass the config
config);

View File

@@ -32,7 +32,12 @@ frc::SwerveModuleState SwerveModule::GetState() const {
frc::Rotation2d(units::radian_t(m_turningEncoder.Get()))};
}
void SwerveModule::SetDesiredState(const frc::SwerveModuleState& state) {
void SwerveModule::SetDesiredState(
const frc::SwerveModuleState& referenceState) {
// Optimize the reference state to avoid spinning further than 90 degrees
const auto state = frc::SwerveModuleState::Optimize(
referenceState, units::radian_t(m_turningEncoder.Get()));
// Calculate the drive output from the drive PID controller.
const auto driveOutput = m_drivePIDController.Calculate(
m_driveEncoder.GetRate(), state.speed.to<double>());

View File

@@ -65,7 +65,7 @@ void DriveSubsystem::Drive(units::meters_per_second_t xSpeed,
}
void DriveSubsystem::SetModuleStates(
std::array<frc::SwerveModuleState, 4> desiredStates) {
wpi::array<frc::SwerveModuleState, 4> desiredStates) {
kDriveKinematics.NormalizeWheelSpeeds(&desiredStates,
AutoConstants::kMaxSpeed);
m_frontLeft.SetDesiredState(desiredStates[0]);

View File

@@ -43,7 +43,12 @@ frc::SwerveModuleState SwerveModule::GetState() {
frc::Rotation2d(units::radian_t(m_turningEncoder.Get()))};
}
void SwerveModule::SetDesiredState(frc::SwerveModuleState& state) {
void SwerveModule::SetDesiredState(
const frc::SwerveModuleState& referenceState) {
// Optimize the reference state to avoid spinning further than 90 degrees
const auto state = frc::SwerveModuleState::Optimize(
referenceState, units::radian_t(m_turningEncoder.Get()));
// Calculate the drive output from the drive PID controller.
const auto driveOutput = m_drivePIDController.Calculate(
m_driveEncoder.GetRate(), state.speed.to<double>());

View File

@@ -43,7 +43,7 @@ class DriveSubsystem : public frc2::SubsystemBase {
*/
void Drive(units::meters_per_second_t xSpeed,
units::meters_per_second_t ySpeed, units::radians_per_second_t rot,
bool feildRelative);
bool fieldRelative);
/**
* Resets the drive encoders to currently read a position of 0.
@@ -53,7 +53,7 @@ class DriveSubsystem : public frc2::SubsystemBase {
/**
* Sets the drive SpeedControllers to a power from -1 to 1.
*/
void SetModuleStates(std::array<frc::SwerveModuleState, 4> desiredStates);
void SetModuleStates(wpi::array<frc::SwerveModuleState, 4> desiredStates);
/**
* Returns the heading of the robot.

View File

@@ -27,7 +27,7 @@ class SwerveModule {
frc::SwerveModuleState GetState();
void SetDesiredState(frc::SwerveModuleState& state);
void SetDesiredState(const frc::SwerveModuleState& state);
void ResetEncoders();

View File

@@ -32,7 +32,12 @@ frc::SwerveModuleState SwerveModule::GetState() const {
frc::Rotation2d(units::radian_t(m_turningEncoder.Get()))};
}
void SwerveModule::SetDesiredState(const frc::SwerveModuleState& state) {
void SwerveModule::SetDesiredState(
const frc::SwerveModuleState& referenceState) {
// Optimize the reference state to avoid spinning further than 90 degrees
const auto state = frc::SwerveModuleState::Optimize(
referenceState, units::radian_t(m_turningEncoder.Get()));
// Calculate the drive output from the drive PID controller.
const auto driveOutput = m_drivePIDController.Calculate(
m_driveEncoder.GetRate(), state.speed.to<double>());

View File

@@ -165,10 +165,7 @@ public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, Sendable
@Override
public void reset() {
if (m_simAngle != null) {
m_simAngle.set(0.0);
}
if (m_simRate != null) {
m_simRate.set(0.0);
m_simAngle.reset();
}
if (m_spi != null) {
m_spi.resetAccumulator();

View File

@@ -10,16 +10,17 @@ public final class Threads {
/**
* Get the thread priority for the current thread.
*
* @return The current thread priority. Scaled 1-99.
* @return The current thread priority. For real-time, this is 1-99 with 99 being highest. For
* non-real-time, this is 0. See "man 7 sched" for details.
*/
public static int getCurrentThreadPriority() {
return ThreadsJNI.getCurrentThreadPriority();
}
/**
* Get if the current thread is realtime.
* Get if the current thread is real-time.
*
* @return If the current thread is realtime
* @return If the current thread is real-time.
*/
public static boolean getCurrentThreadIsRealTime() {
return ThreadsJNI.getCurrentThreadIsRealTime();
@@ -28,10 +29,10 @@ public final class Threads {
/**
* Sets the thread priority for the current thread.
*
* @param realTime Set to true to set a realtime priority, false for standard priority
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being highest. On RoboRIO,
* priority is ignored for non realtime setting
* @return The success state of setting the priority
* @param realTime Set to true to set a real-time priority, false for standard priority.
* @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being
* highest. For non-real-time, this is forced to 0. See "man 7 sched" for details.
* @return True on success.
*/
public static boolean setCurrentThreadPriority(boolean realTime, int priority) {
return ThreadsJNI.setCurrentThreadPriority(realTime, priority);

View File

@@ -8,7 +8,7 @@ import edu.wpi.first.hal.SimDouble;
import edu.wpi.first.wpilibj.ADXRS450_Gyro;
/** Class to control a simulated ADXRS450 gyroscope. */
@SuppressWarnings("TypeName")
@SuppressWarnings({"TypeName", "AbbreviationAsWordInName"})
public class ADXRS450_GyroSim {
private final SimDouble m_simAngle;
private final SimDouble m_simRate;

View File

@@ -60,71 +60,161 @@ public class AddressableLEDSim {
return new AddressableLEDSim(index);
}
/**
* Register a callback on the Initialized property.
*
* @param callback the callback that will be called whenever the Initialized property is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AddressableLEDDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelInitializedCallback);
}
/**
* Check if initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AddressableLEDDataJNI.getInitialized(m_index);
}
/**
* Change the Initialized value of the LED strip.
*
* @param initialized the new value
*/
public void setInitialized(boolean initialized) {
AddressableLEDDataJNI.setInitialized(m_index, initialized);
}
/**
* Register a callback on the output port.
*
* @param callback the callback that will be called whenever the output port is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerOutputPortCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AddressableLEDDataJNI.registerOutputPortCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelOutputPortCallback);
}
/**
* Get the output port.
*
* @return the output port
*/
public int getOutputPort() {
return AddressableLEDDataJNI.getOutputPort(m_index);
}
/**
* Change the output port.
*
* @param outputPort the new output port
*/
public void setOutputPort(int outputPort) {
AddressableLEDDataJNI.setOutputPort(m_index, outputPort);
}
/**
* Register a callback on the length.
*
* @param callback the callback that will be called whenever the length is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerLengthCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AddressableLEDDataJNI.registerLengthCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelLengthCallback);
}
/**
* Get the length of the LED strip.
*
* @return the length
*/
public int getLength() {
return AddressableLEDDataJNI.getLength(m_index);
}
/**
* Change the length of the LED strip.
*
* @param length the new value
*/
public void setLength(int length) {
AddressableLEDDataJNI.setLength(m_index, length);
}
/**
* Register a callback on whether the LEDs are running.
*
* @param callback the callback that will be called whenever the LED state is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerRunningCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AddressableLEDDataJNI.registerRunningCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelRunningCallback);
}
/**
* Check if the LEDs are running.
*
* @return true if they are
*/
public boolean getRunning() {
return AddressableLEDDataJNI.getRunning(m_index);
}
/**
* Change whether the LEDs are active.
*
* @param running the new value
*/
public void setRunning(boolean running) {
AddressableLEDDataJNI.setRunning(m_index, running);
}
/**
* Register a callback on the LED data.
*
* @param callback the callback that will be called whenever the LED data is changed
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerDataCallback(ConstBufferCallback callback) {
int uid = AddressableLEDDataJNI.registerDataCallback(m_index, callback);
return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelDataCallback);
}
/**
* Get the LED data.
*
* @return the LED data
*/
public byte[] getData() {
return AddressableLEDDataJNI.getData(m_index);
}
/**
* Change the LED data.
*
* @param data the new data
*/
public void setData(byte[] data) {
AddressableLEDDataJNI.setData(m_index, data);
}
/** Reset all simulation data for this LED object. */
public void resetData() {
AddressableLEDDataJNI.resetData(m_index);
}

View File

@@ -30,45 +30,100 @@ public class AnalogGyroSim {
m_index = channel;
}
/**
* Register a callback on the angle.
*
* @param callback the callback that will be called whenever the angle changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAngleCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogGyroDataJNI.registerAngleCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogGyroDataJNI::cancelAngleCallback);
}
/**
* Get the current angle of the gyro.
*
* @return the angle measured by the gyro
*/
public double getAngle() {
return AnalogGyroDataJNI.getAngle(m_index);
}
/**
* Change the angle measured by the gyro.
*
* @param angle the new value
*/
public void setAngle(double angle) {
AnalogGyroDataJNI.setAngle(m_index, angle);
}
/**
* Register a callback on the rate.
*
* @param callback the callback that will be called whenever the rate changes
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerRateCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogGyroDataJNI.registerRateCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogGyroDataJNI::cancelRateCallback);
}
/**
* Get the rate of angle change on this gyro.
*
* @return the rate
*/
public double getRate() {
return AnalogGyroDataJNI.getRate(m_index);
}
/**
* Change the rate of the gyro.
*
* @param rate the new rate
*/
public void setRate(double rate) {
AnalogGyroDataJNI.setRate(m_index, rate);
}
/**
* Register a callback on whether the gyro is initialized.
*
* @param callback the callback that will be called whenever the gyro is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogGyroDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogGyroDataJNI::cancelInitializedCallback);
}
/**
* Check if the gyro is initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AnalogGyroDataJNI.getInitialized(m_index);
}
/**
* Set whether this gyro is initialized.
*
* @param initialized the new value
*/
public void setInitialized(boolean initialized) {
AnalogGyroDataJNI.setInitialized(m_index, initialized);
}
/** Reset all simulation data for this object. */
public void resetData() {
AnalogGyroDataJNI.resetData(m_index);
}

View File

@@ -30,59 +30,139 @@ public class AnalogInputSim {
m_index = channel;
}
/**
* Register a callback on whether the analog input is initialized.
*
* @param callback the callback that will be called whenever the analog input is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelInitializedCallback);
}
/**
* Check if this analog input has been initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AnalogInDataJNI.getInitialized(m_index);
}
/**
* Change whether this analog input has been initialized.
*
* @param initialized the new value
*/
public void setInitialized(boolean initialized) {
AnalogInDataJNI.setInitialized(m_index, initialized);
}
/**
* Register a callback on the number of average bits.
*
* @param callback the callback that will be called whenever the number of average bits is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAverageBitsCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerAverageBitsCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAverageBitsCallback);
}
/**
* Get the number of average bits.
*
* @return the number of average bits
*/
public int getAverageBits() {
return AnalogInDataJNI.getAverageBits(m_index);
}
/**
* Change the number of average bits.
*
* @param averageBits the new value
*/
public void setAverageBits(int averageBits) {
AnalogInDataJNI.setAverageBits(m_index, averageBits);
}
/**
* Register a callback on the amount of oversampling bits.
*
* @param callback the callback that will be called whenever the oversampling bits are changed.
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerOversampleBitsCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerOversampleBitsCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelOversampleBitsCallback);
}
/**
* Get the amount of oversampling bits.
*
* @return the amount of oversampling bits
*/
public int getOversampleBits() {
return AnalogInDataJNI.getOversampleBits(m_index);
}
/**
* Change the amount of oversampling bits.
*
* @param oversampleBits the new value
*/
public void setOversampleBits(int oversampleBits) {
AnalogInDataJNI.setOversampleBits(m_index, oversampleBits);
}
/**
* Register a callback on the voltage.
*
* @param callback the callback that will be called whenever the voltage is changed.
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerVoltageCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerVoltageCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelVoltageCallback);
}
/**
* Get the voltage.
*
* @return the voltage
*/
public double getVoltage() {
return AnalogInDataJNI.getVoltage(m_index);
}
/**
* Change the voltage.
*
* @param voltage the new value
*/
public void setVoltage(double voltage) {
AnalogInDataJNI.setVoltage(m_index, voltage);
}
/**
* Register a callback on whether the accumulator is initialized.
*
* @param callback the callback that will be called whenever the accumulator is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAccumulatorInitializedCallback(
NotifyCallback callback, boolean initialNotify) {
int uid =
@@ -90,70 +170,153 @@ public class AnalogInputSim {
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAccumulatorInitializedCallback);
}
/**
* Check if the accumulator has been initialized.
*
* @return true if initialized
*/
public boolean getAccumulatorInitialized() {
return AnalogInDataJNI.getAccumulatorInitialized(m_index);
}
/**
* Change whether the accumulator has been initialized.
*
* @param accumulatorInitialized the new value
*/
public void setAccumulatorInitialized(boolean accumulatorInitialized) {
AnalogInDataJNI.setAccumulatorInitialized(m_index, accumulatorInitialized);
}
/**
* Register a callback on the accumulator value.
*
* @param callback the callback that will be called whenever the accumulator value is changed.
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAccumulatorValueCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerAccumulatorValueCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAccumulatorValueCallback);
}
/**
* Get the accumulator value.
*
* @return the accumulator value
*/
public long getAccumulatorValue() {
return AnalogInDataJNI.getAccumulatorValue(m_index);
}
/**
* Change the accumulator value.
*
* @param accumulatorValue the new value
*/
public void setAccumulatorValue(long accumulatorValue) {
AnalogInDataJNI.setAccumulatorValue(m_index, accumulatorValue);
}
/**
* Register a callback on the accumulator count.
*
* @param callback the callback that will be called whenever the accumulator count is changed.
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAccumulatorCountCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerAccumulatorCountCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAccumulatorCountCallback);
}
/**
* Get the accumulator count.
*
* @return the accumulator count.
*/
public long getAccumulatorCount() {
return AnalogInDataJNI.getAccumulatorCount(m_index);
}
/**
* Change the accumulator count.
*
* @param accumulatorCount the new count.
*/
public void setAccumulatorCount(long accumulatorCount) {
AnalogInDataJNI.setAccumulatorCount(m_index, accumulatorCount);
}
/**
* Register a callback on the accumulator center.
*
* @param callback the callback that will be called whenever the accumulator center is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAccumulatorCenterCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerAccumulatorCenterCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAccumulatorCenterCallback);
}
/**
* Get the accumulator center.
*
* @return the accumulator center
*/
public int getAccumulatorCenter() {
return AnalogInDataJNI.getAccumulatorCenter(m_index);
}
/**
* Change the accumulator center.
*
* @param accumulatorCenter the new center
*/
public void setAccumulatorCenter(int accumulatorCenter) {
AnalogInDataJNI.setAccumulatorCenter(m_index, accumulatorCenter);
}
/**
* Register a callback on the accumulator deadband.
*
* @param callback the callback that will be called whenever the accumulator deadband is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerAccumulatorDeadbandCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = AnalogInDataJNI.registerAccumulatorDeadbandCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogInDataJNI::cancelAccumulatorDeadbandCallback);
}
/**
* Get the accumulator deadband.
*
* @return the accumulator deadband
*/
public int getAccumulatorDeadband() {
return AnalogInDataJNI.getAccumulatorDeadband(m_index);
}
/**
* Change the accumulator deadband.
*
* @param accumulatorDeadband the new deadband
*/
public void setAccumulatorDeadband(int accumulatorDeadband) {
AnalogInDataJNI.setAccumulatorDeadband(m_index, accumulatorDeadband);
}
/** Reset all simulation data for this object. */
public void resetData() {
AnalogInDataJNI.resetData(m_index);
}

View File

@@ -30,32 +30,69 @@ public class AnalogOutputSim {
m_index = channel;
}
/**
* Register a callback to be run whenever the voltage changes.
*
* @param callback the callback
* @param initialNotify whether to call the callback with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerVoltageCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogOutDataJNI.registerVoltageCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogOutDataJNI::cancelVoltageCallback);
}
/**
* Read the analog output voltage.
*
* @return the voltage on this analog output
*/
public double getVoltage() {
return AnalogOutDataJNI.getVoltage(m_index);
}
/**
* Set the analog output voltage.
*
* @param voltage the new voltage on this analog output
*/
public void setVoltage(double voltage) {
AnalogOutDataJNI.setVoltage(m_index, voltage);
}
/**
* Register a callback to be run when this analog output is initialized.
*
* @param callback the callback
* @param initialNotify whether to run the callback with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogOutDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogOutDataJNI::cancelInitializedCallback);
}
/**
* Check whether this analog output has been initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AnalogOutDataJNI.getInitialized(m_index);
}
/**
* Define whether this analog output has been initialized.
*
* @param initialized whether this object is initialized
*/
public void setInitialized(boolean initialized) {
AnalogOutDataJNI.setInitialized(m_index, initialized);
}
/** Reset all simulation data on this object. */
public void resetData() {
AnalogOutDataJNI.resetData(m_index);
}

View File

@@ -52,19 +52,45 @@ public class AnalogTriggerSim {
return new AnalogTriggerSim(index);
}
/**
* Register a callback on whether the analog trigger is initialized.
*
* @param callback the callback that will be called whenever the analog trigger is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogTriggerDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelInitializedCallback);
}
/**
* Check if this analog trigger has been initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AnalogTriggerDataJNI.getInitialized(m_index);
}
/**
* Change whether this analog trigger has been initialized.
*
* @param initialized the new value
*/
public void setInitialized(boolean initialized) {
AnalogTriggerDataJNI.setInitialized(m_index, initialized);
}
/**
* Register a callback on the lower bound.
*
* @param callback the callback that will be called whenever the lower bound is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerTriggerLowerBoundCallback(
NotifyCallback callback, boolean initialNotify) {
int uid =
@@ -72,14 +98,32 @@ public class AnalogTriggerSim {
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelTriggerLowerBoundCallback);
}
/**
* Get the lower bound.
*
* @return the lower bound
*/
public double getTriggerLowerBound() {
return AnalogTriggerDataJNI.getTriggerLowerBound(m_index);
}
/**
* Change the lower bound.
*
* @param triggerLowerBound the new lower bound
*/
public void setTriggerLowerBound(double triggerLowerBound) {
AnalogTriggerDataJNI.setTriggerLowerBound(m_index, triggerLowerBound);
}
/**
* Register a callback on the upper bound.
*
* @param callback the callback that will be called whenever the upper bound is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerTriggerUpperBoundCallback(
NotifyCallback callback, boolean initialNotify) {
int uid =
@@ -87,14 +131,25 @@ public class AnalogTriggerSim {
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelTriggerUpperBoundCallback);
}
/**
* Get the upper bound.
*
* @return the upper bound
*/
public double getTriggerUpperBound() {
return AnalogTriggerDataJNI.getTriggerUpperBound(m_index);
}
/**
* Change the upper bound.
*
* @param triggerUpperBound the new upper bound
*/
public void setTriggerUpperBound(double triggerUpperBound) {
AnalogTriggerDataJNI.setTriggerUpperBound(m_index, triggerUpperBound);
}
/** Reset all simulation data for this object. */
public void resetData() {
AnalogTriggerDataJNI.resetData(m_index);
}

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.simulation;
/** A utility class to simulate the robot battery. */
public final class BatterySim {
private BatterySim() {
// Utility class

Some files were not shown because too many files have changed in this diff Show More