[robotpy] Mirror most other subprojects (#8208)

GitOrigin-RevId: ac60fd3cf4a24023184376687da28373d14b781a

This mirrors the robotpy files for the following projects:
- apriltag
- datalog
- hal
- ntcore
- romiVendordep
- wpilibc
- wpimath
- xrpVendordep

This excludes cscore and the halsim wrappers for at this time.

NOTE: This does not hook these projects up to the build system, just simply mirrors the files. The building will take place in a follow up PR to make it easier to review the changes necessary to build.
This commit is contained in:
PJ Reiniger
2025-10-24 01:28:04 -04:00
committed by GitHub
parent 8992dcdc99
commit 44b9cc1398
545 changed files with 27293 additions and 38 deletions

View File

@@ -23,6 +23,13 @@ generatedFileExclude {
fieldImages/src/main/native/resources/
apriltag/src/test/resources/
wpilibc/src/generated/
apriltag/src/main/python/
apriltag/src/test/python/
wpilibc/src/main/python/
wpilibc/src/test/python/
xrpVendordep/src/main/python/
xrpVendordep/src/test/python/
}
repoRootNameOverride {

View File

@@ -0,0 +1,4 @@
robotpy-apriltag
================
RobotPy wrappers around WPILib's version of the apriltag library.

View File

@@ -0,0 +1,41 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"hatchling",
"hatch-nativelib~=0.2.0",
"hatch-robotpy~=0.2.1",
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-wpimath==2027.0.0a2",
]
[project]
name = "robotpy-native-apriltag"
version = "2027.0.0a2"
description = "WPILib AprilTag Library"
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-wpimath==2027.0.0a2",
]
[tool.hatch.build.targets.wheel]
packages = ["src/native"]
[[tool.hatch.build.hooks.robotpy.maven_lib_download]]
artifact_id = "apriltag-cpp"
group_id = "edu.wpi.first.apriltag"
repo_url = "https://frcmaven.wpi.edu/artifactory/release-2027"
version = "2027.0.0-alpha-2"
extract_to = "src/native/apriltag"
libs = ["apriltag"]
[[tool.hatch.build.hooks.nativelib.pcfile]]
pcfile = "src/native/apriltag/robotpy-native-apriltag.pc"
name = "apriltag"
includedir = "src/native/apriltag/include"
libdir = "src/native/apriltag/lib"
shared_libraries = ["apriltag"]
requires = ["robotpy-native-wpiutil", "robotpy-native-wpimath"]

View File

@@ -0,0 +1,74 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"semiwrap~=0.1.7",
"hatch-meson~=0.1.0b2",
"hatch-robotpy~=0.2.1",
"hatchling",
"robotpy-native-apriltag==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2",
"robotpy-wpimath==2027.0.0a2",
]
[project]
name = "robotpy-apriltag"
version = "2027.0.0a2"
description = "RobotPy bindings for WPILib's AprilTag library"
authors = [
{name = "RobotPy Development Team", email = "robotpy@googlegroups.com"},
]
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-apriltag==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2",
"robotpy-wpimath==2027.0.0a2",
]
[project.urls]
"Source code" = "https://github.com/robotpy/mostrobotpy"
[tool.hatch.build.hooks.robotpy]
version_file = "robotpy_apriltag/version.py"
[tool.hatch.build.hooks.semiwrap]
[tool.hatch.build.hooks.meson]
[tool.hatch.build.targets.wheel]
packages = ["robotpy_apriltag"]
[tool.semiwrap]
update_init = [
"robotpy_apriltag robotpy_apriltag._apriltag"
]
scan_headers_ignore = [
"common/*",
"test/*",
"apriltag.h",
"apriltag_math.h",
"apriltag_pose.h",
"frc/apriltag/AprilTagDetector_cv.h",
"tag16h5.h",
"tag36h11.h",
]
[tool.semiwrap.extension_modules."robotpy_apriltag._apriltag"]
name = "apriltag"
wraps = ["robotpy-native-apriltag"]
depends = ["wpiutil", "wpimath"]
[tool.semiwrap.extension_modules."robotpy_apriltag._apriltag".headers]
# frc/apriltag
AprilTag = "frc/apriltag/AprilTag.h"
AprilTagDetection = "frc/apriltag/AprilTagDetection.h"
AprilTagDetector = "frc/apriltag/AprilTagDetector.h"
# AprilTagDetector_cv = "frc/apriltag/AprilTagDetector_cv.h"
AprilTagFieldLayout = "frc/apriltag/AprilTagFieldLayout.h"
AprilTagFields = "frc/apriltag/AprilTagFields.h"
AprilTagPoseEstimate = "frc/apriltag/AprilTagPoseEstimate.h"
AprilTagPoseEstimator = "frc/apriltag/AprilTagPoseEstimator.h"

View File

@@ -0,0 +1,22 @@
from . import _init__apriltag
# autogenerated by 'semiwrap create-imports robotpy_apriltag robotpy_apriltag._apriltag'
from ._apriltag import (
AprilTag,
AprilTagDetection,
AprilTagDetector,
AprilTagField,
AprilTagFieldLayout,
AprilTagPoseEstimate,
AprilTagPoseEstimator,
)
__all__ = [
"AprilTag",
"AprilTagDetection",
"AprilTagDetector",
"AprilTagField",
"AprilTagFieldLayout",
"AprilTagPoseEstimate",
"AprilTagPoseEstimator",
]

View File

@@ -0,0 +1,4 @@
#include "semiwrap_init.robotpy_apriltag._apriltag.hpp"
SEMIWRAP_PYBIND11_MODULE(m) { initWrapper(m); }

View File

@@ -0,0 +1,16 @@
functions:
to_json:
ignore: true
from_json:
ignore: true
classes:
frc::AprilTag:
attributes:
ID:
pose:
methods:
Generate36h11AprilTagImage:
ignore: true
Generate16h5AprilTagImage:
ignore: true
operator==:

View File

@@ -0,0 +1,43 @@
extra_includes:
- pybind11/eigen.h
classes:
frc::AprilTagDetection:
methods:
GetFamily:
GetId:
GetHamming:
GetDecisionMargin:
GetHomography:
GetHomographyMatrix:
GetCenter:
GetCorner:
GetCorners:
inline_code: |
.def("__repr__", [](const AprilTagDetection &self) {
return py::str("<AprilTagDetection tag_family={} tag_id={} hamming={} decision_margin={} center={}>")
.format(self.GetFamily(), self.GetId(), self.GetHamming(), self.GetDecisionMargin(), self.GetCenter());
})
frc::AprilTagDetection::Point:
attributes:
x:
y:
inline_code: |
.def(py::init([](double x, double y) {
AprilTagDetection::Point pt{x, y};
return std::make_unique<AprilTagDetection::Point>(std::move(pt));
}), py::arg("x"), py::arg("y"))
.def("__len__", [](const AprilTagDetection::Point &self) { return 2; })
.def("__getitem__", [](const AprilTagDetection::Point &self, int index) {
switch (index) {
case 0:
return self.x;
case 1:
return self.y;
default:
throw std::out_of_range("AprilTagDetection.Point index out of range");
}
})
.def("__repr__", [](const AprilTagDetection::Point &self) {
return py::str("AprilTagDetection.Point(x={}, y={})").format(self.x, self.y);
})

View File

@@ -0,0 +1,99 @@
extra_includes:
- pybind11_typing.h
classes:
frc::AprilTagDetector:
methods:
AprilTagDetector:
SetConfig:
GetConfig:
SetQuadThresholdParameters:
GetQuadThresholdParameters:
AddFamily:
RemoveFamily:
ClearFamilies:
Detect:
overloads:
int, int, int, uint8_t*:
ignore: true
int, int, uint8_t*:
ignore: true
inline_code: |
.def("detect", [](AprilTagDetector *self, py::buffer img) {
// validate the input image buffer
auto buf = img.request();
if (buf.ndim != 2) {
throw py::value_error("buffer must only have two dimensions");
} else if (buf.itemsize != 1) {
throw py::value_error("buffer elements must be bytes");
}
// We are going to move the detection result into this shared_ptr
// so that python can keep it alive. We don't expose the result directly
// to the user because we'd have to pretend it's a list, and that would
// be annoying.
std::shared_ptr<AprilTagDetector::Results> c_result;
{
py::gil_scoped_release unlock;
c_result = std::make_shared<AprilTagDetector::Results>(std::move(self->Detect(buf.shape[1], buf.shape[0], (uint8_t*)buf.ptr)));
}
// This tells python about the shared_ptr, and it'll keep it alive as
// long as the python reference is alive. When we call get(), we marked
// the return value as reference_internal so python will keep the python
// reference for the results object alive for as long as all of its
// results that we put into the list are alive
py::object py_result = py::cast(c_result);
auto len = c_result->size();
auto get = py_result.attr("get");
py::typing::List<AprilTagDetection> l(len);
for (size_t i = 0; i < len; i++) {
l[i] = get(i);
}
return l;
}, py::arg("image"),
R"doc(
Detect tags from an 8-bit grayscale image with shape (height, width)
:return: list of results
)doc"
)
frc::AprilTagDetector::Config:
attributes:
numThreads:
quadDecimate:
quadSigma:
refineEdges:
decodeSharpening:
debug:
methods:
operator==:
frc::AprilTagDetector::QuadThresholdParameters:
attributes:
minClusterPixels:
maxNumMaxima:
criticalAngle:
maxLineFitMSE:
minWhiteBlackDiff:
deglitch:
methods:
operator==:
frc::AprilTagDetector::Results:
rename: _Results
ignored_bases:
- std::span<const AprilTagDetection* const>
force_no_trampoline: true
methods:
Results:
overloads:
'':
ignore: true
void*, const private_init&:
ignore: true
inline_code: |
// use the keepalive to keep the array of results around until
// the user deletes them
.def("get", [](const AprilTagDetector::Results &self, int i) {
return self[i];
}, py::return_value_policy::reference_internal)

View File

@@ -0,0 +1,29 @@
functions:
to_json:
ignore: true
from_json:
ignore: true
LoadAprilTagLayoutField:
ignore: true
classes:
frc::AprilTagFieldLayout:
enums:
OriginPosition:
methods:
AprilTagFieldLayout:
overloads:
'':
std::string_view:
std::vector<AprilTag>, units::meter_t, units::meter_t:
LoadField:
GetFieldLength:
GetFieldWidth:
GetTags:
SetOrigin:
overloads:
OriginPosition:
const Pose3d&:
GetOrigin:
GetTagPose:
Serialize:
operator==:

View File

@@ -0,0 +1,2 @@
enums:
AprilTagField:

View File

@@ -0,0 +1,9 @@
classes:
frc::AprilTagPoseEstimate:
attributes:
pose1:
pose2:
error1:
error2:
methods:
GetAmbiguity:

View File

@@ -0,0 +1,36 @@
extra_includes:
- frc/apriltag/AprilTagDetection.h
classes:
frc::AprilTagPoseEstimator:
methods:
AprilTagPoseEstimator:
SetConfig:
GetConfig:
EstimateHomography:
overloads:
const AprilTagDetection& [const]:
std::span<const double, 9> [const]:
EstimateOrthogonalIteration:
overloads:
const AprilTagDetection&, int [const]:
std::span<const double, 9>, std::span<const double, 8>, int [const]:
Estimate:
overloads:
const AprilTagDetection& [const]:
std::span<const double, 9>, std::span<const double, 8> [const]:
frc::AprilTagPoseEstimator::Config:
force_no_default_constructor: true
attributes:
tagSize:
fx:
fy:
cx:
cy:
methods:
operator==:
inline_code: |
.def(py::init([](units::meter_t tagSize, double fx, double fy, double cx, double cy) {
AprilTagPoseEstimator::Config cfg{tagSize, fx, fy, cx, cy};
return std::make_unique<AprilTagPoseEstimator::Config>(std::move(cfg));
}), py::arg("tagSize"), py::arg("fx"), py::arg("fy"), py::arg("cx"), py::arg("cy"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,119 @@
import cv2
import robotpy_apriltag
from wpimath.geometry import Transform3d
import math
import pathlib
import pytest
def test_point():
point = robotpy_apriltag.AprilTagDetection.Point()
x, y = point
assert x == 0
assert y == 0
def _load_grayscale_image(fname):
full_path = pathlib.Path(__file__).parent / fname
img = cv2.imread(str(full_path))
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
def test_1():
detector = robotpy_apriltag.AprilTagDetector()
assert detector.addFamily("tag16h5")
assert detector.addFamily("tag36h11")
img = _load_grayscale_image("tag1_640_480.jpg")
results = detector.detect(img)
assert len(results) == 1
assert results[0].getFamily() == "tag36h11"
assert results[0].getId() == 1
assert results[0].getHamming() == 0
estimator = robotpy_apriltag.AprilTagPoseEstimator(
robotpy_apriltag.AprilTagPoseEstimator.Config(0.2, 500, 500, 320, 240)
)
est = estimator.estimateOrthogonalIteration(results[0], 50)
assert est.pose2 == Transform3d()
pose = estimator.estimate(results[0])
assert est.pose1 == pose
def test_pose_rotated_x():
"""
This tag is rotated such that the top is closer to the camera than the bottom. In the camera
frame, with +x to the right, this is a rotation about +X by 45 degrees.
"""
detector = robotpy_apriltag.AprilTagDetector()
assert detector.addFamily("tag16h5")
img = _load_grayscale_image("tag2_45deg_X.png")
results = detector.detect(img)
assert len(results) == 1
estimator = robotpy_apriltag.AprilTagPoseEstimator(
robotpy_apriltag.AprilTagPoseEstimator.Config(
0.2, 500, 500, img.shape[1] / 2.0, img.shape[0] / 2.0
)
)
est = estimator.estimateOrthogonalIteration(results[0], 50)
assert pytest.approx(est.pose1.rotation().x, abs=0.1) == math.radians(45)
assert pytest.approx(est.pose1.rotation().y, abs=0.1) == math.radians(0)
assert pytest.approx(est.pose1.rotation().z, abs=0.1) == math.radians(0)
def test_pose_rotated_y():
"""
This tag is rotated such that the right is closer to the camera than the left. In the camera
frame, with +y down, this is a rotation of 45 degrees about +y.
"""
detector = robotpy_apriltag.AprilTagDetector()
assert detector.addFamily("tag16h5")
img = _load_grayscale_image("tag2_45deg_y.png")
results = detector.detect(img)
assert len(results) == 1
estimator = robotpy_apriltag.AprilTagPoseEstimator(
robotpy_apriltag.AprilTagPoseEstimator.Config(
0.2, 500, 500, img.shape[1] / 2.0, img.shape[0] / 2.0
)
)
est = estimator.estimateOrthogonalIteration(results[0], 50)
assert pytest.approx(est.pose1.rotation().x, abs=0.1) == math.radians(0)
assert pytest.approx(est.pose1.rotation().y, abs=0.1) == math.radians(45)
assert pytest.approx(est.pose1.rotation().z, abs=0.1) == math.radians(0)
def test_pose_straight_on():
"""
This tag is facing right at the camera -- no rotation should be observed.
"""
detector = robotpy_apriltag.AprilTagDetector()
assert detector.addFamily("tag16h5")
img = _load_grayscale_image("tag2_16h5_straight.png")
results = detector.detect(img)
assert len(results) == 1
estimator = robotpy_apriltag.AprilTagPoseEstimator(
robotpy_apriltag.AprilTagPoseEstimator.Config(
0.2, 500, 500, img.shape[1] / 2.0, img.shape[0] / 2.0
)
)
est = estimator.estimateOrthogonalIteration(results[0], 50)
assert pytest.approx(est.pose1.rotation().x, abs=0.1) == math.radians(0)
assert pytest.approx(est.pose1.rotation().y, abs=0.1) == math.radians(0)
assert pytest.approx(est.pose1.rotation().z, abs=0.1) == math.radians(0)

View File

@@ -6,6 +6,11 @@ cppSrcFileInclude {
\.cpp$
}
generatedFileExclude {
src/main/python/
src/test/python/
}
licenseUpdateExclude {
examples/printlog
}

View File

@@ -0,0 +1,40 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"hatchling",
"hatch-nativelib~=0.2.0",
"hatch-robotpy~=0.2.1",
"robotpy-native-wpiutil==2027.0.0a2",
]
[project]
name = "robotpy-native-datalog"
version = "2027.0.0a2"
description = "WPILib Utility Library"
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-wpiutil==2027.0.0a2",
]
[tool.hatch.build.targets.wheel]
packages = ["src/native"]
[[tool.hatch.build.hooks.robotpy.maven_lib_download]]
artifact_id = "datalog-cpp"
group_id = "edu.wpi.first.datalog"
repo_url = "https://frcmaven.wpi.edu/artifactory/release-2027"
version = "2027.0.0-alpha-2"
extract_to = "src/native/datalog"
libs = ["datalog"]
[[tool.hatch.build.hooks.nativelib.pcfile]]
pcfile = "src/native/datalog/robotpy-native-datalog.pc"
name = "datalog"
includedir = "src/native/datalog/include"
libdir = "src/native/datalog/lib"
shared_libraries = ["datalog"]
requires = ["robotpy-native-wpiutil"]

