Skip to content

Commit f022130

Browse files
committed
do stuff
1 parent 5457db9 commit f022130

File tree

12 files changed

+249
-74
lines changed

12 files changed

+249
-74
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Minimal wpimath stub for Sphinx docs build
2+
from . import geometry
3+
from . import units
4+
5+
__all__ = ["geometry", "units"]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Stub module to match wpimath compiled module names
2+
# This file exists so imports like `wpimath._init__wpimath` succeed during docs build.
3+
4+
# no-op
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Minimal geometry stubs for Sphinx documentation
2+
3+
class Rotation3d:
4+
def __init__(self, roll=0.0, pitch=0.0, yaw=0.0):
5+
# store yaw as the primary rotation for simple stubs
6+
self.roll = roll
7+
self.pitch = pitch
8+
self.yaw = yaw
9+
10+
def toRotation2d(self):
11+
# convert yaw to a Rotation2d for simple compatibility in docs build
12+
return Rotation2d(self.yaw)
13+
14+
class Translation3d:
15+
def __init__(self, x=0.0, y=0.0, z=0.0):
16+
# Support both (x, y, z) and (distance, Rotation3d) forms used by the real wpimath
17+
# If y is a Rotation3d, compute a point at 'distance' along its yaw/pitch
18+
try:
19+
from math import cos, sin
20+
except Exception:
21+
def cos(x):
22+
return x
23+
def sin(x):
24+
return x
25+
26+
if hasattr(y, "yaw") and hasattr(y, "pitch"):
27+
# interpret constructor as Translation3d(distance, Rotation3d)
28+
distance = float(x)
29+
pitch = float(getattr(y, "pitch", 0.0))
30+
yaw = float(getattr(y, "yaw", 0.0))
31+
# approximate spherical -> cartesian
32+
self._x = distance * cos(pitch) * cos(yaw)
33+
self._y = distance * cos(pitch) * sin(yaw)
34+
self._z = distance * sin(pitch)
35+
else:
36+
self._x = float(x)
37+
self._y = float(y)
38+
self._z = float(z)
39+
40+
def X(self):
41+
return self._x
42+
43+
def Y(self):
44+
return self._y
45+
46+
def Z(self):
47+
return self._z
48+
49+
class Pose3d:
50+
def __init__(self, *args, **kwargs):
51+
pass
52+
53+
class Rotation2d:
54+
def __init__(self, *args):
55+
# Accept several initialization forms used in the real wpimath Rotation2d
56+
# - Rotation2d(angle)
57+
# - Rotation2d(fx, xOffset) used by SimCameraProperties.getPixelYaw
58+
if len(args) == 0:
59+
self._angle = 0.0
60+
elif len(args) == 1:
61+
self._angle = float(args[0])
62+
else:
63+
# fallback: when called with fx, xOffset, approximate angle as 0.0
64+
self._angle = 0.0
65+
66+
def degrees(self):
67+
from math import degrees
68+
69+
return degrees(self._angle)
70+
71+
def radians(self):
72+
return float(self._angle)
73+
74+
def __add__(self, other):
75+
# allow Rotation2d + Rotation2d or Rotation2d + numeric
76+
if hasattr(other, "_angle"):
77+
return Rotation2d(self._angle + float(other._angle))
78+
try:
79+
return Rotation2d(self._angle + float(other))
80+
except Exception:
81+
return NotImplemented
82+
83+
def __radd__(self, other):
84+
# numeric + Rotation2d
85+
return self.__add__(other)
86+
87+
def __sub__(self, other):
88+
if hasattr(other, "_angle"):
89+
return Rotation2d(self._angle - float(other._angle))
90+
try:
91+
return Rotation2d(self._angle - float(other))
92+
except Exception:
93+
return NotImplemented
94+
95+
def __neg__(self):
96+
return Rotation2d(-self._angle)
97+
98+
def __repr__(self):
99+
return f"Rotation2d({self._angle})"
100+
101+
class Translation2d:
102+
def __init__(self, x=0.0, y=0.0):
103+
self._x = float(x)
104+
self._y = float(y)
105+
106+
def X(self):
107+
return self._x
108+
109+
def Y(self):
110+
return self._y
111+
112+
class Pose2d:
113+
def __init__(self, *args, **kwargs):
114+
pass
115+
116+
def __repr__(self) -> str:
117+
return "Pose2d()"
118+
119+
120+
class Transform3d:
121+
def __init__(self, *args, **kwargs):
122+
pass
123+
124+
125+
class Quaternion:
126+
def __init__(self, *args, **kwargs):
127+
pass
128+
129+
# Expose names commonly used by photonlibpy
130+
__all__ = ["Rotation3d", "Translation3d", "Pose3d", "Rotation2d", "Translation2d", "Pose2d"]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Minimal interpolation stub for docs
2+
class TimeInterpolatableRotation2dBuffer:
3+
def __init__(self, *args, **kwargs):
4+
pass
5+
6+
def addSample(self, *args, **kwargs):
7+
pass
8+
9+
def sample(self, *args, **kwargs):
10+
return None
11+
12+
__all__ = ["TimeInterpolatableRotation2dBuffer"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from ._interpolation import *
2+
3+
__all__ = ["TimeInterpolatableRotation2dBuffer"]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Minimal interpolation submodule stub for docs
2+
class TimeInterpolatableRotation2dBuffer:
3+
def __init__(self, *args, **kwargs):
4+
pass
5+
6+
def addSample(self, *args, **kwargs):
7+
pass
8+
9+
def sample(self, *args, **kwargs):
10+
return None
11+
12+
13+
class TimeInterpolatablePose3dBuffer:
14+
def __init__(self, *args, **kwargs):
15+
# buffer of Pose3d-like objects for docs import
16+
pass
17+
18+
def addSample(self, *args, **kwargs):
19+
pass
20+
21+
def sample(self, *args, **kwargs):
22+
return None
23+
24+
25+
__all__ = ["TimeInterpolatableRotation2dBuffer", "TimeInterpolatablePose3dBuffer"]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Minimal wpimath.units stub for documentation builds."""
2+
3+
def degreesToRadians(deg: float) -> float:
4+
from math import pi
5+
6+
return deg * (pi / 180.0)
7+
8+
9+
# Represent seconds as a float alias for annotations
10+
seconds = float
11+
12+
__all__ = ["degreesToRadians", "seconds"]
13+
14+
# Common unit aliases used in type annotations in WPILib stubs
15+
meters = float
16+
meters_per_second = float
17+
meters_per_second_squared = float
18+
kilograms = float
19+
kilogram_square_meters = float
20+
21+
__all__.extend([
22+
"meters",
23+
"meters_per_second",
24+
"meters_per_second_squared",
25+
"kilograms",
26+
"kilogram_square_meters",
27+
"hertz",
28+
])
29+
30+
# frequency
31+
hertz = float

photon-lib/py/docs/source/conf.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,20 @@
2828
import os
2929
import sys
3030

31+
sys.path.insert(
32+
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "_stubs"))
33+
) # add docs stubs first so they shadow unavailable third-party packages
34+
3135
sys.path.insert(
3236
0, os.path.abspath("../../photonlibpy")
3337
) # adjust based on your project layout
34-
print(sys.path)
38+
# Mock imports that aren't available in the docs build environment so autodoc
39+
# can import the local modules even if optional runtime deps (like wpimath)
40+
# aren't installed. Add other names here if you see warnings for missing
41+
# third-party packages during the build.
42+
autodoc_mock_imports = [
43+
"wpilib",
44+
]
3545
templates_path = ["_templates"]
3646
exclude_patterns = []
3747

photon-lib/py/docs/source/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
contain the root `toctree` directive.
55
66
PhotonLib Python Documentation
7-
==========================
7+
===============================
88

99

1010
The main documentation for PhotonVision can be found at `photonvision.org <https://photonvision.org>`_.
@@ -14,4 +14,4 @@ The main documentation for PhotonVision can be found at `photonvision.org <https
1414
:caption: Contents:
1515

1616
modules
17-
photonlibpy # if you have these .rst files from sphinx-apidoc
17+
photonlibpy

photon-lib/py/photonlibpy/packet.py

Lines changed: 12 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,11 @@ def _getNextByteAsInt(self) -> int:
7070
return retVal
7171

7272
def getData(self) -> bytes:
73-
"""
74-
* Returns the packet data.
75-
*
76-
* @return The packet data.
77-
"""
73+
"""Return the packet data."""
7874
return self.packetData
7975

8076
def setData(self, data: bytes):
81-
"""
82-
* Sets the packet data.
83-
*
84-
* @param data The packet data.
85-
"""
77+
"""Set the packet data."""
8678
self.clear()
8779
self.packetData = data
8880
self.size = len(self.packetData)
@@ -101,86 +93,50 @@ def _decodeGeneric(self, unpackFormat, numBytes):
10193
return value
10294

10395
def decode8(self) -> int:
104-
"""
105-
* Returns a single decoded byte from the packet.
106-
*
107-
* @return A decoded byte from the packet.
108-
"""
96+
"""Return a single decoded byte from the packet."""
10997
return self._decodeGeneric("<b", 1)
11098

11199
def decode16(self) -> int:
112-
"""
113-
* Returns a single decoded short from the packet.
114-
*
115-
* @return A decoded short from the packet.
116-
"""
100+
"""Return a single decoded short from the packet."""
117101
return self._decodeGeneric("<h", 2)
118102

119103
def decodeInt(self) -> int:
120-
"""
121-
* Returns a decoded int (32 bytes) from the packet.
122-
*
123-
* @return A decoded int from the packet.
124-
"""
104+
"""Return a decoded 32-bit integer from the packet."""
125105
return self._decodeGeneric("<l", 4)
126106

127107
def decodeFloat(self) -> float:
128-
"""
129-
* Returns a decoded float from the packet.
130-
*
131-
* @return A decoded float from the packet.
132-
"""
108+
"""Return a decoded float from the packet."""
133109
return self._decodeGeneric("<f", 4)
134110

135111
def decodeLong(self) -> int:
136-
"""
137-
* Returns a decoded int64 from the packet.
138-
*
139-
* @return A decoded int64 from the packet.
140-
"""
112+
"""Return a decoded 64-bit integer from the packet."""
141113
return self._decodeGeneric("<q", 8)
142114

143115
def decodeDouble(self) -> float:
144-
"""
145-
* Returns a decoded double from the packet.
146-
*
147-
* @return A decoded double from the packet.
148-
"""
116+
"""Return a decoded double from the packet."""
149117
return self._decodeGeneric("<d", 8)
150118

151119
def decodeBoolean(self) -> bool:
152-
"""
153-
* Returns a decoded boolean from the packet.
154-
*
155-
* @return A decoded boolean from the packet.
156-
"""
120+
"""Return a decoded boolean from the packet."""
157121
return self.decode8() == 1
158122

159123
def decodeDoubleArray(self, length: int) -> list[float]:
160-
"""
161-
* Returns a decoded array of floats from the packet.
162-
"""
124+
"""Return a decoded list of doubles of the given length from the packet."""
163125
ret = []
164126
for _ in range(length):
165127
ret.append(self.decodeDouble())
166128
return ret
167129

168130
def decodeShortList(self) -> list[int]:
169-
"""
170-
* Returns a decoded array of shorts from the packet.
171-
"""
131+
"""Return a decoded list of shorts from the packet (length-prefixed)."""
172132
length = self.decode8()
173133
ret = []
174134
for _ in range(length):
175135
ret.append(self.decode16())
176136
return ret
177137

178138
def decodeTransform(self) -> Transform3d:
179-
"""
180-
* Returns a decoded Transform3d
181-
*
182-
* @return A decoded Tansform3d from the packet.
183-
"""
139+
"""Return a decoded Transform3d from the packet."""
184140
x = self.decodeDouble()
185141
y = self.decodeDouble()
186142
z = self.decodeDouble()

0 commit comments

Comments
 (0)