Compare commits

...

17 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
30 changed files with 435 additions and 123 deletions

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

@@ -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,7 +106,6 @@ 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.")
destinationDirectory = outputsFolder
@@ -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

@@ -140,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

@@ -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

@@ -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.
*
@@ -708,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

@@ -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.79-1"
imguiVersion = "1.79-2"
wpimathVersion = "-1"
}
}

View File

@@ -1348,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

@@ -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

@@ -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

@@ -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

@@ -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.

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

@@ -183,7 +183,8 @@ public class Rotation2d {
@Override
public boolean equals(Object obj) {
if (obj instanceof Rotation2d) {
return Math.abs(((Rotation2d) obj).m_value - m_value) < 1E-9;
var other = (Rotation2d) obj;
return Math.hypot(m_cos - other.m_cos, m_sin - other.m_sin) < 1E-9;
}
return false;
}

View File

@@ -65,7 +65,7 @@ Rotation2d Rotation2d::operator*(double scalar) const {
}
bool Rotation2d::operator==(const Rotation2d& other) const {
return units::math::abs(m_value - other.m_value) < 1E-9_rad;
return std::hypot(m_cos - other.m_cos, m_sin - other.m_sin) < 1E-9;
}
bool Rotation2d::operator!=(const Rotation2d& other) const {

View File

@@ -101,8 +101,8 @@ class DifferentialDrivePoseEstimator {
* gyroscope angle does not need to be reset here on the user's robot code.
* The library automatically takes care of offsetting the gyro angle.
*
*@param pose The estimated pose of the robot on the field.
*@param gyroAngle The current gyro angle.
* @param pose The estimated pose of the robot on the field.
* @param gyroAngle The current gyro angle.
*/
void ResetPosition(const Pose2d& pose, const Rotation2d& gyroAngle);

View File

@@ -41,9 +41,8 @@ namespace frc {
*
* <strong> u = [[vx, vy, omega]]^T </strong> in the field-coordinate system.
*
* <strong> y = [[x, y, std::theta]]^T </strong> in field
* coords from vision, or <strong> y = [[theta]]^T
* </strong> from the gyro.
* <strong> y = [[x, y, theta]]^T </strong> in field coords from vision,
* or <strong> y = [[theta]]^T </strong> from the gyro.
*/
template <size_t NumModules>
class SwerveDrivePoseEstimator {

View File

@@ -15,22 +15,22 @@ class Rotation2dTest {
@Test
void testRadiansToDegrees() {
var one = new Rotation2d(Math.PI / 3);
var two = new Rotation2d(Math.PI / 4);
var rot1 = new Rotation2d(Math.PI / 3);
var rot2 = new Rotation2d(Math.PI / 4);
assertAll(
() -> assertEquals(one.getDegrees(), 60.0, kEpsilon),
() -> assertEquals(two.getDegrees(), 45.0, kEpsilon));
() -> assertEquals(rot1.getDegrees(), 60.0, kEpsilon),
() -> assertEquals(rot2.getDegrees(), 45.0, kEpsilon));
}
@Test
void testRadiansAndDegrees() {
var one = Rotation2d.fromDegrees(45.0);
var two = Rotation2d.fromDegrees(30.0);
var rot1 = Rotation2d.fromDegrees(45.0);
var rot2 = Rotation2d.fromDegrees(30.0);
assertAll(
() -> assertEquals(one.getRadians(), Math.PI / 4, kEpsilon),
() -> assertEquals(two.getRadians(), Math.PI / 6, kEpsilon));
() -> assertEquals(rot1.getRadians(), Math.PI / 4, kEpsilon),
() -> assertEquals(rot2.getRadians(), Math.PI / 6, kEpsilon));
}
@Test
@@ -53,23 +53,27 @@ class Rotation2dTest {
@Test
void testMinus() {
var one = Rotation2d.fromDegrees(70.0);
var two = Rotation2d.fromDegrees(30.0);
var rot1 = Rotation2d.fromDegrees(70.0);
var rot2 = Rotation2d.fromDegrees(30.0);
assertEquals(one.minus(two).getDegrees(), 40.0, kEpsilon);
assertEquals(rot1.minus(rot2).getDegrees(), 40.0, kEpsilon);
}
@Test
void testEquality() {
var one = Rotation2d.fromDegrees(43.0);
var two = Rotation2d.fromDegrees(43.0);
assertEquals(one, two);
var rot1 = Rotation2d.fromDegrees(43.0);
var rot2 = Rotation2d.fromDegrees(43.0);
assertEquals(rot1, rot2);
var rot3 = Rotation2d.fromDegrees(-180.0);
var rot4 = Rotation2d.fromDegrees(180.0);
assertEquals(rot3, rot4);
}
@Test
void testInequality() {
var one = Rotation2d.fromDegrees(43.0);
var two = Rotation2d.fromDegrees(43.5);
assertNotEquals(one, two);
var rot1 = Rotation2d.fromDegrees(43.0);
var rot2 = Rotation2d.fromDegrees(43.5);
assertNotEquals(rot1, rot2);
}
}

View File

@@ -0,0 +1,53 @@
// 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.wpilibj.kinematics;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import edu.wpi.first.wpilibj.geometry.Rotation2d;
import org.junit.jupiter.api.Test;
class SwerveModuleStateTest {
private static final double kEpsilon = 1E-9;
@Test
void testOptimize() {
var angleA = Rotation2d.fromDegrees(45);
var refA = new SwerveModuleState(-2.0, Rotation2d.fromDegrees(180));
var optimizedA = SwerveModuleState.optimize(refA, angleA);
assertAll(
() -> assertEquals(2.0, optimizedA.speedMetersPerSecond, kEpsilon),
() -> assertEquals(0.0, optimizedA.angle.getDegrees(), kEpsilon));
var angleB = Rotation2d.fromDegrees(-50);
var refB = new SwerveModuleState(4.7, Rotation2d.fromDegrees(41));
var optimizedB = SwerveModuleState.optimize(refB, angleB);
assertAll(
() -> assertEquals(-4.7, optimizedB.speedMetersPerSecond, kEpsilon),
() -> assertEquals(-139.0, optimizedB.angle.getDegrees(), kEpsilon));
}
@Test
void testNoOptimize() {
var angleA = Rotation2d.fromDegrees(0);
var refA = new SwerveModuleState(2.0, Rotation2d.fromDegrees(89));
var optimizedA = SwerveModuleState.optimize(refA, angleA);
assertAll(
() -> assertEquals(2.0, optimizedA.speedMetersPerSecond, kEpsilon),
() -> assertEquals(89.0, optimizedA.angle.getDegrees(), kEpsilon));
var angleB = Rotation2d.fromDegrees(0);
var refB = new SwerveModuleState(-2.0, Rotation2d.fromDegrees(-2));
var optimizedB = SwerveModuleState.optimize(refB, angleB);
assertAll(
() -> assertEquals(-2.0, optimizedB.speedMetersPerSecond, kEpsilon),
() -> assertEquals(-2.0, optimizedB.angle.getDegrees(), kEpsilon));
}
}

View File

@@ -14,19 +14,19 @@ using namespace frc;
static constexpr double kEpsilon = 1E-9;
TEST(Rotation2dTest, RadiansToDegrees) {
const Rotation2d one{units::radian_t(wpi::math::pi / 3)};
const Rotation2d two{units::radian_t(wpi::math::pi / 4)};
const Rotation2d rot1{units::radian_t(wpi::math::pi / 3)};
const Rotation2d rot2{units::radian_t(wpi::math::pi / 4)};
EXPECT_NEAR(one.Degrees().to<double>(), 60.0, kEpsilon);
EXPECT_NEAR(two.Degrees().to<double>(), 45.0, kEpsilon);
EXPECT_NEAR(rot1.Degrees().to<double>(), 60.0, kEpsilon);
EXPECT_NEAR(rot2.Degrees().to<double>(), 45.0, kEpsilon);
}
TEST(Rotation2dTest, DegreesToRadians) {
const auto one = Rotation2d(45.0_deg);
const auto two = Rotation2d(30.0_deg);
const auto rot1 = Rotation2d(45.0_deg);
const auto rot2 = Rotation2d(30.0_deg);
EXPECT_NEAR(one.Radians().to<double>(), wpi::math::pi / 4.0, kEpsilon);
EXPECT_NEAR(two.Radians().to<double>(), wpi::math::pi / 6.0, kEpsilon);
EXPECT_NEAR(rot1.Radians().to<double>(), wpi::math::pi / 4.0, kEpsilon);
EXPECT_NEAR(rot2.Radians().to<double>(), wpi::math::pi / 6.0, kEpsilon);
}
TEST(Rotation2dTest, RotateByFromZero) {
@@ -45,20 +45,24 @@ TEST(Rotation2dTest, RotateByNonZero) {
}
TEST(Rotation2dTest, Minus) {
const auto one = Rotation2d(70.0_deg);
const auto two = Rotation2d(30.0_deg);
const auto rot1 = Rotation2d(70.0_deg);
const auto rot2 = Rotation2d(30.0_deg);
EXPECT_NEAR((one - two).Degrees().to<double>(), 40.0, kEpsilon);
EXPECT_NEAR((rot1 - rot2).Degrees().to<double>(), 40.0, kEpsilon);
}
TEST(Rotation2dTest, Equality) {
const auto one = Rotation2d(43_deg);
const auto two = Rotation2d(43_deg);
EXPECT_TRUE(one == two);
const auto rot1 = Rotation2d(43_deg);
const auto rot2 = Rotation2d(43_deg);
EXPECT_EQ(rot1, rot2);
const auto rot3 = Rotation2d(-180_deg);
const auto rot4 = Rotation2d(180_deg);
EXPECT_EQ(rot3, rot4);
}
TEST(Rotation2dTest, Inequality) {
const auto one = Rotation2d(43_deg);
const auto two = Rotation2d(43.5_deg);
EXPECT_TRUE(one != two);
const auto rot1 = Rotation2d(43_deg);
const auto rot2 = Rotation2d(43.5_deg);
EXPECT_NE(rot1, rot2);
}

View File

@@ -0,0 +1,41 @@
// 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.
#include "frc/geometry/Rotation2d.h"
#include "frc/kinematics/SwerveModuleState.h"
#include "gtest/gtest.h"
static constexpr double kEpsilon = 1E-9;
TEST(SwerveModuleState, Optimize) {
frc::Rotation2d angleA{45_deg};
frc::SwerveModuleState refA{-2_mps, 180_deg};
auto optimizedA = frc::SwerveModuleState::Optimize(refA, angleA);
EXPECT_NEAR(optimizedA.speed.to<double>(), 2.0, kEpsilon);
EXPECT_NEAR(optimizedA.angle.Degrees().to<double>(), 0.0, kEpsilon);
frc::Rotation2d angleB{-50_deg};
frc::SwerveModuleState refB{4.7_mps, 41_deg};
auto optimizedB = frc::SwerveModuleState::Optimize(refB, angleB);
EXPECT_NEAR(optimizedB.speed.to<double>(), -4.7, kEpsilon);
EXPECT_NEAR(optimizedB.angle.Degrees().to<double>(), -139.0, kEpsilon);
}
TEST(SwerveModuleState, NoOptimize) {
frc::Rotation2d angleA{0_deg};
frc::SwerveModuleState refA{2_mps, 89_deg};
auto optimizedA = frc::SwerveModuleState::Optimize(refA, angleA);
EXPECT_NEAR(optimizedA.speed.to<double>(), 2.0, kEpsilon);
EXPECT_NEAR(optimizedA.angle.Degrees().to<double>(), 89.0, kEpsilon);
frc::Rotation2d angleB{0_deg};
frc::SwerveModuleState refB{-2_mps, -2_deg};
auto optimizedB = frc::SwerveModuleState::Optimize(refB, angleB);
EXPECT_NEAR(optimizedB.speed.to<double>(), -2.0, kEpsilon);
EXPECT_NEAR(optimizedB.angle.Degrees().to<double>(), -2.0, kEpsilon);
}

View File

@@ -55,7 +55,7 @@ void SetProcessorAffinity(int32_t core_id) {
void SetThreadRealtimePriorityOrDie(int32_t priority) {
struct sched_param param;
// Set realtime priority for this thread
// Set real-time priority for this thread
param.sched_priority = priority + sched_get_priority_min(SCHED_RR);
ASSERT_EQ(pthread_setschedparam(pthread_self(), SCHED_RR, &param), 0)
<< ": Failed to set scheduler priority.";