View File

@@ -0,0 +1,63 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"semiwrap~=0.1.7",
"hatch-meson~=0.1.0b2",
"hatchling",
"robotpy-native-datalog==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2"
]
[project]
name = "robotpy-wpilog"
version = "2027.0.0a2"
description = "Binary wrapper for FRC wpilog library"
authors = [
{name = "RobotPy Development Team", email = "robotpy@googlegroups.com"},
]
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-datalog==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2"
]
[project.urls]
"Source code" = "https://github.com/robotpy/mostrobotpy"
[tool.hatch.build.hooks.robotpy]
version_file = "wpilog/version.py"
[tool.hatch.build.hooks.semiwrap]
[tool.hatch.build.hooks.meson]
[tool.hatch.build.targets.wheel]
packages = ["wpilog"]
[tool.semiwrap]
update_init = [
"wpilog"
]
scan_headers_ignore = [
# wpi/datalog
"wpi/datalog/DataLog_c.h",
"wpi/datalog/DataLogReaderThread.h",
"wpi/datalog/FileLogger.h",
]
[tool.semiwrap.extension_modules."wpilog._wpilog"]
name = "wpilog"
wraps = ["robotpy-native-datalog"]
depends = ["wpiutil"]
[tool.semiwrap.extension_modules."wpilog._wpilog".headers]
# wpi/datalog
DataLog = "wpi/datalog/DataLog.h"
DataLogBackgroundWriter = "wpi/datalog/DataLogBackgroundWriter.h"
DataLogReader = "wpi/datalog/DataLogReader.h"
# DataLogReaderThread = "wpi/datalog/DataLogReaderThread.h"
DataLogWriter = "wpi/datalog/DataLogWriter.h"
# DataLog_c = "wpi/datalog/DataLog_c.h"
# FileLogger = "wpi/datalog/FileLogger.h"

View File

@@ -0,0 +1,431 @@
# defaults:
# ignore: true
# report_ignored_missing: false
enums:
ControlRecordType:
classes:
wpi::log::DataLog:
attributes:
kBlockSize:
s_defaultMessageLog:
ignore: true
m_msglog:
ignore: true
methods:
DataLog:
ignore: true
Flush:
Pause:
Resume:
Stop:
HasSchema:
AddSchema:
overloads:
std::string_view, std::string_view, std::span<const uint8_t>, int64_t:
std::string_view, std::string_view, std::string_view, int64_t:
AddProtobufSchema:
ignore: true
AddStructSchema:
param_override:
info:
name: type
cpp_code: |
[](DataLog &self, const py::type &t, int64_t timestamp) {
WPyStructInfo info(t);
return self.AddStructSchema<WPyStruct, WPyStructInfo>(info, timestamp);
}
Start:
Finish:
SetMetadata:
AppendRaw:
AppendRaw2:
AppendBoolean:
AppendInteger:
AppendFloat:
AppendDouble:
AppendString:
AppendBooleanArray:
overloads:
int, std::span<const bool>, int64_t:
int, std::span<const int>, int64_t:
ignore: true
int, std::span<const uint8_t>, int64_t:
ignore: true
AppendIntegerArray:
AppendFloatArray:
AppendDoubleArray:
AppendStringArray:
overloads:
int, std::span<const std::string>, int64_t:
ignore: true
int, std::span<const std::string_view>, int64_t:
int, std::span<const struct WPI_String>, int64_t:
ignore: true
StartFile:
FlushBufs:
ignore: true
ReleaseBufs:
ignore: true
BufferHalfFull:
BufferFull:
wpi::log::DataLogEntry:
force_no_trampoline: true
methods:
SetMetadata:
Finish:
wpi::log::DataLogValueEntryImpl:
template_params:
- T
force_no_trampoline: true
attributes:
m_mutex:
ignore: true
m_lastValue:
ignore: true
methods:
HasLastValue:
GetLastValue:
DataLogValueEntryImpl:
overloads:
"":
ignore: true
DataLog&, std::string_view, std::string_view, std::string_view, int64_t:
wpi::log::RawLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
RawLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::BooleanLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
BooleanLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::IntegerLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
IntegerLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::FloatLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
FloatLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::DoubleLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
DoubleLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::StringLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
StringLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, std::string_view, int64_t:
Append:
Update:
wpi::log::BooleanArrayLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
BooleanArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
overloads:
std::span<const bool>, int64_t:
std::initializer_list<bool>, int64_t:
ignore: true
std::span<const int>, int64_t:
ignore: true
std::initializer_list<int>, int64_t:
ignore: true
std::span<const uint8_t>, int64_t:
ignore: true
Update:
overloads:
std::span<const bool>, int64_t:
std::initializer_list<bool>, int64_t:
ignore: true
std::span<const int>, int64_t:
std::initializer_list<int>, int64_t:
ignore: true
std::span<const uint8_t>, int64_t:
ignore: true
wpi::log::IntegerArrayLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
IntegerArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
overloads:
std::span<const int64_t>, int64_t:
std::initializer_list<int64_t>, int64_t:
ignore: true
Update:
overloads:
std::span<const int64_t>, int64_t:
std::initializer_list<int64_t>, int64_t:
ignore: true
wpi::log::FloatArrayLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
FloatArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
overloads:
std::span<const float>, int64_t:
std::initializer_list<float>, int64_t:
ignore: true
Update:
overloads:
std::span<const float>, int64_t:
std::initializer_list<float>, int64_t:
ignore: true
wpi::log::DoubleArrayLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
DoubleArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
overloads:
std::span<const double>, int64_t:
std::initializer_list<double>, int64_t:
ignore: true
Update:
overloads:
std::span<const double>, int64_t:
std::initializer_list<double>, int64_t:
ignore: true
wpi::log::StringArrayLogEntry:
force_no_trampoline: true
attributes:
kDataType:
methods:
StringArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
overloads:
std::span<const std::string>, int64_t:
ignore: true
std::span<const std::string_view>, int64_t:
std::initializer_list<std::string_view>, int64_t:
ignore: true
Update:
overloads:
std::span<const std::string>, int64_t:
ignore: true
std::span<const std::string_view>, int64_t:
std::initializer_list<std::string_view>, int64_t:
ignore: true
wpi::log::StructLogEntry:
force_no_trampoline: true
template_params:
- T
- I
methods:
StructLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, I..., int64_t:
param_override:
info:
name: type
cpp_code: |
[](DataLog &log, std::string_view name, const py::type &t, int64_t timestamp) {
WPyStructInfo info(t);
return std::make_shared<StructLogEntry<WPyStruct, WPyStructInfo>>(log, name, info, timestamp);
}
DataLog&, std::string_view, std::string_view, I..., int64_t:
param_override:
info:
name: type
cpp_code: |
[](DataLog &log, std::string_view name, std::string_view metadata, const py::type &t, int64_t timestamp) {
WPyStructInfo info(t);
return std::make_shared<StructLogEntry<WPyStruct, WPyStructInfo>>(log, name, metadata, info, timestamp);
}
Append:
Update:
HasLastValue:
GetLastValue:
wpi::log::StructArrayLogEntry:
force_no_trampoline: true
template_params:
- T
- I
methods:
StructArrayLogEntry:
overloads:
"":
ignore: true
DataLog&, std::string_view, I..., int64_t:
param_override:
info:
name: type
cpp_code: |
[](DataLog &log, std::string_view name, const py::type &t, int64_t timestamp) {
WPyStructInfo info(t);
return std::make_shared<StructArrayLogEntry<WPyStruct, WPyStructInfo>>(log, name, info, timestamp);
}
DataLog&, std::string_view, std::string_view, I..., int64_t:
param_override:
info:
name: type
cpp_code: |
[](DataLog &log, std::string_view name, std::string_view metadata, const py::type &t, int64_t timestamp) {
WPyStructInfo info(t);
return std::make_shared<StructArrayLogEntry<WPyStruct, WPyStructInfo>>(log, name, metadata, info, timestamp);
}
Append:
overloads:
U&&, int64_t:
ignore: true
std::span<const T>, int64_t:
Update:
HasLastValue:
GetLastValue:
wpi::log::ProtobufLogEntry:
force_no_trampoline: true
ignore: true
methods:
ProtobufLogEntry:
overloads:
"":
DataLog&, std::string_view, int64_t:
DataLog&, std::string_view, std::string_view, int64_t:
Append:
Update:
HasLastValue:
GetLastValue:
templates:
StructLogEntry:
qualname: wpi::log::StructLogEntry
params:
- WPyStruct
- WPyStructInfo
StructArrayLogEntry:
qualname: wpi::log::StructArrayLogEntry
params:
- WPyStruct
- WPyStructInfo
_RawLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<uint8_t>
_BooleanLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- bool
_IntegerLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- int64_t
_FloatLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- float
_DoubleLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- double
_StringLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::string
_BooleanArrayLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<int>
_IntegerArrayLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<int64_t>
_FloatArrayLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<float>
_DoubleArrayLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<double>
_StringArrayLogEntryImpl:
qualname: wpi::log::DataLogValueEntryImpl
params:
- std::vector<std::string>

View File

@@ -0,0 +1,16 @@
classes:
wpi::log::DataLogBackgroundWriter:
methods:
DataLogBackgroundWriter:
overloads:
std::string_view, std::string_view, double, std::string_view:
wpi::Logger&, std::string_view, std::string_view, double, std::string_view:
ignore: true
std::function<void (std::span<const uint8_t> data)>, double, std::string_view:
wpi::Logger&, std::function<void (std::span<const uint8_t> data)>, double, std::string_view:
ignore: true
SetFilename:
Flush:
Pause:
Resume:
Stop:

View File

@@ -0,0 +1,332 @@
classes:
wpi::log::StartRecordData:
attributes:
entry:
access: readonly
name:
access: readonly
type:
access: readonly
metadata:
access: readonly
wpi::log::MetadataRecordData:
attributes:
entry:
access: readonly
metadata:
access: readonly
wpi::log::DataLogRecord:
methods:
DataLogRecord:
overloads:
"":
ignore: true
int, int64_t, std::span<const uint8_t>:
ignore: true
GetEntry:
GetTimestamp:
GetSize:
GetRaw:
no_release_gil: true
cpp_code: |
[](const DataLogRecord *self) {
auto data = self->GetRaw();
return py::bytes((char*)data.data(), data.size());
}
IsControl:
IsStart:
IsFinish:
IsSetMetadata:
GetStartData:
no_release_gil: true
param_override:
out:
ignore: true
doc: |
Decodes a start control record. Raises TypeError on error.
cpp_code: |
[](const DataLogRecord *self) {
auto ptr = std::make_unique<wpi::log::StartRecordData>();
if (!self->GetStartData(ptr.get())) {
throw py::type_error("not a start record");
}
return ptr;
}
return_value_policy: reference_internal
GetFinishEntry:
no_release_gil: true
param_override:
out:
ignore: true
doc: |
Decodes a finish control record. Raises TypeError on error.
cpp_code: |
[](const DataLogRecord *self) {
int value;
if (!self->GetFinishEntry(&value)) {
throw py::type_error("not a finish entry");
}
return value;
}
GetSetMetadataData:
no_release_gil: true
param_override:
out:
ignore: true
doc: |
Decodes a set metadata control record. Raises TypeError on error.
cpp_code: |
[](const DataLogRecord *self) {
auto ptr = std::make_unique<wpi::log::MetadataRecordData>();
if (!self->GetSetMetadataData(ptr.get())) {
throw py::type_error("not a metadata control record");
}
return ptr;
}
return_value_policy: reference_internal
GetBoolean:
no_release_gil: true
param_override:
value:
ignore: true
doc: |
Decodes a data record as a boolean. Note if the data type (as indicated in
the corresponding start control record for this entry) is not "boolean",
invalid results may be returned or TypeError will be raised.
cpp_code: |
[](const DataLogRecord *self) {
bool value;
if (!self->GetBoolean(&value)) {
throw py::type_error("not a boolean");
}
return value;
}
GetInteger:
no_release_gil: true
param_override:
value:
ignore: true
doc: |
Decodes a data record as an integer. Note if the data type (as indicated in
the corresponding start control record for this entry) is not "int64",
invalid results may be returned or TypeError will be raised.
cpp_code: |
[](const DataLogRecord *self) {
int64_t value;
if (!self->GetInteger(&value)) {
throw py::type_error("not an integer");
}
return value;
}
GetFloat:
no_release_gil: true
param_override:
value:
ignore: true
doc: |
Decodes a data record as a float. Note if the data type (as indicated in
the corresponding start control record for this entry) is not "float",
invalid results may be returned or TypeError will be raised.
cpp_code: |
[](const DataLogRecord *self) {
float value;
if (!self->GetFloat(&value)) {
throw py::type_error("not a float");
}
return value;
}
GetDouble:
no_release_gil: true
param_override:
value:
ignore: true
doc: |
Decodes a data record as a double. Note if the data type (as indicated in
the corresponding start control record for this entry) is not "double",
invalid results may be returned or TypeError will be raised.
cpp_code: |
[](const DataLogRecord *self) {
double value;
if (!self->GetDouble(&value)) {
throw py::type_error("not a double");
}
return value;
}
GetString:
no_release_gil: true
param_override:
value:
ignore: true
doc: |
Decodes a data record as a string. Note if the data type (as indicated in
the corresponding start control record for this entry) is not "string",
invalid results may be returned or TypeError will be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::string_view value;
if (!self->GetString(&value)) {
throw py::type_error("not a string");
}
return value;
}
GetBooleanArray:
no_release_gil: true
param_override:
arr:
ignore: true
doc: |
Decodes a data record as a boolean array. Note if the data type (as
indicated in the corresponding start control record for this entry) is not
"boolean[]", invalid results may be returned or a TypeError may be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::vector<int> arr;
if (!self->GetBooleanArray(&arr)) {
throw py::type_error("not a boolean array");
}
py::list l(arr.size());
for (size_t i = 0; i < arr.size(); i++) {
auto b = py::bool_(arr[i]);
PyList_SET_ITEM(l.ptr(), i, b.release().ptr());
}
return l;
}
GetIntegerArray:
no_release_gil: true
param_override:
arr:
ignore: true
doc: |
Decodes a data record as an integer array. Note if the data type (as
indicated in the corresponding start control record for this entry) is not
"int64[]", invalid results may be returned or a TypeError may be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::vector<int64_t> arr;
if (!self->GetIntegerArray(&arr)) {
throw py::type_error("not an integer array");
}
return arr;
}
GetFloatArray:
no_release_gil: true
param_override:
arr:
ignore: true
doc: |
Decodes a data record as a float array. Note if the data type (as
indicated in the corresponding start control record for this entry) is not
"float[]", invalid results may be returned or a TypeError may be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::vector<float> arr;
if (!self->GetFloatArray(&arr)) {
throw py::type_error("not a float array");
}
return arr;
}
GetDoubleArray:
no_release_gil: true
param_override:
arr:
ignore: true
doc: |
Decodes a data record as a double array. Note if the data type (as
indicated in the corresponding start control record for this entry) is not
"double[]", invalid results may be returned or a TypeError may be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::vector<double> arr;
if (!self->GetDoubleArray(&arr)) {
throw py::type_error("not a double array");
}
return arr;
}
GetStringArray:
no_release_gil: true
param_override:
arr:
ignore: true
doc: |
Decodes a data record as a string array. Note if the data type (as
indicated in the corresponding start control record for this entry) is not
"string[]", invalid results may be returned or a TypeError may be raised.
cpp_code: |
[](const DataLogRecord *self) {
std::vector<std::string_view> arr;
if (!self->GetStringArray(&arr)) {
throw py::type_error("not a string array");
}
return arr;
}
wpi::log::DataLogIterator:
ignore: true
wpi::log::DataLogReader:
typealias:
- wpi::MemoryBuffer
methods:
DataLogReader:
ignore: true
IsValid:
GetVersion:
GetExtraHeader:
GetBufferIdentifier:
begin:
ignore: true
end:
ignore: true
inline_code: |
cls_StartRecordData
.def("__repr__", [](const wpi::log::StartRecordData &data) -> std::string {
return "StartRecordData(entry=" + std::to_string(data.entry) + ", "
"name=\"" + std::string(data.name) + "\", "
"type=\"" + std::string(data.type) + "\", "
"metadata=\"" + std::string(data.metadata) + "\")";
});
cls_MetadataRecordData
.def("__repr__", [](const wpi::log::MetadataRecordData &data) -> std::string {
return "MetadataRecordData(entry=" + std::to_string(data.entry) + ", "
"metadata=\"" + std::string(data.metadata) + "\")";
});
cls_DataLogReader
.def(py::init([](const std::string &filename) {
auto mbuf = wpi::MemoryBuffer::GetFile(filename);
if (!mbuf) {
py::gil_scoped_acquire gil;
#ifdef _WIN32
PyErr_SetFromWindowsErr(mbuf.error().value());
#else
errno = mbuf.error().value();
PyErr_SetFromErrno(PyExc_OSError);
#endif
throw py::error_already_set();
}
return std::make_shared<wpi::log::DataLogReader>(std::move(*mbuf));
}),
release_gil(), py::arg("filename"))
.def(py::init([](const py::buffer &buffer, const std::string &name) {
auto req = buffer.request();
if (req.itemsize != 1) {
throw py::value_error("buffer must only contain bytes");
} else if (req.ndim != 1) {
throw py::value_error("buffer must only have a single dimension");
}
auto mbuf = wpi::MemoryBuffer::GetMemBuffer(std::span((uint8_t*)req.ptr, req.size), name);
{
py::gil_scoped_release gil;
return std::make_shared<wpi::log::DataLogReader>(std::move(mbuf));
}
}),
py::arg("buffer"), py::arg("name") = "",
py::keep_alive<1, 2>())
.def("__iter__", [](wpi::log::DataLogReader * that) {
return py::make_iterator(that->begin(), that->end());
}, py::keep_alive<0,1>());

View File

@@ -0,0 +1,28 @@
classes:
wpi::log::DataLogWriter:
methods:
DataLogWriter:
overloads:
std::string_view, std::error_code&, std::string_view:
cpp_code: |
[](std::string_view filename, std::string_view extraHeader) {
std::error_code ec;
auto writer = std::make_unique<DataLogWriter>(filename, ec, extraHeader);
if (ec) {
throw std::system_error(ec);
}
return writer;
}
param_override:
ec:
ignore: true
wpi::Logger&, std::string_view, std::error_code&, std::string_view:
ignore: true
std::unique_ptr<wpi::raw_ostream>, std::string_view:
ignore: true
wpi::Logger&, std::unique_ptr<wpi::raw_ostream>, std::string_view:
ignore: true
Flush:
Stop:
GetStream:
ignore: true

View File

@@ -0,0 +1,6 @@
#include <semiwrap_init.wpilog._wpilog.hpp>
SEMIWRAP_PYBIND11_MODULE(m) {
initWrapper(m);
}

View File

@@ -0,0 +1,52 @@
from . import _init__wpilog
# autogenerated by 'semiwrap create-imports wpilog wpilog._wpilog'
from ._wpilog import (
BooleanArrayLogEntry,
BooleanLogEntry,
ControlRecordType,
DataLog,
DataLogBackgroundWriter,
DataLogEntry,
DataLogReader,
DataLogRecord,
DataLogWriter,
DoubleArrayLogEntry,
DoubleLogEntry,
FloatArrayLogEntry,
FloatLogEntry,
IntegerArrayLogEntry,
IntegerLogEntry,
MetadataRecordData,
RawLogEntry,
StartRecordData,
StringArrayLogEntry,
StringLogEntry,
StructArrayLogEntry,
StructLogEntry,
)
__all__ = [
"BooleanArrayLogEntry",
"BooleanLogEntry",
"ControlRecordType",
"DataLog",
"DataLogBackgroundWriter",
"DataLogEntry",
"DataLogReader",
"DataLogRecord",
"DataLogWriter",
"DoubleArrayLogEntry",
"DoubleLogEntry",
"FloatArrayLogEntry",
"FloatLogEntry",
"IntegerArrayLogEntry",
"IntegerLogEntry",
"MetadataRecordData",
"RawLogEntry",
"StartRecordData",
"StringArrayLogEntry",
"StringLogEntry",
"StructArrayLogEntry",
"StructLogEntry",
]

View File

View File

@@ -0,0 +1,5 @@
import wpilog
def test_existance():
pass

View File

@@ -18,6 +18,9 @@ generatedFileExclude {
hal/src/main/native/systemcore/rev/
UsageReporting\.h$
src/generated/main/native/cpp
src/main/python/
src/test/python/
}
modifiableFileExclude {

View File

@@ -0,0 +1,7 @@
robotpy-hal
===========
Python wrappers around the WPILib HAL.
API Documentation can be found at
https://robotpy.readthedocs.io/projects/hal/en/latest

View File

@@ -0,0 +1,12 @@
from .version import version as __version__
# Only needed for side effects
from . import _initialize
from .exceptions import HALError
from . import _init__wpiHal
from ._wpiHal import *
from ._wpiHal import __hal_simulation__
del _init__wpiHal

View File

@@ -0,0 +1,9 @@
from . import exceptions, _init__wpiHal, _wpiHal
# Always initialize HAL here, disable extension notice because we'll handle
# that for users
_sse = getattr(_wpiHal, "setShowExtensionsNotFoundMessages", None)
if _sse:
_wpiHal.setShowExtensionsNotFoundMessages(False)
_wpiHal.initialize(500, 0)

View File

@@ -0,0 +1,2 @@
class HALError(RuntimeError):
pass

View File

View File

@@ -0,0 +1,4 @@
from . import _init__simulation
from ._simulation import *
del _init__simulation

View File

@@ -0,0 +1,30 @@
#include <semiwrap_init.hal.simulation._simulation.hpp>
#include <pybind11/functional.h>
#include "sim_cb.h"
#include "sim_value_cb.h"
void HALSIM_ResetGlobalHandles();
SEMIWRAP_PYBIND11_MODULE(m) {
py::class_<SimCB> cls_SimCB(m, "SimCB");
cls_SimCB.doc() = "Simulation callback handle";
cls_SimCB.def("cancel", &SimCB::Cancel, py::doc("Cancel the callback"));
py::class_<SimValueCB> cls_SimValueCB(m, "SimValueCB");
cls_SimValueCB.doc() = "Simulation callback handle";
cls_SimValueCB.def("cancel", &SimValueCB::Cancel, py::doc("Cancel the callback"));
initWrapper(m);
m.def(
"resetGlobalHandles",
[]() {
#ifndef __FRC_SYSTEMCORE__
HALSIM_ResetGlobalHandles();
#endif
},
release_gil());
}

View File

@@ -0,0 +1,29 @@
#ifndef __FRC_SYSTEMCORE__
#include <hal/Notifier.h>
#include <hal/handles/HandlesInternal.h>
#include <hal/simulation/NotifierData.h>
void HALSIM_ResetGlobalHandles() {
// if we just reset the handles, notifiers might hang forever,
// so we just enumerate and cancel them all
auto sz = HALSIM_GetNotifierInfo(nullptr, 0);
if (sz > 0) {
struct HALSIM_NotifierInfo *info = new struct HALSIM_NotifierInfo[sz];
HALSIM_GetNotifierInfo(info, sz);
for (int i = 0; i < sz; i++) {
HAL_CleanNotifier(info->handle);
}
}
hal::HandleBase::ResetGlobalHandles();
}
#else
void HALSIM_ResetGlobalHandles() {}
#endif

View File

@@ -0,0 +1,33 @@
#pragma once
class SimCB {
public:
SimCB(std::function<void(void)> fn, std::function<void(int32_t)> cancel) :
m_fn(fn),
m_cancel(cancel)
{}
void SetUID(int32_t uid) {
m_uid = uid;
}
~SimCB() {
Cancel();
}
void Cancel() {
if (m_valid) {
m_cancel(m_uid);
m_valid = false;
}
}
std::function<void(void)> m_fn;
private:
bool m_valid = true;
int32_t m_uid;
std::function<void(int32_t)> m_cancel;
};

View File

@@ -0,0 +1,37 @@
#pragma once
#include <hal/SimDevice.h>
class SimValueCB {
public:
using FnType = std::function<void(const char *, HAL_SimValueHandle, HAL_SimValueDirection, HAL_Value)>;
SimValueCB(FnType fn, std::function<void(int32_t)> cancel) :
m_fn(fn),
m_cancel(cancel)
{}
void SetUID(int32_t uid) {
m_uid = uid;
}
~SimValueCB() {
Cancel();
}
void Cancel() {
if (m_valid) {
m_cancel(m_uid);
m_valid = false;
}
}
FnType m_fn;
private:
bool m_valid = true;
int32_t m_uid;
std::function<void(int32_t)> m_cancel;
};

View File

@@ -0,0 +1,16 @@
#pragma once
#include <pybind11/pybind11.h>
#include "hal/DriverStationTypes.h"
namespace pybind11 {
template <>
struct format_descriptor<HAL_JoystickPOV> {
static constexpr const char c = 'B';
static constexpr const char value[2] = {c, '\0'};
static std::string format() { return std::string(1, c); }
};
}

View File

@@ -0,0 +1,110 @@
#include <hal/HALBase.h>
#include <hal/DriverStation.h>
#include <hal/Value.h>
#include <semiwrap_init.hal._wpiHal.hpp>
using namespace pybind11::literals;
static py::module_ sys_module;
SEMIWRAP_PYBIND11_MODULE(m) {
// Add this manually so it can be used from SimValue
py::enum_<HAL_Type>(m, "Type")
.value("UNASSIGNED", HAL_Type::HAL_UNASSIGNED)
.value("BOOLEAN", HAL_Type::HAL_BOOLEAN)
.value("DOUBLE", HAL_Type::HAL_DOUBLE)
.value("ENUM", HAL_Type::HAL_ENUM)
.value("INT", HAL_Type::HAL_INT)
.value("LONG", HAL_Type::HAL_LONG);
// Add this manually because it would be annoying to do otherwise
py::class_<HAL_Value>(m, "Value")
.def_readonly("type", &HAL_Value::type)
.def_property_readonly("value",
[](const HAL_Value &self) -> py::object {
switch (self.type) {
case HAL_BOOLEAN:
return py::bool_(self.data.v_boolean);
case HAL_DOUBLE:
return py::float_(self.data.v_double);
case HAL_ENUM:
return py::int_(self.data.v_enum);
case HAL_INT:
return py::int_(self.data.v_int);
case HAL_LONG:
return py::int_(self.data.v_long);
default:
return py::none();
}
}
)
.def("__repr__", [](const HAL_Value &self) -> py::str {
switch (self.type) {
case HAL_BOOLEAN:
return "<Value type=bool value=" + std::to_string(self.data.v_boolean) + ">";
case HAL_DOUBLE:
return "<Value type=double value=" + std::to_string(self.data.v_double) + ">";
case HAL_ENUM:
return "<Value type=enum value=" + std::to_string(self.data.v_enum) + ">";
case HAL_INT:
return "<Value type=int value=" + std::to_string(self.data.v_int) + ">";
case HAL_LONG:
return "<Value type=long value=" + std::to_string(self.data.v_long) + ">";
default:
return "<Value type=invalid>";
}
});
initWrapper(m);
#ifdef __FRC_SYSTEMCORE__
m.attr("__halplatform__") = "Systemcore";
m.attr("__hal_simulation__") = false;
#else
m.attr("__halplatform__") = "sim";
m.attr("__hal_simulation__") = true;
m.def("__test_senderr", []() {
HAL_SendError(1, 2, 0, "\xfa" "badmessage", "location", "callstack", 1);
}, release_gil());
#endif
// Redirect stderr to python stderr
sys_module = py::module_::import("sys");
HAL_SetPrintErrorImpl([](const char *line, size_t size) {
if (size == 0) {
return;
}
py::gil_scoped_acquire lock;
PyObject *o = PyUnicode_DecodeUTF8(line, size, "replace");
if (o == nullptr) {
PyErr_Clear();
py::print(py::bytes(line, size), "file"_a=sys_module.attr("stderr"));
} else {
py::print(py::reinterpret_steal<py::str>(o), "file"_a=sys_module.attr("stderr"));
}
});
// Do cleanup on module unload
static int unused; // the capsule needs something to reference
py::capsule cleanup(&unused, [](void *) {
{
py::gil_scoped_acquire lock;
HAL_SetPrintErrorImpl(nullptr);
sys_module.dec_ref();
sys_module.release();
}
{
py::gil_scoped_release unlock;
HAL_Shutdown();
}
});
m.add_object("_cleanup", cleanup);
}

View File

@@ -0,0 +1,41 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"hatchling",
"hatch-nativelib~=0.2.0",
"hatch-robotpy~=0.2.1",
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-ntcore==2027.0.0a2",
]
[project]
name = "robotpy-native-wpihal"
version = "2027.0.0a2"
description = "WPILib HAL implementation"
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-ntcore==2027.0.0a2",
]
[tool.hatch.build.targets.wheel]
packages = ["src/native"]
[[tool.hatch.build.hooks.robotpy.maven_lib_download]]
artifact_id = "hal-cpp"
group_id = "edu.wpi.first.hal"
repo_url = "https://frcmaven.wpi.edu/artifactory/release-2027"
version = "2027.0.0-alpha-2"
extract_to = "src/native/wpihal"
libs = ["wpiHal"]
[[tool.hatch.build.hooks.nativelib.pcfile]]
pcfile = "src/native/wpihal/robotpy-native-wpihal.pc"
name = "wpihal"
includedir = "src/native/wpihal/include"
libdir = "src/native/wpihal/lib"
shared_libraries = ["wpiHal"]
requires = ["robotpy-native-wpiutil", "robotpy-native-ntcore"]

View File

@@ -0,0 +1,169 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"semiwrap~=0.1.7",
"hatch-meson~=0.1.0b2",
"hatchling",
"pyntcore==2027.0.0a2",
"robotpy-native-wpihal==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2",
]
[project]
name = "robotpy-hal"
version = "2027.0.0a2"
description = "Binary wrapper for FRC HAL"
authors = [
{name = "RobotPy Development Team", email = "robotpy@googlegroups.com"},
]
license = "BSD-3-Clause"
dependencies = [
"pyntcore==2027.0.0a2",
"robotpy-native-wpihal==2027.0.0a2",
"robotpy-wpiutil==2027.0.0a2",
]
[project.urls]
"Source code" = "https://github.com/robotpy/mostrobotpy"
[tool.hatch.build.hooks.robotpy]
version_file = "hal/version.py"
[tool.hatch.build.hooks.semiwrap]
[tool.hatch.build.hooks.meson]
[tool.hatch.build.targets.wheel]
packages = ["hal"]
[tool.semiwrap]
update_init = []
scan_headers_ignore = [
"hal/ChipObject.h",
"hal/DMA.h",
"hal/Errors.h",
"hal/HAL.h",
"hal/IMU.h",
"hal/IMUTypes.h",
"hal/SystemServer.h",
"hal/Types.h",
"hal/Value.h",
"hal/cpp/SerialHelper.h",
"hal/cpp/UnsafeDIO.h",
"hal/cpp/fpga_clock.h",
"hal/handles/DigitalHandleResource.h",
"hal/handles/IndexedClassedHandleResource.h",
"hal/handles/IndexedHandleResource.h",
"hal/handles/LimitedClassedHandleResource.h",
"hal/handles/LimitedHandleResource.h",
"hal/handles/UnlimitedHandleResource.h",
"hal/proto/*",
"hal/roborio/HMB.h",
"hal/roborio/InterruptManager.h",
"hal/simulation/CanData.h",
"hal/simulation/I2CData.h",
"hal/simulation/NotifyListener.h",
"hal/simulation/SPIData.h",
"hal/simulation/SimCallbackRegistry.h",
"hal/simulation/SimDataValue.h",
# TODO: might want this in the future
"mrc/*",
"src/ds_types_fmt.h",
"sim_cb.h",
"sim_value_cb.h",
]
[tool.semiwrap.extension_modules."hal._wpiHal"]
name = "wpihal"
wraps = ["robotpy-native-wpihal"]
depends = ["wpiutil", "ntcore"]
[tool.semiwrap.extension_modules."hal._wpiHal".headers]
# hal
AddressableLED = "hal/AddressableLED.h"
AddressableLEDTypes = "hal/AddressableLEDTypes.h"
AnalogInput = "hal/AnalogInput.h"
CAN = "hal/CAN.h"
CANAPI = "hal/CANAPI.h"
CANAPITypes = "hal/CANAPITypes.h"
CTREPCM = "hal/CTREPCM.h"
Constants = "hal/Constants.h"
Counter = "hal/Counter.h"
DIO = "hal/DIO.h"
# DMA = "hal/DMA.h"
DriverStation = "hal/DriverStation.h"
DriverStationTypes = "hal/DriverStationTypes.h"
DutyCycle = "hal/DutyCycle.h"
Encoder = "hal/Encoder.h"
# Errors = "hal/Errors.h"
Extensions = "hal/Extensions.h"
# HAL = "hal/HAL.h"
HALBase = "hal/HALBase.h"
I2C = "hal/I2C.h"
I2CTypes = "hal/I2CTypes.h"
# IMU = "hal/IMU.h"
# IMUTypes = "hal/IMUTypes.h"
Main = "hal/Main.h"
Notifier = "hal/Notifier.h"
PWM = "hal/PWM.h"
Ports = "hal/Ports.h"
Power = "hal/Power.h"
PowerDistribution = "hal/PowerDistribution.h"
REVPH = "hal/REVPH.h"
SerialPort = "hal/SerialPort.h"
SimDevice = "hal/SimDevice.h"
UsageReporting = "hal/UsageReporting.h"
Threads = "hal/Threads.h"
# Types = "hal/Types.h"
# Value = "hal/Value.h"
# hal/cpp
# fpga_clock = "hal/cpp/fpga_clock.h"
# hal/handles
# DigitalHandleResource = "hal/handles/DigitalHandleResource.h"
HandlesInternal = "hal/handles/HandlesInternal.h"
# IndexedClassedHandleResource = "hal/handles/IndexedClassedHandleResource.h"
# IndexedHandleResource = "hal/handles/IndexedHandleResource.h"
# LimitedClassedHandleResource = "hal/handles/LimitedClassedHandleResource.h"
# LimitedHandleResource = "hal/handles/LimitedHandleResource.h"
# UnlimitedHandleResource = "hal/handles/UnlimitedHandleResource.h"
[tool.semiwrap.extension_modules."hal.simulation._simulation"]
name = "hal_simulation"
wraps = ["robotpy-native-wpihal"]
depends = ["wpiutil", "ntcore"]
yaml_path = "semiwrap/simulation"
[tool.semiwrap.extension_modules."hal.simulation._simulation".headers]
AddressableLEDData = "hal/simulation/AddressableLEDData.h"
AnalogInData = "hal/simulation/AnalogInData.h"
CTREPCMData = "hal/simulation/CTREPCMData.h"
# CanData = "hal/simulation/CanData.h"
DIOData = "hal/simulation/DIOData.h"
DigitalPWMData = "hal/simulation/DigitalPWMData.h"
DriverStationData = "hal/simulation/DriverStationData.h"
DutyCycleData = "hal/simulation/DutyCycleData.h"
EncoderData = "hal/simulation/EncoderData.h"
# I2CData = "hal/simulation/I2CData.h"
MockHooks = "hal/simulation/MockHooks.h"
NotifierData = "hal/simulation/NotifierData.h"
# NotifyListener = "hal/simulation/NotifyListener.h"
PWMData = "hal/simulation/PWMData.h"
PowerDistributionData = "hal/simulation/PowerDistributionData.h"
REVPHData = "hal/simulation/REVPHData.h"
Reset = "hal/simulation/Reset.h"
RoboRioData = "hal/simulation/RoboRioData.h"
# SimCallbackRegistry = "hal/simulation/SimCallbackRegistry.h"
# SimDataValue = "hal/simulation/SimDataValue.h"
SimDeviceData = "hal/simulation/SimDeviceData.h"

View File

@@ -0,0 +1,9 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeAddressableLED:
HAL_FreeAddressableLED:
HAL_SetAddressableLEDLength:
HAL_SetAddressableLEDStart:
HAL_SetAddressableLEDData:

View File

@@ -0,0 +1,14 @@
strip_prefixes:
- HAL_
classes:
HAL_AddressableLEDData:
attributes:
b:
g:
r:
enums:
HAL_AddressableLEDColorOrder:
functions:
format_as:
ignore: true

View File

@@ -0,0 +1,23 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeAnalogInputPort:
HAL_FreeAnalogInputPort:
HAL_CheckAnalogModule:
HAL_CheckAnalogInputChannel:
HAL_SetAnalogInputSimDevice:
HAL_SetAnalogSampleRate:
HAL_GetAnalogSampleRate:
HAL_SetAnalogAverageBits:
HAL_GetAnalogAverageBits:
HAL_SetAnalogOversampleBits:
HAL_GetAnalogOversampleBits:
HAL_GetAnalogValue:
HAL_GetAnalogAverageValue:
HAL_GetAnalogVoltsToValue:
HAL_GetAnalogVoltage:
HAL_GetAnalogAverageVoltage:
HAL_GetAnalogLSBWeight:
HAL_GetAnalogOffset:
HAL_GetAnalogValueToVolts:

View File

@@ -0,0 +1,16 @@
strip_prefixes:
- HAL_
functions:
HAL_CAN_SendMessage:
HAL_CAN_ReceiveMessage:
HAL_CAN_OpenStreamSession:
HAL_CAN_CloseStreamSession:
HAL_CAN_ReadStreamSession:
ignore: true # TODO: an array of messages
HAL_CAN_GetCANStatus:
classes:
HAL_CANStreamMessage:
attributes:
messageId:
message:

View File

@@ -0,0 +1,13 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeCAN:
HAL_CleanCAN:
HAL_WriteCANPacket:
HAL_WriteCANPacketRepeating:
HAL_WriteCANRTRFrame:
HAL_StopCANPacketRepeating:
HAL_ReadCANPacketNew:
HAL_ReadCANPacketLatest:
HAL_ReadCANPacketTimeout:

View File

@@ -0,0 +1,19 @@
strip_prefixes:
- HAL_
enums:
HAL_CANDeviceType:
value_prefix: HAL_CAN_Dev
HAL_CANManufacturer:
value_prefix: HAL_CAN_Man
HAL_CANFlags:
classes:
HAL_CANMessage:
attributes:
flags:
dataSize:
data:
HAL_CANReceiveMessage:
attributes:
timeStamp:
message:

View File

@@ -0,0 +1,26 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeCTREPCM:
HAL_FreeCTREPCM:
HAL_CheckCTREPCMSolenoidChannel:
HAL_GetCTREPCMCompressor:
HAL_SetCTREPCMClosedLoopControl:
HAL_GetCTREPCMClosedLoopControl:
HAL_GetCTREPCMPressureSwitch:
HAL_GetCTREPCMCompressorCurrent:
HAL_GetCTREPCMCompressorCurrentTooHighFault:
HAL_GetCTREPCMCompressorCurrentTooHighStickyFault:
HAL_GetCTREPCMCompressorShortedStickyFault:
HAL_GetCTREPCMCompressorShortedFault:
HAL_GetCTREPCMCompressorNotConnectedStickyFault:
HAL_GetCTREPCMCompressorNotConnectedFault:
HAL_GetCTREPCMSolenoids:
HAL_SetCTREPCMSolenoids:
HAL_GetCTREPCMSolenoidDisabledList:
HAL_GetCTREPCMSolenoidVoltageStickyFault:
HAL_GetCTREPCMSolenoidVoltageFault:
HAL_ClearAllCTREPCMStickyFaults:
HAL_FireCTREPCMOneShot:
HAL_SetCTREPCMOneShotDuration:

View File

@@ -0,0 +1,5 @@
strip_prefixes:
- HAL_
functions:
HAL_GetSystemClockTicksPerMicrosecond:

View File

@@ -0,0 +1,12 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeCounter:
HAL_FreeCounter:
HAL_ResetCounter:
HAL_GetCounter:
HAL_GetCounterPeriod:
HAL_SetCounterMaxPeriod:
HAL_GetCounterStopped:
HAL_SetCounterEdgeConfiguration:

View File

@@ -0,0 +1,22 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeDIOPort:
HAL_CheckDIOChannel:
HAL_FreeDIOPort:
HAL_SetDIOSimDevice:
HAL_AllocateDigitalPWM:
HAL_FreeDigitalPWM:
HAL_SetDigitalPWMRate:
HAL_SetDigitalPWMDutyCycle:
HAL_SetDigitalPWMPPS:
HAL_SetDigitalPWMOutputChannel:
HAL_SetDIO:
HAL_SetDIODirection:
HAL_GetDIO:
HAL_GetDIODirection:
HAL_Pulse:
HAL_PulseMultiple:
HAL_IsPulsing:
HAL_IsAnyPulsing:

View File

@@ -0,0 +1,42 @@
strip_prefixes:
- HAL_
functions:
HAL_SendError:
HAL_SetPrintErrorImpl:
ignore: true
HAL_SendConsoleLine:
HAL_GetControlWord:
HAL_GetAllianceStation:
HAL_GetJoystickAxes:
HAL_GetJoystickPOVs:
HAL_GetJoystickButtons:
HAL_GetAllJoystickData:
HAL_GetJoystickDescriptor:
HAL_GetJoystickType:
HAL_GetJoystickName:
param_override:
name:
ignore: true
cpp_code: |
[](int32_t joystickNum) {
WPI_String name;
HAL_GetJoystickName(&name, joystickNum);
std::string sname(wpi::to_string_view(&name));
WPI_FreeString(&name);
return sname;
}
HAL_GetJoystickAxisType:
HAL_SetJoystickOutputs:
HAL_GetMatchTime:
HAL_GetOutputsEnabled:
HAL_GetMatchInfo:
HAL_RefreshDSData:
HAL_ProvideNewDataEventHandle:
HAL_RemoveNewDataEventHandle:
HAL_ObserveUserProgramStarting:
HAL_ObserveUserProgramDisabled:
HAL_ObserveUserProgramAutonomous:
HAL_ObserveUserProgramTeleop:
HAL_ObserveUserProgramTest:
HAL_GetJoystickIsGamepad:

View File

@@ -0,0 +1,53 @@
strip_prefixes:
- HAL_
extra_includes:
- src/ds_types_fmt.h
enums:
HAL_AllianceStationID:
value_prefix: HAL_AllianceStationID
HAL_JoystickPOV:
value_prefix: HAL_JoystickPOV
HAL_MatchType:
value_prefix: HAL_kMatchType
classes:
HAL_ControlWord:
attributes:
enabled:
autonomous:
test:
eStop:
fmsAttached:
dsAttached:
control_reserved:
HAL_JoystickAxes:
attributes:
count:
axes:
raw:
HAL_JoystickPOVs:
attributes:
count:
povs:
HAL_JoystickButtons:
attributes:
buttons:
count:
HAL_JoystickDescriptor:
attributes:
type:
name:
axisCount:
axisTypes:
buttonCount:
povCount:
isGamepad:
HAL_MatchInfo:
attributes:
eventName:
matchType:
matchNumber:
replayNumber:
gameSpecificMessage:
gameSpecificMessageSize:

View File

@@ -0,0 +1,11 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeDutyCycle:
HAL_FreeDutyCycle:
HAL_SetDutyCycleSimDevice:
ifndef: __FRC_SYSTEMCORE__
HAL_GetDutyCycleFrequency:
HAL_GetDutyCycleOutput:
HAL_GetDutyCycleHighTime:

View File

@@ -0,0 +1,31 @@
strip_prefixes:
- HAL_
enums:
HAL_EncoderIndexingType:
value_prefix: HAL
HAL_EncoderEncodingType:
value_prefix: HAL
functions:
HAL_InitializeEncoder:
HAL_FreeEncoder:
HAL_SetEncoderSimDevice:
HAL_GetEncoder:
HAL_GetEncoderRaw:
HAL_GetEncoderEncodingScale:
HAL_ResetEncoder:
HAL_GetEncoderPeriod:
HAL_SetEncoderMaxPeriod:
HAL_GetEncoderStopped:
HAL_GetEncoderDirection:
HAL_GetEncoderDistance:
HAL_GetEncoderRate:
HAL_SetEncoderMinRate:
HAL_SetEncoderDistancePerPulse:
HAL_SetEncoderReverseDirection:
HAL_SetEncoderSamplesToAverage:
HAL_GetEncoderSamplesToAverage:
HAL_GetEncoderFPGAIndex:
HAL_GetEncoderDecodingScaleFactor:
HAL_GetEncoderDistancePerPulse:
HAL_GetEncoderEncodingType:

View File

@@ -0,0 +1,16 @@
strip_prefixes:
- HAL_
functions:
HAL_LoadOneExtension:
ifndef: __FRC_SYSTEMCORE__
HAL_LoadExtensions:
ifndef: __FRC_SYSTEMCORE__
HAL_RegisterExtension:
ignore: true
HAL_RegisterExtensionListener:
ignore: true
HAL_SetShowExtensionsNotFoundMessages:
ifndef: __FRC_SYSTEMCORE__
HAL_OnShutdown:
ignore: true

View File

@@ -0,0 +1,47 @@
strip_prefixes:
- HAL_
enums:
HAL_RuntimeType:
functions:
HAL_GetErrorMessage:
HAL_GetFPGAVersion:
HAL_GetFPGARevision:
HAL_GetSerialNumber:
param_override:
serialNumber:
ignore: true
cpp_code: |
[]() {
WPI_String s;
HAL_GetSerialNumber(&s);
std::string ss(wpi::to_string_view(&s));
WPI_FreeString(&s);
return ss;
}
HAL_GetComments:
param_override:
comments:
ignore: true
cpp_code: |
[]() {
WPI_String s;
HAL_GetComments(&s);
std::string ss(wpi::to_string_view(&s));
WPI_FreeString(&s);
return ss;
}
HAL_GetTeamNumber:
HAL_GetRuntimeType:
HAL_GetSystemActive:
HAL_GetBrownedOut:
HAL_GetFPGATime:
HAL_ExpandFPGATime:
HAL_GetRSLState:
HAL_GetSystemTimeValid:
HAL_Initialize:
HAL_Shutdown:
HAL_SimPeriodicBefore:
HAL_SimPeriodicAfter:
HAL_GetLastError:
HAL_GetCommsDisableCount:

View File

@@ -0,0 +1,15 @@
strip_prefixes:
- HAL_
enums:
HAL_HandleEnum:
functions:
getHandleIndex:
getHandleType:
isHandleType:
isHandleCorrectVersion:
getHandleTypedIndex:
createHandle:
classes:
hal::HandleBase:
ignore: true

View File

@@ -0,0 +1,16 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeI2C:
HAL_TransactionI2C:
buffers:
- {type: IN, src: dataToSend, len: sendSize}
- {type: OUT, src: dataReceived, len: receiveSize}
HAL_WriteI2C:
buffers:
- {type: IN, src: dataToSend, len: sendSize}
HAL_ReadI2C:
buffers:
- {type: OUT, src: buffer, len: count}
HAL_CloseI2C:

View File

@@ -0,0 +1,6 @@
strip_prefixes:
- HAL_
enums:
HAL_I2CPort:
value_prefix: HAL_I2C

View File

@@ -0,0 +1,9 @@
strip_prefixes:
- HAL_
functions:
HAL_SetMain:
ignore: true # TODO
HAL_HasMain:
HAL_RunMain:
HAL_ExitMain:

View File

@@ -0,0 +1,12 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializeNotifier:
HAL_SetNotifierName:
HAL_StopNotifier:
HAL_CleanNotifier:
HAL_UpdateNotifierAlarm:
HAL_CancelNotifierAlarm:
HAL_WaitForNotifierAlarm:
HAL_SetNotifierThreadPriority:

View File

@@ -0,0 +1,11 @@
strip_prefixes:
- HAL_
functions:
HAL_InitializePWMPort:
HAL_FreePWMPort:
HAL_CheckPWMChannel:
HAL_SetPWMPulseTimeMicroseconds:
HAL_GetPWMPulseTimeMicroseconds:
HAL_SetPWMSimDevice:
HAL_SetPWMOutputPeriod:

View File

@@ -0,0 +1,22 @@
strip_prefixes:
- HAL_
functions:
HAL_GetNumAnalogInputs:
HAL_GetNumCounters:
HAL_GetNumDigitalChannels:
HAL_GetNumPWMChannels:
HAL_GetNumDigitalPWMOutputs:
HAL_GetNumEncoders:
HAL_GetNumInterrupts:
HAL_GetNumDutyCycles:
HAL_GetNumAddressableLEDs:
HAL_GetNumCTREPCMModules:
HAL_GetNumCTRESolenoidChannels:
HAL_GetNumCTREPDPModules:
HAL_GetNumCTREPDPChannels:
HAL_GetNumREVPDHModules:
HAL_GetNumREVPDHChannels:
HAL_GetNumREVPHModules:
HAL_GetNumREVPHChannels:
HAL_GetNumCanBuses:

View File

@@ -0,0 +1,14 @@
strip_prefixes:
- HAL_
functions:
HAL_GetVinVoltage:
HAL_GetUserVoltage3V3:
HAL_GetUserCurrent3V3:
HAL_GetUserActive3V3:
HAL_GetUserCurrentFaults3V3:
HAL_SetUserRailEnabled3V3:
HAL_GetBrownoutVoltage:
HAL_SetBrownoutVoltage:
HAL_GetCPUTemp:
HAL_ResetUserCurrentFaults:

View File

@@ -0,0 +1,105 @@
strip_prefixes:
- HAL_
enums:
HAL_PowerDistributionType:
functions:
HAL_InitializePowerDistribution:
HAL_GetPowerDistributionModuleNumber:
HAL_CleanPowerDistribution:
HAL_CheckPowerDistributionChannel:
HAL_CheckPowerDistributionModule:
HAL_GetPowerDistributionType:
HAL_GetPowerDistributionNumChannels:
HAL_GetPowerDistributionTemperature:
HAL_GetPowerDistributionVoltage:
HAL_GetPowerDistributionChannelCurrent:
HAL_GetPowerDistributionAllChannelCurrents:
HAL_GetPowerDistributionTotalCurrent:
HAL_GetPowerDistributionTotalPower:
HAL_GetPowerDistributionTotalEnergy:
HAL_ResetPowerDistributionTotalEnergy:
HAL_ClearPowerDistributionStickyFaults:
HAL_SetPowerDistributionSwitchableChannel:
HAL_GetPowerDistributionSwitchableChannel:
HAL_GetPowerDistributionVersion:
HAL_GetPowerDistributionFaults:
HAL_GetPowerDistributionStickyFaults:
HAL_StartPowerDistributionStream:
ifdef: __FRC_SYSTEMCORE__
HAL_GetPowerDistributionStreamData:
ifdef: __FRC_SYSTEMCORE__
HAL_FreePowerDistributionStreamData:
ifdef: __FRC_SYSTEMCORE__
HAL_StopPowerDistributionStream:
ifdef: __FRC_SYSTEMCORE__
classes:
HAL_PowerDistributionVersion:
attributes:
firmwareMajor:
firmwareMinor:
firmwareFix:
hardwareMinor:
hardwareMajor:
uniqueId:
HAL_PowerDistributionFaults:
attributes:
channel0BreakerFault:
channel1BreakerFault:
channel2BreakerFault:
channel3BreakerFault:
channel4BreakerFault:
channel5BreakerFault:
channel6BreakerFault:
channel7BreakerFault:
channel8BreakerFault:
channel9BreakerFault:
channel10BreakerFault:
channel11BreakerFault:
channel12BreakerFault:
channel13BreakerFault:
channel14BreakerFault:
channel15BreakerFault:
channel16BreakerFault:
channel17BreakerFault:
channel18BreakerFault:
channel19BreakerFault:
channel20BreakerFault:
channel21BreakerFault:
channel22BreakerFault:
channel23BreakerFault:
brownout:
canWarning:
hardwareFault:
HAL_PowerDistributionStickyFaults:
attributes:
channel0BreakerFault:
channel1BreakerFault:
channel2BreakerFault:
channel3BreakerFault:
channel4BreakerFault:
channel5BreakerFault:
channel6BreakerFault:
channel7BreakerFault:
channel8BreakerFault:
channel9BreakerFault:
channel10BreakerFault:
channel11BreakerFault:
channel12BreakerFault:
channel13BreakerFault:
channel14BreakerFault:
channel15BreakerFault:
channel16BreakerFault:
channel17BreakerFault:
channel18BreakerFault:
channel19BreakerFault:
channel20BreakerFault:
channel21BreakerFault:
channel22BreakerFault:
channel23BreakerFault:
brownout:
canWarning:
canBusOff:
hasReset:
hardwareFault:
firmwareFault:

View File

@@ -0,0 +1,82 @@
strip_prefixes:
- HAL_
enums:
HAL_REVPHCompressorConfigType:
functions:
HAL_InitializeREVPH:
HAL_FreeREVPH:
HAL_CheckREVPHSolenoidChannel:
HAL_CheckREVPHModuleNumber:
HAL_GetREVPHCompressor:
HAL_SetREVPHCompressorConfig:
HAL_SetREVPHClosedLoopControlDisabled:
HAL_SetREVPHClosedLoopControlDigital:
HAL_SetREVPHClosedLoopControlAnalog:
HAL_SetREVPHClosedLoopControlHybrid:
HAL_GetREVPHCompressorConfig:
HAL_GetREVPHPressureSwitch:
HAL_GetREVPHCompressorCurrent:
HAL_GetREVPHAnalogVoltage:
HAL_GetREVPHVoltage:
HAL_GetREVPH5VVoltage:
HAL_GetREVPHSolenoidCurrent:
HAL_GetREVPHSolenoidVoltage:
HAL_GetREVPHVersion:
HAL_GetREVPHSolenoids:
HAL_SetREVPHSolenoids:
HAL_FireREVPHOneShot:
HAL_GetREVPHFaults:
HAL_GetREVPHStickyFaults:
HAL_ClearREVPHStickyFaults:
HAL_GetREVPHSolenoidDisabledList:
classes:
HAL_REVPHVersion:
attributes:
firmwareMajor:
firmwareMinor:
firmwareFix:
hardwareMinor:
hardwareMajor:
uniqueId:
HAL_REVPHCompressorConfig:
attributes:
minAnalogVoltage:
maxAnalogVoltage:
forceDisable:
useDigital:
HAL_REVPHFaults:
attributes:
channel0Fault:
channel1Fault:
channel2Fault:
channel3Fault:
channel4Fault:
channel5Fault:
channel6Fault:
channel7Fault:
channel8Fault:
channel9Fault:
channel10Fault:
channel11Fault:
channel12Fault:
channel13Fault:
channel14Fault:
channel15Fault:
compressorOverCurrent:
compressorOpen:
solenoidOverCurrent:
brownout:
canWarning:
hardwareFault:
HAL_REVPHStickyFaults:
attributes:
compressorOverCurrent:
compressorOpen:
solenoidOverCurrent:
brownout:
canWarning:
canBusOff:
hasReset:
hardwareFault:
firmwareFault:

View File

@@ -0,0 +1,30 @@
strip_prefixes:
- HAL_
enums:
HAL_SerialPort:
functions:
HAL_InitializeSerialPort:
HAL_InitializeSerialPortDirect:
HAL_GetSerialFD:
HAL_SetSerialBaudRate:
HAL_SetSerialDataBits:
HAL_SetSerialParity:
HAL_SetSerialStopBits:
HAL_SetSerialWriteMode:
HAL_SetSerialFlowControl:
HAL_SetSerialTimeout:
HAL_EnableSerialTermination:
HAL_DisableSerialTermination:
HAL_SetSerialReadBufferSize:
HAL_SetSerialWriteBufferSize:
HAL_GetSerialBytesReceived:
HAL_ReadSerial:
buffers:
- {type: OUT, src: buffer, len: count}
HAL_WriteSerial:
buffers:
- {type: IN, src: buffer, len: count}
HAL_FlushSerial:
HAL_ClearSerial:
HAL_CloseSerial:

View File

@@ -0,0 +1,376 @@
defaults:
ignore: true
report_ignored_missing: false
extra_includes:
- hal/simulation/SimDeviceData.h
strip_prefixes:
- HAL_
enums:
HAL_SimValueDirection:
classes:
hal::SimValue:
doc: |
Readonly wrapper around a HAL simulator value.
It is not useful to construct these directly -- they are returned from
:meth:`.SimDeviceSim.getValue` or :meth:`.SimDevice.createValue`.
methods:
SimValue:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
GetValue:
ignore: true
SetValue:
ignore: true
hal::SimInt:
doc: |
Wrapper around a HAL simulator int value handle.
It is not useful to construct these directly, they are returned
from various functions.
force_no_trampoline: true
methods:
SimInt:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
Get:
Set:
Reset:
hal::SimLong:
doc: |
Wrapper around a HAL simulator long value handle.
It is not useful to construct these directly, they are returned
from various functions.
force_no_trampoline: true
methods:
SimLong:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
Get:
Set:
Reset:
hal::SimDouble:
doc: |
Wrapper around a HAL simulator double value.
It is not useful to construct these directly -- they are returned from
:meth:`.SimDeviceSim.getDouble` or :meth:`.SimDevice.createDouble`.
force_no_trampoline: true
methods:
SimDouble:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
Get:
Set:
Reset:
hal::SimEnum:
doc: |
Wrapper around a HAL simulator enum value.
It is not useful to construct these directly -- they are returned from
:meth:`.SimDeviceSim.getEnum` or :meth:`.SimDevice.createEnum`.
force_no_trampoline: true
methods:
SimEnum:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
Get:
Set:
hal::SimBoolean:
doc: |
Wrapper around a HAL simulator boolean value.
It is not useful to construct these directly -- they are returned from
:meth:`.SimDeviceSim.getBoolean` or :meth:`.SimDevice.createBoolean`.
force_no_trampoline: true
methods:
SimBoolean:
overloads:
'':
ignore: true
HAL_SimValueHandle:
param_override:
val:
name: handle
Get:
Set:
hal::SimDevice:
doc: |
Wrapper around a HAL simulation 'device'
This creates a simulated 'device' object that can be interacted with
from user SimDeviceSim objects or via the Simulation GUI.
.. note:: To interact with an existing device use
:class:`hal.simulation.SimDeviceSim` instead.
force_type_casters:
- wpi::SmallVector
enums:
Direction:
methods:
SimDevice:
overloads:
'':
ignore: true
const char*:
const char*, int:
const char*, int, int:
GetName:
CreateValue:
ignore: true
CreateDouble:
CreateEnum:
overloads:
const char*, int32_t, std::initializer_list<const char *>, int32_t:
ignore: true
const char*, int32_t, std::span<const char * const>, int32_t:
cpp_code: |
[](SimDevice &self, const char * name, int32_t direction, const wpi::SmallVector<std::string, 8> &options, int32_t initialValue) {
wpi::SmallVector<const char *, 8> coptions;
coptions.reserve(options.size());
for (auto &s: options) {
coptions.push_back(s.c_str());
}
return self.CreateEnum(name, direction, coptions, initialValue);
}
CreateEnumDouble:
overloads:
const char*, int32_t, std::initializer_list<const char *>, std::initializer_list<double>, int32_t:
ignore: true
const char*, int32_t, std::span<const char * const>, std::span<const double>, int32_t:
cpp_code: |
[](SimDevice &self, const char * name, int32_t direction, const wpi::SmallVector<std::string, 8> &options, const wpi::SmallVector<double, 8> &optionValues, int32_t initialValue) {
wpi::SmallVector<const char *, 8> coptions;
coptions.reserve(options.size());
for (auto &s: options) {
coptions.push_back(s.c_str());
}
return self.CreateEnumDouble(name, direction, coptions, optionValues, initialValue);
}
CreateBoolean:
CreateInt:
CreateLong:
inline_code: |2
cls_SimValue
.def_property_readonly("value", [](const hal::SimValue &self) -> py::object {
HAL_Value value;
{
py::gil_scoped_release release;
value = self.GetValue();
}
switch (value.type) {
case HAL_BOOLEAN:
return py::bool_(value.data.v_boolean);
case HAL_DOUBLE:
return py::float_(value.data.v_double);
case HAL_ENUM:
return py::int_(value.data.v_enum);
case HAL_INT:
return py::int_(value.data.v_int);
case HAL_LONG:
return py::int_(value.data.v_long);
default:
return py::none();
}
})
.def_property_readonly("type", [](const hal::SimValue &self) -> HAL_Type {
py::gil_scoped_release release;
return self.GetValue().type;
})
.def("__bool__", [](const hal::SimValue &self) -> bool {
return (bool)self;
})
.def("__repr__", [](const hal::SimValue &self) -> py::str {
if (!self) {
return "<SimValue (invalid)>";
}
HAL_Value value;
{
py::gil_scoped_release release;
value = self.GetValue();
}
switch (value.type) {
case HAL_BOOLEAN:
if (value.data.v_boolean) {
return "<SimValue (bool) True>";
} else {
return "<SimValue (bool) False>";
}
case HAL_DOUBLE:
return "<SimValue (double) " + std::to_string(value.data.v_double) + ">";
case HAL_ENUM:
return "<SimValue (enum) " + std::to_string(value.data.v_enum) + ">";
case HAL_INT:
return "<SimValue (int) " + std::to_string(value.data.v_int) + ">";
case HAL_LONG:
return "<SimValue (long) " + std::to_string(value.data.v_long) + ">";
default:
return "<SimValue (unknown)>";
}
});
cls_SimBoolean
.def_property("value", &SimBoolean::Get, &SimBoolean::Set, release_gil())
.def("__repr__", [](const SimBoolean &self) -> py::str {
if (self) {
bool value;
{
py::gil_scoped_release release;
value = self.Get();
}
return std::string("<SimBoolean value=") + (value ? "True" : "False") + ">";
} else {
return "<SimBoolean (invalid)>";
}
});
cls_SimDevice
.def("__bool__", [](const hal::SimDevice &self) -> bool {
return (bool)self;
})
.def_property_readonly("name", [](const hal::SimDevice &self) -> py::str {
#ifdef __FRC_SYSTEMCORE__
return "<invalid>";
#else
if (!self) {
return "<invalid>";
} else {
const char *name;
{
py::gil_scoped_release release;
name = HALSIM_GetSimDeviceName(self);
}
return name;
}
#endif
})
.def("__repr__", [](const hal::SimDevice &self) -> py::str {
#ifdef __FRC_SYSTEMCORE__
return "<SimDevice (invalid)>";
#else
if (!self) {
return "<SimDevice (invalid)>";
}
const char *name;
{
py::gil_scoped_release release;
name = HALSIM_GetSimDeviceName(self);
}
return py::str("SimDevice(name={!r})").format(py::str(name));
#endif
});
cls_SimDouble
.def_property("value", &SimDouble::Get, &SimDouble::Set, release_gil())
.def("__repr__", [](const SimDouble &self) -> py::str {
if (self) {
double value;
{
py::gil_scoped_release release;
value = self.Get();
}
return "<SimDouble value=" + std::to_string(value) + ">";
} else {
return "<SimDouble (invalid)>";
}
});
cls_SimEnum
.def_property("value", &SimEnum::Get, &SimEnum::Set)
.def("__repr__", [](const SimEnum &self) -> py::str {
#ifdef __FRC_SYSTEMCORE__
return "<SimEnum (invalid)>";
#else
if (self) {
int32_t value;
int32_t numOptions;
int32_t numdOptions;
const char ** options;
const double * doptions;
const char * option = "<unknown>";
std::string doption;
{
py::gil_scoped_release release;
value = self.Get();
options = HALSIM_GetSimValueEnumOptions(self, &numOptions);
doptions = HALSIM_GetSimValueEnumDoubleValues(self, &numdOptions);
}
if (options && value >= 0 && value < numOptions) {
option = options[value];
}
if (doptions && value >= 0 && value < numdOptions) {
doption = " dvalue=" + std::to_string(doptions[value]);
}
return "<SimEnum name=" + std::string(option) +
" value=" + std::to_string(value) + doption + ">";
} else {
return "<SimEnum (invalid)>";
}
#endif
});
cls_SimInt
.def_property("value", &SimInt::Get, &SimInt::Set)
.def("__repr__", [](const SimInt &self) -> py::str {
if (self) {
int32_t value;
{
py::gil_scoped_release release;
value = self.Get();
}
return "<SimInt value=" + std::to_string(value) + ">";
} else {
return "<SimInt (invalid)>";
}
});
cls_SimLong
.def_property("value", &SimLong::Get, &SimLong::Set)
.def("__repr__", [](const SimLong &self) -> py::str {
if (self) {
int64_t value;
{
py::gil_scoped_release release;
value = self.Get();
}
return "<SimLong value=" + std::to_string(value) + ">";
} else {
return "<SimLong (invalid)>";
}
});

View File

@@ -0,0 +1,12 @@
strip_prefixes:
- HAL_
functions:
HAL_GetThreadPriority:
# no way to get native handle
ignore: true
HAL_GetCurrentThreadPriority:
HAL_SetThreadPriority:
# no way to get native handle
ignore: true
HAL_SetCurrentThreadPriority:

View File

@@ -0,0 +1,10 @@
strip_prefixes:
- HAL_
functions:
HAL_ReportUsage:
overloads:
const struct WPI_String*, const struct WPI_String*:
ignore: true
std::string_view, std::string_view:
std::string_view, int, std::string_view:

View File

@@ -0,0 +1,31 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetAddressableLEDData:
HALSIM_RegisterAddressableLEDInitializedCallback:
ignore: true
HALSIM_CancelAddressableLEDInitializedCallback:
ignore: true
HALSIM_GetAddressableLEDInitialized:
HALSIM_SetAddressableLEDInitialized:
HALSIM_RegisterAddressableLEDStartCallback:
ignore: true
HALSIM_CancelAddressableLEDStartCallback:
ignore: true
HALSIM_GetAddressableLEDStart:
HALSIM_SetAddressableLEDStart:
HALSIM_RegisterAddressableLEDLengthCallback:
ignore: true
HALSIM_CancelAddressableLEDLengthCallback:
ignore: true
HALSIM_GetAddressableLEDLength:
HALSIM_SetAddressableLEDLength:
HALSIM_RegisterAddressableLEDDataCallback:
ignore: true
HALSIM_CancelAddressableLEDDataCallback:
ignore: true
HALSIM_GetAddressableLEDData:
HALSIM_SetAddressableLEDData:
HALSIM_RegisterAddressableLEDAllCallbacks:
ignore: true

View File

@@ -0,0 +1,28 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetAnalogInData:
HALSIM_RegisterAnalogInInitializedCallback:
ignore: true
HALSIM_CancelAnalogInInitializedCallback:
HALSIM_GetAnalogInInitialized:
HALSIM_SetAnalogInInitialized:
HALSIM_GetAnalogInSimDevice:
HALSIM_RegisterAnalogInAverageBitsCallback:
ignore: true
HALSIM_CancelAnalogInAverageBitsCallback:
HALSIM_GetAnalogInAverageBits:
HALSIM_SetAnalogInAverageBits:
HALSIM_RegisterAnalogInOversampleBitsCallback:
ignore: true
HALSIM_CancelAnalogInOversampleBitsCallback:
HALSIM_GetAnalogInOversampleBits:
HALSIM_SetAnalogInOversampleBits:
HALSIM_RegisterAnalogInVoltageCallback:
ignore: true
HALSIM_CancelAnalogInVoltageCallback:
HALSIM_GetAnalogInVoltage:
HALSIM_SetAnalogInVoltage:
HALSIM_RegisterAnalogInAllCallbacks:
ignore: true

View File

@@ -0,0 +1,47 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetCTREPCMData:
HALSIM_RegisterCTREPCMInitializedCallback:
ignore: true
HALSIM_CancelCTREPCMInitializedCallback:
ignore: true
HALSIM_GetCTREPCMInitialized:
HALSIM_SetCTREPCMInitialized:
HALSIM_RegisterCTREPCMSolenoidOutputCallback:
ignore: true
HALSIM_CancelCTREPCMSolenoidOutputCallback:
ignore: true
HALSIM_GetCTREPCMSolenoidOutput:
HALSIM_SetCTREPCMSolenoidOutput:
HALSIM_RegisterCTREPCMCompressorOnCallback:
ignore: true
HALSIM_CancelCTREPCMCompressorOnCallback:
ignore: true
HALSIM_GetCTREPCMCompressorOn:
HALSIM_SetCTREPCMCompressorOn:
HALSIM_RegisterCTREPCMClosedLoopEnabledCallback:
ignore: true
HALSIM_CancelCTREPCMClosedLoopEnabledCallback:
ignore: true
HALSIM_GetCTREPCMClosedLoopEnabled:
HALSIM_SetCTREPCMClosedLoopEnabled:
HALSIM_RegisterCTREPCMPressureSwitchCallback:
ignore: true
HALSIM_CancelCTREPCMPressureSwitchCallback:
ignore: true
HALSIM_GetCTREPCMPressureSwitch:
HALSIM_SetCTREPCMPressureSwitch:
HALSIM_RegisterCTREPCMCompressorCurrentCallback:
ignore: true
HALSIM_CancelCTREPCMCompressorCurrentCallback:
ignore: true
HALSIM_GetCTREPCMCompressorCurrent:
HALSIM_SetCTREPCMCompressorCurrent:
HALSIM_GetCTREPCMAllSolenoids:
HALSIM_SetCTREPCMAllSolenoids:
HALSIM_RegisterCTREPCMAllNonSolenoidCallbacks:
ignore: true
HALSIM_RegisterCTREPCMAllSolenoidCallbacks:
ignore: true

View File

@@ -0,0 +1,33 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetDIOData:
HALSIM_RegisterDIOInitializedCallback:
ignore: true
HALSIM_CancelDIOInitializedCallback:
HALSIM_GetDIOInitialized:
HALSIM_SetDIOInitialized:
HALSIM_GetDIOSimDevice:
HALSIM_RegisterDIOValueCallback:
ignore: true
HALSIM_CancelDIOValueCallback:
HALSIM_GetDIOValue:
HALSIM_SetDIOValue:
HALSIM_RegisterDIOPulseLengthCallback:
ignore: true
HALSIM_CancelDIOPulseLengthCallback:
HALSIM_GetDIOPulseLength:
HALSIM_SetDIOPulseLength:
HALSIM_RegisterDIOIsInputCallback:
ignore: true
HALSIM_CancelDIOIsInputCallback:
HALSIM_GetDIOIsInput:
HALSIM_SetDIOIsInput:
HALSIM_RegisterDIOFilterIndexCallback:
ignore: true
HALSIM_CancelDIOFilterIndexCallback:
HALSIM_GetDIOFilterIndex:
HALSIM_SetDIOFilterIndex:
HALSIM_RegisterDIOAllCallbacks:
ignore: true

View File

@@ -0,0 +1,23 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_FindDigitalPWMForChannel:
HALSIM_ResetDigitalPWMData:
HALSIM_RegisterDigitalPWMInitializedCallback:
ignore: true
HALSIM_CancelDigitalPWMInitializedCallback:
HALSIM_GetDigitalPWMInitialized:
HALSIM_SetDigitalPWMInitialized:
HALSIM_RegisterDigitalPWMDutyCycleCallback:
ignore: true
HALSIM_CancelDigitalPWMDutyCycleCallback:
HALSIM_GetDigitalPWMDutyCycle:
HALSIM_SetDigitalPWMDutyCycle:
HALSIM_RegisterDigitalPWMPinCallback:
ignore: true
HALSIM_CancelDigitalPWMPinCallback:
HALSIM_GetDigitalPWMPin:
HALSIM_SetDigitalPWMPin:
HALSIM_RegisterDigitalPWMAllCallbacks:
ignore: true

View File

@@ -0,0 +1,113 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetDriverStationData:
HALSIM_RegisterDriverStationEnabledCallback:
ignore: true
HALSIM_CancelDriverStationEnabledCallback:
HALSIM_GetDriverStationEnabled:
HALSIM_SetDriverStationEnabled:
HALSIM_RegisterDriverStationAutonomousCallback:
ignore: true
HALSIM_CancelDriverStationAutonomousCallback:
HALSIM_GetDriverStationAutonomous:
HALSIM_SetDriverStationAutonomous:
HALSIM_RegisterDriverStationTestCallback:
ignore: true
HALSIM_CancelDriverStationTestCallback:
HALSIM_GetDriverStationTest:
HALSIM_SetDriverStationTest:
HALSIM_RegisterDriverStationEStopCallback:
ignore: true
HALSIM_CancelDriverStationEStopCallback:
HALSIM_GetDriverStationEStop:
HALSIM_SetDriverStationEStop:
HALSIM_RegisterDriverStationFmsAttachedCallback:
ignore: true
HALSIM_CancelDriverStationFmsAttachedCallback:
HALSIM_GetDriverStationFmsAttached:
HALSIM_SetDriverStationFmsAttached:
HALSIM_RegisterDriverStationDsAttachedCallback:
ignore: true
HALSIM_CancelDriverStationDsAttachedCallback:
HALSIM_GetDriverStationDsAttached:
HALSIM_SetDriverStationDsAttached:
HALSIM_RegisterDriverStationAllianceStationIdCallback:
ignore: true
HALSIM_CancelDriverStationAllianceStationIdCallback:
HALSIM_GetDriverStationAllianceStationId:
HALSIM_SetDriverStationAllianceStationId:
HALSIM_RegisterDriverStationMatchTimeCallback:
ignore: true
HALSIM_CancelDriverStationMatchTimeCallback:
HALSIM_GetDriverStationMatchTime:
HALSIM_SetDriverStationMatchTime:
HALSIM_RegisterJoystickAxesCallback:
ignore: true
HALSIM_CancelJoystickAxesCallback:
HALSIM_GetJoystickAxes:
HALSIM_SetJoystickAxes:
HALSIM_RegisterJoystickPOVsCallback:
ignore: true
HALSIM_CancelJoystickPOVsCallback:
HALSIM_GetJoystickPOVs:
HALSIM_SetJoystickPOVs:
HALSIM_RegisterJoystickButtonsCallback:
ignore: true
HALSIM_CancelJoystickButtonsCallback:
HALSIM_GetJoystickButtons:
HALSIM_SetJoystickButtons:
HALSIM_RegisterJoystickDescriptorCallback:
ignore: true
HALSIM_CancelJoystickDescriptorCallback:
HALSIM_GetJoystickDescriptor:
HALSIM_SetJoystickDescriptor:
HALSIM_RegisterJoystickOutputsCallback:
ignore: true
HALSIM_CancelJoystickOutputsCallback:
HALSIM_GetJoystickOutputs:
HALSIM_SetJoystickOutputs:
HALSIM_RegisterMatchInfoCallback:
ignore: true
HALSIM_CancelMatchInfoCallback:
HALSIM_GetMatchInfo:
HALSIM_SetMatchInfo:
HALSIM_SetJoystickButton:
HALSIM_SetJoystickAxis:
HALSIM_SetJoystickPOV:
HALSIM_SetJoystickButtonsValue:
HALSIM_SetJoystickAxisCount:
HALSIM_SetJoystickPOVCount:
HALSIM_SetJoystickButtonCount:
HALSIM_GetJoystickCounts:
HALSIM_SetJoystickType:
HALSIM_SetJoystickName:
cpp_code: |
[](int32_t stick, std::string_view sv) {
auto s = wpi::make_string(sv);
HALSIM_SetJoystickName(stick, &s);
}
HALSIM_SetJoystickAxisType:
HALSIM_SetGameSpecificMessage:
cpp_code: |
[](std::string_view sv) {
auto s = wpi::make_string(sv);
HALSIM_SetGameSpecificMessage(&s);
}
HALSIM_SetEventName:
cpp_code: |
[](std::string_view sv) {
auto s = wpi::make_string(sv);
HALSIM_SetEventName(&s);
}
HALSIM_SetMatchType:
HALSIM_SetMatchNumber:
HALSIM_SetReplayNumber:
HALSIM_RegisterDriverStationAllCallbacks:
ignore: true
HALSIM_RegisterDriverStationNewDataCallback:
ignore: true
HALSIM_CancelDriverStationNewDataCallback:
HALSIM_NotifyDriverStationNewData:
HALSIM_SetJoystickIsGamepad:

View File

@@ -0,0 +1,23 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetDutyCycleData:
HALSIM_RegisterDutyCycleInitializedCallback:
ignore: true
HALSIM_CancelDutyCycleInitializedCallback:
HALSIM_GetDutyCycleInitialized:
HALSIM_SetDutyCycleInitialized:
HALSIM_GetDutyCycleSimDevice:
HALSIM_RegisterDutyCycleOutputCallback:
ignore: true
HALSIM_CancelDutyCycleOutputCallback:
HALSIM_GetDutyCycleOutput:
HALSIM_SetDutyCycleOutput:
HALSIM_RegisterDutyCycleFrequencyCallback:
ignore: true
HALSIM_CancelDutyCycleFrequencyCallback:
HALSIM_GetDutyCycleFrequency:
HALSIM_SetDutyCycleFrequency:
HALSIM_RegisterDutyCycleAllCallbacks:
ignore: true

View File

@@ -0,0 +1,60 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_FindEncoderForChannel:
HALSIM_ResetEncoderData:
HALSIM_GetEncoderDigitalChannelA:
HALSIM_GetEncoderDigitalChannelB:
HALSIM_RegisterEncoderInitializedCallback:
ignore: true
HALSIM_CancelEncoderInitializedCallback:
HALSIM_GetEncoderInitialized:
HALSIM_SetEncoderInitialized:
HALSIM_GetEncoderSimDevice:
HALSIM_RegisterEncoderCountCallback:
ignore: true
HALSIM_CancelEncoderCountCallback:
HALSIM_GetEncoderCount:
HALSIM_SetEncoderCount:
HALSIM_RegisterEncoderPeriodCallback:
ignore: true
HALSIM_CancelEncoderPeriodCallback:
HALSIM_GetEncoderPeriod:
HALSIM_SetEncoderPeriod:
HALSIM_RegisterEncoderResetCallback:
ignore: true
HALSIM_CancelEncoderResetCallback:
HALSIM_GetEncoderReset:
HALSIM_SetEncoderReset:
HALSIM_RegisterEncoderMaxPeriodCallback:
ignore: true
HALSIM_CancelEncoderMaxPeriodCallback:
HALSIM_GetEncoderMaxPeriod:
HALSIM_SetEncoderMaxPeriod:
HALSIM_RegisterEncoderDirectionCallback:
ignore: true
HALSIM_CancelEncoderDirectionCallback:
HALSIM_GetEncoderDirection:
HALSIM_SetEncoderDirection:
HALSIM_RegisterEncoderReverseDirectionCallback:
ignore: true
HALSIM_CancelEncoderReverseDirectionCallback:
HALSIM_GetEncoderReverseDirection:
HALSIM_SetEncoderReverseDirection:
HALSIM_RegisterEncoderSamplesToAverageCallback:
ignore: true
HALSIM_CancelEncoderSamplesToAverageCallback:
HALSIM_GetEncoderSamplesToAverage:
HALSIM_SetEncoderSamplesToAverage:
HALSIM_RegisterEncoderDistancePerPulseCallback:
ignore: true
HALSIM_CancelEncoderDistancePerPulseCallback:
HALSIM_GetEncoderDistancePerPulse:
HALSIM_SetEncoderDistancePerPulse:
HALSIM_RegisterEncoderAllCallbacks:
ignore: true
HALSIM_SetEncoderDistance:
HALSIM_GetEncoderDistance:
HALSIM_SetEncoderRate:
HALSIM_GetEncoderRate:

View File

@@ -0,0 +1,59 @@
extra_includes:
- sim_cb.h
- pybind11/functional.h
strip_prefixes:
- HALSIM_
functions:
HALSIM_SetRuntimeType:
HALSIM_WaitForProgramStart:
HALSIM_SetProgramStarted:
HALSIM_GetProgramStarted:
HALSIM_RestartTiming:
HALSIM_PauseTiming:
HALSIM_ResumeTiming:
HALSIM_IsTimingPaused:
HALSIM_StepTiming:
HALSIM_StepTimingAsync:
# following functions are ignored for raw function pointers
HALSIM_SetSendError:
ignore: true
HALSIM_SetSendConsoleLine:
ignore: true
HALSIM_RegisterSimPeriodicBeforeCallback:
param_override:
param:
ignore: true
cpp_code: |
[](std::function<void(void)> fn) -> std::unique_ptr<SimCB> {
auto cb = std::make_unique<SimCB>(fn, HALSIM_CancelSimPeriodicBeforeCallback);
auto uid = HALSIM_RegisterSimPeriodicBeforeCallback([](void *param) {
((SimCB*)param)->m_fn();
}, cb.get());
cb->SetUID(uid);
return std::move(cb);
}
HALSIM_CancelSimPeriodicBeforeCallback:
ignore: true
HALSIM_RegisterSimPeriodicAfterCallback:
param_override:
param:
ignore: true
cpp_code: |
[](std::function<void(void)> fn) -> std::unique_ptr<SimCB> {
auto cb = std::make_unique<SimCB>(fn, HALSIM_CancelSimPeriodicAfterCallback);
auto uid = HALSIM_RegisterSimPeriodicAfterCallback([](void *param) {
((SimCB*)param)->m_fn();
}, cb.get());
cb->SetUID(uid);
return std::move(cb);
}
HALSIM_CancelSimPeriodicAfterCallback:
ignore: true
HALSIM_CancelAllSimPeriodicCallbacks:

View File

@@ -0,0 +1,14 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_GetNextNotifierTimeout:
HALSIM_GetNumNotifiers:
HALSIM_GetNotifierInfo:
classes:
HALSIM_NotifierInfo:
attributes:
handle:
name:
timeout:
waitTimeValid:

View File

@@ -0,0 +1,25 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetPWMData:
HALSIM_RegisterPWMInitializedCallback:
ignore: true
HALSIM_CancelPWMInitializedCallback:
HALSIM_GetPWMInitialized:
HALSIM_SetPWMInitialized:
HALSIM_RegisterPWMPulseMicrosecondCallback:
ignore: true
HALSIM_CancelPWMPulseMicrosecondCallback:
ignore: true
HALSIM_GetPWMPulseMicrosecond:
HALSIM_SetPWMPulseMicrosecond:
HALSIM_RegisterPWMAllCallbacks:
ignore: true
HALSIM_GetPWMSimDevice:
HALSIM_RegisterPWMOutputPeriodCallback:
ignore: true
HALSIM_CancelPWMOutputPeriodCallback:
ignore: true
HALSIM_GetPWMOutputPeriod:
HALSIM_SetPWMOutputPeriod:

View File

@@ -0,0 +1,29 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetPowerDistributionData:
HALSIM_RegisterPowerDistributionInitializedCallback:
ignore: true
HALSIM_CancelPowerDistributionInitializedCallback:
HALSIM_GetPowerDistributionInitialized:
HALSIM_SetPowerDistributionInitialized:
HALSIM_RegisterPowerDistributionTemperatureCallback:
ignore: true
HALSIM_CancelPowerDistributionTemperatureCallback:
HALSIM_GetPowerDistributionTemperature:
HALSIM_SetPowerDistributionTemperature:
HALSIM_RegisterPowerDistributionVoltageCallback:
ignore: true
HALSIM_CancelPowerDistributionVoltageCallback:
HALSIM_GetPowerDistributionVoltage:
HALSIM_SetPowerDistributionVoltage:
HALSIM_RegisterPowerDistributionCurrentCallback:
ignore: true
HALSIM_CancelPowerDistributionCurrentCallback:
HALSIM_GetPowerDistributionCurrent:
HALSIM_SetPowerDistributionCurrent:
HALSIM_GetPowerDistributionAllCurrents:
HALSIM_SetPowerDistributionAllCurrents:
HALSIM_RegisterPowerDistributionAllNonCurrentCallbacks:
ignore: true

View File

@@ -0,0 +1,41 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetREVPHData:
HALSIM_RegisterREVPHInitializedCallback:
ignore: true
HALSIM_CancelREVPHInitializedCallback:
HALSIM_GetREVPHInitialized:
HALSIM_SetREVPHInitialized:
HALSIM_RegisterREVPHSolenoidOutputCallback:
ignore: true
HALSIM_CancelREVPHSolenoidOutputCallback:
HALSIM_GetREVPHSolenoidOutput:
HALSIM_SetREVPHSolenoidOutput:
HALSIM_RegisterREVPHCompressorOnCallback:
ignore: true
HALSIM_CancelREVPHCompressorOnCallback:
HALSIM_GetREVPHCompressorOn:
HALSIM_SetREVPHCompressorOn:
HALSIM_RegisterREVPHCompressorConfigTypeCallback:
ignore: true
HALSIM_CancelREVPHCompressorConfigTypeCallback:
HALSIM_GetREVPHCompressorConfigType:
HALSIM_SetREVPHCompressorConfigType:
HALSIM_RegisterREVPHPressureSwitchCallback:
ignore: true
HALSIM_CancelREVPHPressureSwitchCallback:
HALSIM_GetREVPHPressureSwitch:
HALSIM_SetREVPHPressureSwitch:
HALSIM_RegisterREVPHCompressorCurrentCallback:
ignore: true
HALSIM_CancelREVPHCompressorCurrentCallback:
HALSIM_GetREVPHCompressorCurrent:
HALSIM_SetREVPHCompressorCurrent:
HALSIM_GetREVPHAllSolenoids:
HALSIM_SetREVPHAllSolenoids:
HALSIM_RegisterREVPHAllNonSolenoidCallbacks:
ignore: true
HALSIM_RegisterREVPHAllSolenoidCallbacks:
ignore: true

View File

@@ -0,0 +1,5 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetAllSimData:

View File

@@ -0,0 +1,97 @@
strip_prefixes:
- HALSIM_
functions:
HALSIM_ResetRoboRioData:
HALSIM_RegisterRoboRioFPGAButtonCallback:
ignore: true
HALSIM_CancelRoboRioFPGAButtonCallback:
ignore: true
HALSIM_GetRoboRioFPGAButton:
ignore: true
HALSIM_SetRoboRioFPGAButton:
ignore: true
HALSIM_RegisterRoboRioVInVoltageCallback:
ignore: true
HALSIM_CancelRoboRioVInVoltageCallback:
HALSIM_GetRoboRioVInVoltage:
HALSIM_SetRoboRioVInVoltage:
HALSIM_RegisterRoboRioUserVoltage3V3Callback:
ignore: true
HALSIM_CancelRoboRioUserVoltage3V3Callback:
HALSIM_GetRoboRioUserVoltage3V3:
HALSIM_SetRoboRioUserVoltage3V3:
HALSIM_RegisterRoboRioUserCurrent3V3Callback:
ignore: true
HALSIM_CancelRoboRioUserCurrent3V3Callback:
HALSIM_GetRoboRioUserCurrent3V3:
HALSIM_SetRoboRioUserCurrent3V3:
HALSIM_RegisterRoboRioUserActive3V3Callback:
ignore: true
HALSIM_CancelRoboRioUserActive3V3Callback:
HALSIM_GetRoboRioUserActive3V3:
HALSIM_SetRoboRioUserActive3V3:
HALSIM_RegisterRoboRioUserFaults3V3Callback:
ignore: true
HALSIM_CancelRoboRioUserFaults3V3Callback:
HALSIM_GetRoboRioUserFaults3V3:
HALSIM_SetRoboRioUserFaults3V3:
HALSIM_RegisterRoboRioBrownoutVoltageCallback:
ignore: true
HALSIM_CancelRoboRioBrownoutVoltageCallback:
HALSIM_GetRoboRioBrownoutVoltage:
HALSIM_SetRoboRioBrownoutVoltage:
HALSIM_RegisterRoboRioTeamNumberCallback:
ignore: true
HALSIM_CancelRoboRioTeamNumberCallback:
HALSIM_GetRoboRioTeamNumber:
HALSIM_SetRoboRioTeamNumber:
HALSIM_RegisterRoboRioSerialNumberCallback:
ignore: true
HALSIM_CancelRoboRioSerialNumberCallback:
HALSIM_GetRoboRioSerialNumber:
param_override:
serialNumber:
ignore: true
cpp_code: |
[]() {
WPI_String s;
HALSIM_GetRoboRioSerialNumber(&s);
std::string ss(wpi::to_string_view(&s));
WPI_FreeString(&s);
return ss;
}
HALSIM_SetRoboRioSerialNumber:
cpp_code: |
[](std::string_view sv) {
auto s = wpi::make_string(sv);
HALSIM_SetRoboRioSerialNumber(&s);
}
HALSIM_RegisterRoboRioCommentsCallback:
ignore: true
HALSIM_CancelRoboRioCommentsCallback:
HALSIM_GetRoboRioComments:
param_override:
comments:
ignore: true
cpp_code: |
[]() {
WPI_String s;
HALSIM_GetRoboRioComments(&s);
std::string ss(wpi::to_string_view(&s));
WPI_FreeString(&s);
return ss;
}
HALSIM_SetRoboRioComments:
cpp_code: |
[](std::string_view sv) {
auto s = wpi::make_string(sv);
HALSIM_SetRoboRioComments(&s);
}
HALSIM_RegisterRoboRioAllCallbacks:
ignore: true
HALSIM_RegisterRoboRioCPUTempCallback:
ignore: true
HALSIM_CancelRoboRioCPUTempCallback:
HALSIM_GetRoboRioCPUTemp:
HALSIM_SetRoboRioCPUTemp:

View File

@@ -0,0 +1,92 @@
extra_includes:
- sim_value_cb.h
- pybind11/functional.h
strip_prefixes:
- HALSIM_
functions:
HALSIM_SetSimDeviceEnabled:
HALSIM_IsSimDeviceEnabled:
HALSIM_RegisterSimDeviceCreatedCallback:
ignore: true
HALSIM_CancelSimDeviceCreatedCallback:
ignore: true
HALSIM_RegisterSimDeviceFreedCallback:
ignore: true
HALSIM_CancelSimDeviceFreedCallback:
ignore: true
HALSIM_GetSimDeviceHandle:
HALSIM_GetSimDeviceName:
HALSIM_GetSimValueDeviceHandle:
HALSIM_EnumerateSimDevices:
ignore: true
HALSIM_RegisterSimValueCreatedCallback:
param_override:
param:
ignore: true
cpp_code: |
[](hal::SimDevice &simdevice, std::function<void(const char *, HAL_SimValueHandle, HAL_SimValueDirection, HAL_Value)> fn, bool initialNotify) -> std::unique_ptr<SimValueCB> {
auto cb = std::make_unique<SimValueCB>(fn, HALSIM_CancelSimDeviceCreatedCallback);
auto uid = HALSIM_RegisterSimValueCreatedCallback(simdevice, cb.get(),
[](const char* name, void* param,
HAL_SimValueHandle handle,
int32_t direction,
const struct HAL_Value* value) {
((SimValueCB*)param)->m_fn(name, handle, (HAL_SimValueDirection)direction, *value);
}, initialNotify);
cb->SetUID(uid);
return std::move(cb);
}
HALSIM_CancelSimValueCreatedCallback:
ignore: true
HALSIM_RegisterSimValueChangedCallback:
param_override:
handle:
name: value
param:
ignore: true
cpp_code: |
[](hal::SimValue &simvalue, std::function<void(const char *, HAL_SimValueHandle, HAL_SimValueDirection, HAL_Value)> fn, bool initialNotify) -> std::unique_ptr<SimValueCB> {
auto cb = std::make_unique<SimValueCB>(fn, HALSIM_CancelSimValueChangedCallback);
auto uid = HALSIM_RegisterSimValueChangedCallback(simvalue, cb.get(),
[](const char* name, void* param,
HAL_SimValueHandle handle,
int32_t direction,
const struct HAL_Value* value) {
((SimValueCB*)param)->m_fn(name, handle, (HAL_SimValueDirection)direction, *value);
}, initialNotify);
cb->SetUID(uid);
return std::move(cb);
}
HALSIM_CancelSimValueChangedCallback:
ignore: true
HALSIM_RegisterSimValueResetCallback:
param_override:
handle:
name: value
param:
ignore: true
cpp_code: |
[](hal::SimValue &simvalue, std::function<void(const char *, HAL_SimValueHandle, HAL_SimValueDirection, HAL_Value)> fn, bool initialNotify) -> std::unique_ptr<SimValueCB> {
auto cb = std::make_unique<SimValueCB>(fn, HALSIM_CancelSimValueResetCallback);
auto uid = HALSIM_RegisterSimValueChangedCallback(simvalue, cb.get(),
[](const char* name, void* param,
HAL_SimValueHandle handle,
int32_t direction,
const struct HAL_Value* value) {
((SimValueCB*)param)->m_fn(name, handle, (HAL_SimValueDirection)direction, *value);
}, initialNotify);
cb->SetUID(uid);
return std::move(cb);
}
HALSIM_CancelSimValueResetCallback:
ignore: true
HALSIM_GetSimValueHandle:
HALSIM_EnumerateSimValues:
ignore: true
HALSIM_GetSimValueEnumOptions:
ignore: true
HALSIM_GetSimValueEnumDoubleValues:
ignore: true
HALSIM_ResetSimDeviceData:

View File

@@ -0,0 +1,47 @@
import hal
def test_hal_simdevice():
device = hal.SimDevice("deviceName")
v = device.createInt("i", 0, 1)
assert v.get() == 1
assert v.type == hal.Type.INT
v.set(4)
assert v.get() == 4
def test_hal_simdevice_enum():
device = hal.SimDevice("enumDevice")
names = ["one", "two", "three"]
v = device.createEnum("e", 0, names, 0)
assert v.get() == 0
assert v.type == hal.Type.ENUM
for value, name in enumerate(names):
v.set(value)
assert repr(v) == f"<SimEnum name={name} value={value}>"
def test_hal_simdevice_enum_double():
device = hal.SimDevice("enumDevice")
names = ["one", "two", "three"]
values = [0.0, 1.0, 2.0]
v = device.createEnumDouble("e", 0, names, values, 0)
assert v.get() == 0
assert v.type == hal.Type.ENUM
# TODO: update this test to not use repr once https://github.com/wpilibsuite/allwpilib/issues/7800
# is resolved
for value, (name, dvalue) in enumerate(zip(names, values)):
v.set(value)
assert repr(v) == f"<SimEnum name={name} value={value} dvalue={dvalue:.6f}>"
def test_hal_send_error(capsys):
hal._wpiHal.__test_senderr()
cap = capsys.readouterr()
assert cap.err == "Error at location: <20>badmessage\ncallstack\n\n"

View File

@@ -0,0 +1,41 @@
import hal
import hal.simulation
import typing
def test_value_changed_callback():
recv: typing.Optional[typing.Tuple[bool, str, int]] = None
def created_cb(
name: str, handle: int, direction: hal.SimValueDirection, value: hal.Value
):
nonlocal recv
recv = (True, name, value.value)
def cb(name: str, handle: int, direction: hal.SimValueDirection, value: hal.Value):
nonlocal recv
recv = (False, name, value.value)
dev = hal.SimDevice("simd")
# Must keep the returned value alive or the callback will be unregistered
devunused = hal.simulation.registerSimValueCreatedCallback(dev, created_cb, True)
assert recv is None
val = dev.createInt("answer", 0, 42)
assert recv == (True, "answer", 42)
recv = None
# Must keep the returned value alive or the callback will be unregistered
unused = hal.simulation.registerSimValueChangedCallback(val, cb, True)
assert recv == (False, "answer", 42)
recv = None
val.set(84)
assert recv == (False, "answer", 84)
recv = None

View File

@@ -16,6 +16,9 @@ generatedFileExclude {
ntcore/doc/
ntcore/src/generated
.*\.jinja
src/main/python/
src/test/python/
}
repoRootNameOverride {

View File

@@ -0,0 +1,4 @@
pyntcore
========
Python pybind11 wrappers around the C++ ntcore library.

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
import sphinxify
from cxxheaderparser.simple import parse_string
from cxxheaderparser.tokfmt import tokfmt
if __name__ == "__main__":
with open("ntcore/include/ntcore_cpp.h") as fp:
data = parse_string(fp.read())
for c in data.namespace.namespaces["nt"].classes:
if c.class_decl.typename.format() == "struct PubSubOptions":
params = []
docs = []
for f in c.fields:
if f.static or f.name == "structSize":
continue
if f.type.format() == "NT_Publisher":
params.append(
(
"std::optional<std::shared_ptr<nt::Publisher>>",
f.name,
f"{f.name}.has_value() ? {f.name}.value()->GetHandle() : {f.value.format()}",
"std::nullopt",
)
)
else:
v = f.value.format()
if v == "kDefaultPeriodic":
v = f"nt::PubSubOptions::{v}"
params.append((f.type, f.name, f.name, v))
if f.doxygen:
docs.append(f"@param {f.name} {f.doxygen}")
paramstr = ",\n ".join(f"{t.format()} {n}" for t, n, _, _ in params)
args = ",\n ".join(f'py::arg("{n}") = {v}' for _, n, _, v in params)
options = ",\n ".join(f".{fn} = {n}" for _, fn, n, _ in params)
doc = "\n ".join(
sphinxify.process_raw("\n".join(docs)).splitlines()
)
print(
f"""
// autogenerated by gen-pubsub.py
.def(py::init([](
{paramstr}
) -> nt::PubSubOptions {{
return nt::PubSubOptions{{
{options}
}};
}}),
py::kw_only(),
{args},
R"(
{doc}
)"
)
"""
)

View File

@@ -0,0 +1,43 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"hatchling",
"hatch-nativelib~=0.2.0",
"hatch-robotpy~=0.2.1",
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-wpinet==2027.0.0a2",
"robotpy-native-datalog==2027.0.0a2",
]
[project]
name = "robotpy-native-ntcore"
version = "2027.0.0a2"
description = "WPILib NetworkTables Library"
license = "BSD-3-Clause"
dependencies = [
"robotpy-native-wpiutil==2027.0.0a2",
"robotpy-native-wpinet==2027.0.0a2",
"robotpy-native-datalog==2027.0.0a2",
]
[tool.hatch.build.targets.wheel]
packages = ["src/native"]
[[tool.hatch.build.hooks.robotpy.maven_lib_download]]
artifact_id = "ntcore-cpp"
group_id = "edu.wpi.first.ntcore"
repo_url = "https://frcmaven.wpi.edu/artifactory/release-2027"
version = "2027.0.0-alpha-2"
extract_to = "src/native/ntcore"
libs = ["ntcore"]
[[tool.hatch.build.hooks.nativelib.pcfile]]
pcfile = "src/native/ntcore/robotpy-native-ntcore.pc"
name = "ntcore"
includedir = "src/native/ntcore/include"
libdir = "src/native/ntcore/lib"
shared_libraries = ["ntcore"]
requires = ["robotpy-native-datalog", "robotpy-native-wpinet", "robotpy-native-wpiutil"]

View File

@@ -0,0 +1,195 @@
from . import _init__ntcore
# autogenerated by 'semiwrap create-imports ntcore ntcore._ntcore'
from ._ntcore import (
BooleanArrayEntry,
BooleanArrayPublisher,
BooleanArraySubscriber,
BooleanArrayTopic,
BooleanEntry,
BooleanPublisher,
BooleanSubscriber,
BooleanTopic,
ConnectionInfo,
DoubleArrayEntry,
DoubleArrayPublisher,
DoubleArraySubscriber,
DoubleArrayTopic,
DoubleEntry,
DoublePublisher,
DoubleSubscriber,
DoubleTopic,
Event,
EventFlags,
FloatArrayEntry,
FloatArrayPublisher,
FloatArraySubscriber,
FloatArrayTopic,
FloatEntry,
FloatPublisher,
FloatSubscriber,
FloatTopic,
GenericEntry,
GenericPublisher,
GenericSubscriber,
IntegerArrayEntry,
IntegerArrayPublisher,
IntegerArraySubscriber,
IntegerArrayTopic,
IntegerEntry,
IntegerPublisher,
IntegerSubscriber,
IntegerTopic,
LogMessage,
MultiSubscriber,
NTSendable,
NTSendableBuilder,
NetworkTable,
NetworkTableEntry,
NetworkTableInstance,
NetworkTableListener,
NetworkTableListenerPoller,
NetworkTableType,
PubSubOptions,
Publisher,
RawEntry,
RawPublisher,
RawSubscriber,
RawTopic,
StringArrayEntry,
StringArrayPublisher,
StringArraySubscriber,
StringArrayTopic,
StringEntry,
StringPublisher,
StringSubscriber,
StringTopic,
StructArrayEntry,
StructArrayPublisher,
StructArraySubscriber,
StructArrayTopic,
StructEntry,
StructPublisher,
StructSubscriber,
StructTopic,
Subscriber,
TimeSyncEventData,
TimestampedBoolean,
TimestampedBooleanArray,
TimestampedDouble,
TimestampedDoubleArray,
TimestampedFloat,
TimestampedFloatArray,
TimestampedInteger,
TimestampedIntegerArray,
TimestampedRaw,
TimestampedString,
TimestampedStringArray,
TimestampedStruct,
TimestampedStructArray,
Topic,
TopicInfo,
Value,
ValueEventData,
)
__all__ = [
"BooleanArrayEntry",
"BooleanArrayPublisher",
"BooleanArraySubscriber",
"BooleanArrayTopic",
"BooleanEntry",
"BooleanPublisher",
"BooleanSubscriber",
"BooleanTopic",
"ConnectionInfo",
"DoubleArrayEntry",
"DoubleArrayPublisher",
"DoubleArraySubscriber",
"DoubleArrayTopic",
"DoubleEntry",
"DoublePublisher",
"DoubleSubscriber",
"DoubleTopic",
"Event",
"EventFlags",
"FloatArrayEntry",
"FloatArrayPublisher",
"FloatArraySubscriber",
"FloatArrayTopic",
"FloatEntry",
"FloatPublisher",
"FloatSubscriber",
"FloatTopic",
"GenericEntry",
"GenericPublisher",
"GenericSubscriber",
"IntegerArrayEntry",
"IntegerArrayPublisher",
"IntegerArraySubscriber",
"IntegerArrayTopic",
"IntegerEntry",
"IntegerPublisher",
"IntegerSubscriber",
"IntegerTopic",
"LogMessage",
"MultiSubscriber",
"NTSendable",
"NTSendableBuilder",
"NetworkTable",
"NetworkTableEntry",
"NetworkTableInstance",
"NetworkTableListener",
"NetworkTableListenerPoller",
"NetworkTableType",
"PubSubOptions",
"Publisher",
"RawEntry",
"RawPublisher",
"RawSubscriber",
"RawTopic",
"StringArrayEntry",
"StringArrayPublisher",
"StringArraySubscriber",
"StringArrayTopic",
"StringEntry",
"StringPublisher",
"StringSubscriber",
"StringTopic",
"StructArrayEntry",
"StructArrayPublisher",
"StructArraySubscriber",
"StructArrayTopic",
"StructEntry",
"StructPublisher",
"StructSubscriber",
"StructTopic",
"Subscriber",
"TimeSyncEventData",
"TimestampedBoolean",
"TimestampedBooleanArray",
"TimestampedDouble",
"TimestampedDoubleArray",
"TimestampedFloat",
"TimestampedFloatArray",
"TimestampedInteger",
"TimestampedIntegerArray",
"TimestampedRaw",
"TimestampedString",
"TimestampedStringArray",
"TimestampedStruct",
"TimestampedStructArray",
"Topic",
"TopicInfo",
"Value",
"ValueEventData",
]
from ._ntcore import _now, _setNow
__all__ += ["_now", "_setNow"]
try:
from .version import version as __version__
except ImportError:
__version__ = "master"

View File

@@ -0,0 +1,123 @@
import atexit
import logging
import threading
from . import _ntcore
import wpiutil.sync
class InstanceAlreadyStartedError(Exception):
pass
class NtLogForwarder:
"""
Forwards ntcore's logger to python's logging system
"""
_instlock = threading.Lock()
_instances = {}
_instcfg = {}
@classmethod
def config_logging(
cls,
instance: _ntcore.NetworkTableInstance,
minLevel: _ntcore.NetworkTableInstance.LogLevel,
maxLevel: _ntcore.NetworkTableInstance.LogLevel,
logName: str,
):
handle = instance._getHandle()
with cls._instlock:
if handle in cls._instances:
raise InstanceAlreadyStartedError(
"cannot configure logging after instance has been started"
)
cls._instcfg[handle] = (minLevel, maxLevel, logName)
@classmethod
def onInstanceStart(cls, instance: _ntcore.NetworkTableInstance):
handle = instance._getHandle()
with cls._instlock:
if handle in cls._instances:
return
default_cfg = (
_ntcore.NetworkTableInstance.LogLevel.kLogInfo,
_ntcore.NetworkTableInstance.LogLevel.kLogCritical,
"nt",
)
minLevel, maxLevel, logName = cls._instcfg.get(handle, default_cfg)
cls._instances[handle] = cls(instance, logName, minLevel, maxLevel)
@classmethod
def onInstanceDestroy(cls, instance: _ntcore.NetworkTableInstance):
handle = instance._getHandle()
with cls._instlock:
lfwd = cls._instances.pop(handle, None)
if lfwd:
lfwd.destroy()
def __init__(
self,
instance: _ntcore.NetworkTableInstance,
logName: str,
minLevel: _ntcore.NetworkTableInstance.LogLevel,
maxLevel: _ntcore.NetworkTableInstance.LogLevel,
):
self.lock = threading.Lock()
self.poller = _ntcore.NetworkTableListenerPoller(instance)
ntLogger = self.poller.addLogger(minLevel, maxLevel)
self.thread = threading.Thread(
target=self._logging_thread,
name=logName + "-log-thread",
daemon=True,
args=(self.poller, logName, ntLogger),
)
self.thread.start()
atexit.register(self.destroy)
def _logging_thread(
self, poller: _ntcore.NetworkTableListenerPoller, logName: str, ntLogger: int
):
logger = logging.getLogger(logName)
_waitForObject = wpiutil.sync.waitForObject
handle = poller.getHandle()
while True:
if not _waitForObject(handle):
break
messages = poller.readQueue()
if not messages:
continue
for msg in messages:
msg = msg.data
if logger.isEnabledFor(msg.level):
lr = logger.makeRecord(
logName,
msg.level,
msg.filename,
msg.line,
"%s",
(msg.message,),
None,
)
logger.handle(lr)
def destroy(self):
with self.lock:
if self.poller:
self.poller.close()
self.thread.join(timeout=1)
self.poller = None
_config_logging = NtLogForwarder.config_logging

View File

@@ -0,0 +1,28 @@
# autogenerated by 'semiwrap create-imports ntcore.meta ntcore._ntcore.meta'
from .._ntcore.meta import (
Client,
ClientPublisher,
ClientSubscriber,
SubscriberOptions,
TopicPublisher,
TopicSubscriber,
decodeClientPublishers,
decodeClientSubscribers,
decodeClients,
decodeTopicPublishers,
decodeTopicSubscribers,
)
__all__ = [
"Client",
"ClientPublisher",
"ClientSubscriber",
"SubscriberOptions",
"TopicPublisher",
"TopicSubscriber",
"decodeClientPublishers",
"decodeClientSubscribers",
"decodeClients",
"decodeTopicPublishers",
"decodeTopicSubscribers",
]

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