sbhs_robomaster.data
1from enum import Enum, IntFlag, auto 2from dataclasses import dataclass 3from typing import TypeVar 4 5 6class Frequency(Enum): 7 """""" 8 Off = "0" 9 Hz1 = "1" 10 Hz5 = "5" 11 Hz10 = "10" 12 Hz20 = "20" 13 Hz30 = "30" 14 Hz50 = "50" 15 16 17class Mode(Enum): 18 """""" 19 ChassisLead = "chassis_lead" 20 GimbalLead = "gimbal_lead" 21 Free = "free" 22 23 24class GripperStatus(Enum): 25 """""" 26 Closed = "0" 27 PartiallyOpen = "1" 28 Open = "2" 29 30 31class LineType(Enum): 32 """""" 33 NoLine = "0" 34 Straight = "1" 35 Fork = "2" 36 Intersection = "3" 37 38 39class LineColour(Enum): 40 """""" 41 Red = "red" 42 Blue = "blue" 43 Green = "green" 44 45 46class LedPosition(IntFlag): 47 """ 48 Use the flag combining operator (`|`) to combine multiple leds. 49 50 ```py 51 front_and_left_leds = LedPosition.Front | LedPosition.Left 52 ``` 53 54 `LedPosition.All` is equivalent to `LedPosition.Front | LedPosition.Back | LedPosition.Left | LedPosition.Right`. 55 It's just a lot faster to type. 56 """ 57 Front = auto() 58 Back = auto() 59 Left = auto() 60 Right = auto() 61 All = Front | Back | Left | Right 62 63 64class LedEffect(Enum): 65 """""" 66 Off = "off" 67 Solid = "solid" 68 Pulse = "pulse" 69 Blink = "blink" 70 Scrolling = "scrolling" 71 72 73@dataclass 74class Response: 75 """ 76 Wrapper around the data returned by the robot. 77 78 Provides convenience functions for getting the data in the correct type. 79 """ 80 data: list[str] 81 82 def get_str(self, index: int) -> str: 83 return self.data[index] 84 85 def get_int(self, index: int) -> int: 86 return int(self.data[index]) 87 88 def get_float(self, index: int) -> float: 89 return float(self.data[index]) 90 91 def get_bool(self, index: int) -> bool: 92 if self.data[index] == "on": 93 return True 94 elif self.data[index] == "off": 95 return False 96 elif self.data[index] == "1": 97 return True 98 elif self.data[index] == "0": 99 return False 100 else: 101 raise Exception("Invalid bool value") 102 103 GetEnumT = TypeVar("GetEnumT", bound=Enum) 104 def get_enum(self, index: int, enum: type[GetEnumT]) -> GetEnumT: 105 """ 106 Example usage: 107 ```py 108 class MyEnum(Enum): 109 A = "a" 110 B = "b" 111 C = "c" 112 113 response = Response(["a", "b", "c"]) 114 115 response.get_enum(0, MyEnum) # MyEnum.A 116 response.get_enum(1, MyEnum) # MyEnum.B 117 response.get_enum(2, MyEnum) # MyEnum.C 118 ``` 119 120 **NOTE:** This only works for enums that have strings as their underlying values. 121 """ 122 return enum(self.data[index]) 123 124 125@dataclass 126class WheelSpeed: 127 """All speeds are in rpm.""" 128 129 front_right: float 130 front_left: float 131 back_right: float 132 back_left: float 133 134 135@dataclass 136class ChassisSpeed: 137 z: float 138 """ 139 Movement forwards/backwards (relative to the rotation of the robot) in m/s. 140 """ 141 142 x: float 143 """ 144 Movement right/left (relative to the rotation of the robot) in m/s. 145 """ 146 147 clockwise: float 148 """ 149 Rotational speed around the vertical axis in the clockwise direction in degrees/s. 150 """ 151 152 wheels: WheelSpeed 153 154 @staticmethod 155 def parse(data: Response) -> "ChassisSpeed": 156 return ChassisSpeed( 157 z = data.get_float(0), 158 x = data.get_float(1), 159 clockwise = data.get_float(2), 160 wheels = WheelSpeed( 161 front_right = data.get_float(3), 162 front_left = data.get_float(4), 163 back_right = data.get_float(5), 164 back_left = data.get_float(6) 165 ) 166 ) 167 168 169@dataclass 170class ChassisRotation: 171 """ 172 This actually parses the position data from the robot, 173 but removes the x and z coordinates due to them being 174 too inaccurate and being a major footgun. 175 """ 176 177 clockwise: float 178 """ 179 The rotation in degrees clockwise around the vertical axis, 180 relative to the robot's starting orientation. 181 """ 182 183 @staticmethod 184 def parse(data: Response) -> "ChassisRotation": 185 return ChassisRotation( 186 clockwise = data.get_float(2) 187 ) 188 189 190@dataclass 191class ChassisAttitude: 192 """All values are in degrees.""" 193 194 pitch: float 195 roll: float 196 yaw: float 197 198 @staticmethod 199 def parse(data: Response) -> "ChassisAttitude": 200 return ChassisAttitude( 201 pitch = data.get_float(0), 202 roll = data.get_float(1), 203 yaw = data.get_float(2) 204 ) 205 206 207@dataclass 208class ChassisStatus: 209 static: bool 210 up_hill: bool 211 down_hill: bool 212 on_slope: bool 213 pick_up: bool 214 slip: bool 215 impact_x: bool 216 impact_y: bool 217 impact_z: bool 218 roll_over: bool 219 hill_static: bool 220 221 @staticmethod 222 def parse(data: Response) -> "ChassisStatus": 223 return ChassisStatus( 224 static = data.get_bool(0), 225 up_hill = data.get_bool(1), 226 down_hill = data.get_bool(2), 227 on_slope = data.get_bool(3), 228 pick_up = data.get_bool(4), 229 slip = data.get_bool(5), 230 impact_x = data.get_bool(6), 231 impact_y = data.get_bool(7), 232 impact_z = data.get_bool(8), 233 roll_over = data.get_bool(9), 234 hill_static = data.get_bool(10) 235 ) 236 237 238@dataclass 239class Point: 240 x: float 241 y: float 242 tangent: float 243 curvature: float 244 245 246@dataclass 247class Line: 248 type: LineType 249 points: list[Point] 250 251 @staticmethod 252 def parse(data: Response) -> "Line": 253 point_count = (len(data.data) - 1) // 4 254 255 match data.get_int(0): 256 case 0: 257 line_type = LineType.NoLine 258 case 1: 259 line_type = LineType.Straight 260 case 2: 261 line_type = LineType.Fork 262 case 3: 263 line_type = LineType.Intersection 264 case _: 265 raise Exception("Invalid line type") 266 267 points: list[Point] = [] 268 269 for i in range(point_count): 270 points.append(Point( 271 x = data.get_float(i * 4 + 1), 272 y = data.get_float(i * 4 + 2), 273 tangent = data.get_float(i * 4 + 3), 274 curvature = data.get_float(i * 4 + 4) 275 )) 276 277 return Line(line_type, points) 278 279 280@dataclass 281class Colour: 282 """All values are from 0 to 255, inclusive.""" 283 284 r: float 285 g: float 286 b: float
class
Frequency(enum.Enum):
7class Frequency(Enum): 8 """""" 9 Off = "0" 10 Hz1 = "1" 11 Hz5 = "5" 12 Hz10 = "10" 13 Hz20 = "20" 14 Hz30 = "30" 15 Hz50 = "50"
Off =
<Frequency.Off: '0'>
Hz1 =
<Frequency.Hz1: '1'>
Hz5 =
<Frequency.Hz5: '5'>
Hz10 =
<Frequency.Hz10: '10'>
Hz20 =
<Frequency.Hz20: '20'>
Hz30 =
<Frequency.Hz30: '30'>
Hz50 =
<Frequency.Hz50: '50'>
Inherited Members
- enum.Enum
- name
- value
class
Mode(enum.Enum):
18class Mode(Enum): 19 """""" 20 ChassisLead = "chassis_lead" 21 GimbalLead = "gimbal_lead" 22 Free = "free"
ChassisLead =
<Mode.ChassisLead: 'chassis_lead'>
GimbalLead =
<Mode.GimbalLead: 'gimbal_lead'>
Free =
<Mode.Free: 'free'>
Inherited Members
- enum.Enum
- name
- value
class
GripperStatus(enum.Enum):
Closed =
<GripperStatus.Closed: '0'>
PartiallyOpen =
<GripperStatus.PartiallyOpen: '1'>
Open =
<GripperStatus.Open: '2'>
Inherited Members
- enum.Enum
- name
- value
class
LineType(enum.Enum):
32class LineType(Enum): 33 """""" 34 NoLine = "0" 35 Straight = "1" 36 Fork = "2" 37 Intersection = "3"
NoLine =
<LineType.NoLine: '0'>
Straight =
<LineType.Straight: '1'>
Fork =
<LineType.Fork: '2'>
Intersection =
<LineType.Intersection: '3'>
Inherited Members
- enum.Enum
- name
- value
class
LineColour(enum.Enum):
Red =
<LineColour.Red: 'red'>
Blue =
<LineColour.Blue: 'blue'>
Green =
<LineColour.Green: 'green'>
Inherited Members
- enum.Enum
- name
- value
class
LedPosition(enum.IntFlag):
47class LedPosition(IntFlag): 48 """ 49 Use the flag combining operator (`|`) to combine multiple leds. 50 51 ```py 52 front_and_left_leds = LedPosition.Front | LedPosition.Left 53 ``` 54 55 `LedPosition.All` is equivalent to `LedPosition.Front | LedPosition.Back | LedPosition.Left | LedPosition.Right`. 56 It's just a lot faster to type. 57 """ 58 Front = auto() 59 Back = auto() 60 Left = auto() 61 Right = auto() 62 All = Front | Back | Left | Right
Use the flag combining operator (|) to combine multiple leds.
front_and_left_leds = LedPosition.Front | LedPosition.Left
LedPosition.All is equivalent to LedPosition.Front | LedPosition.Back | LedPosition.Left | LedPosition.Right.
It's just a lot faster to type.
Front =
<LedPosition.Front: 1>
Back =
<LedPosition.Back: 2>
Left =
<LedPosition.Left: 4>
Right =
<LedPosition.Right: 8>
All =
<LedPosition.All: 15>
Inherited Members
- builtins.int
- conjugate
- bit_length
- bit_count
- to_bytes
- from_bytes
- as_integer_ratio
- real
- imag
- numerator
- denominator
- enum.Enum
- name
- value
class
LedEffect(enum.Enum):
65class LedEffect(Enum): 66 """""" 67 Off = "off" 68 Solid = "solid" 69 Pulse = "pulse" 70 Blink = "blink" 71 Scrolling = "scrolling"
Off =
<LedEffect.Off: 'off'>
Solid =
<LedEffect.Solid: 'solid'>
Pulse =
<LedEffect.Pulse: 'pulse'>
Blink =
<LedEffect.Blink: 'blink'>
Scrolling =
<LedEffect.Scrolling: 'scrolling'>
Inherited Members
- enum.Enum
- name
- value
@dataclass
class
Response:
74@dataclass 75class Response: 76 """ 77 Wrapper around the data returned by the robot. 78 79 Provides convenience functions for getting the data in the correct type. 80 """ 81 data: list[str] 82 83 def get_str(self, index: int) -> str: 84 return self.data[index] 85 86 def get_int(self, index: int) -> int: 87 return int(self.data[index]) 88 89 def get_float(self, index: int) -> float: 90 return float(self.data[index]) 91 92 def get_bool(self, index: int) -> bool: 93 if self.data[index] == "on": 94 return True 95 elif self.data[index] == "off": 96 return False 97 elif self.data[index] == "1": 98 return True 99 elif self.data[index] == "0": 100 return False 101 else: 102 raise Exception("Invalid bool value") 103 104 GetEnumT = TypeVar("GetEnumT", bound=Enum) 105 def get_enum(self, index: int, enum: type[GetEnumT]) -> GetEnumT: 106 """ 107 Example usage: 108 ```py 109 class MyEnum(Enum): 110 A = "a" 111 B = "b" 112 C = "c" 113 114 response = Response(["a", "b", "c"]) 115 116 response.get_enum(0, MyEnum) # MyEnum.A 117 response.get_enum(1, MyEnum) # MyEnum.B 118 response.get_enum(2, MyEnum) # MyEnum.C 119 ``` 120 121 **NOTE:** This only works for enums that have strings as their underlying values. 122 """ 123 return enum(self.data[index])
Wrapper around the data returned by the robot.
Provides convenience functions for getting the data in the correct type.
def
get_enum(self, index: int, enum: type[~GetEnumT]) -> ~GetEnumT:
105 def get_enum(self, index: int, enum: type[GetEnumT]) -> GetEnumT: 106 """ 107 Example usage: 108 ```py 109 class MyEnum(Enum): 110 A = "a" 111 B = "b" 112 C = "c" 113 114 response = Response(["a", "b", "c"]) 115 116 response.get_enum(0, MyEnum) # MyEnum.A 117 response.get_enum(1, MyEnum) # MyEnum.B 118 response.get_enum(2, MyEnum) # MyEnum.C 119 ``` 120 121 **NOTE:** This only works for enums that have strings as their underlying values. 122 """ 123 return enum(self.data[index])
Example usage:
class MyEnum(Enum):
A = "a"
B = "b"
C = "c"
response = Response(["a", "b", "c"])
response.get_enum(0, MyEnum) # MyEnum.A
response.get_enum(1, MyEnum) # MyEnum.B
response.get_enum(2, MyEnum) # MyEnum.C
NOTE: This only works for enums that have strings as their underlying values.
@dataclass
class
WheelSpeed:
126@dataclass 127class WheelSpeed: 128 """All speeds are in rpm.""" 129 130 front_right: float 131 front_left: float 132 back_right: float 133 back_left: float
All speeds are in rpm.
@dataclass
class
ChassisSpeed:
136@dataclass 137class ChassisSpeed: 138 z: float 139 """ 140 Movement forwards/backwards (relative to the rotation of the robot) in m/s. 141 """ 142 143 x: float 144 """ 145 Movement right/left (relative to the rotation of the robot) in m/s. 146 """ 147 148 clockwise: float 149 """ 150 Rotational speed around the vertical axis in the clockwise direction in degrees/s. 151 """ 152 153 wheels: WheelSpeed 154 155 @staticmethod 156 def parse(data: Response) -> "ChassisSpeed": 157 return ChassisSpeed( 158 z = data.get_float(0), 159 x = data.get_float(1), 160 clockwise = data.get_float(2), 161 wheels = WheelSpeed( 162 front_right = data.get_float(3), 163 front_left = data.get_float(4), 164 back_right = data.get_float(5), 165 back_left = data.get_float(6) 166 ) 167 )
ChassisSpeed( z: float, x: float, clockwise: float, wheels: WheelSpeed)
wheels: WheelSpeed
155 @staticmethod 156 def parse(data: Response) -> "ChassisSpeed": 157 return ChassisSpeed( 158 z = data.get_float(0), 159 x = data.get_float(1), 160 clockwise = data.get_float(2), 161 wheels = WheelSpeed( 162 front_right = data.get_float(3), 163 front_left = data.get_float(4), 164 back_right = data.get_float(5), 165 back_left = data.get_float(6) 166 ) 167 )
@dataclass
class
ChassisRotation:
170@dataclass 171class ChassisRotation: 172 """ 173 This actually parses the position data from the robot, 174 but removes the x and z coordinates due to them being 175 too inaccurate and being a major footgun. 176 """ 177 178 clockwise: float 179 """ 180 The rotation in degrees clockwise around the vertical axis, 181 relative to the robot's starting orientation. 182 """ 183 184 @staticmethod 185 def parse(data: Response) -> "ChassisRotation": 186 return ChassisRotation( 187 clockwise = data.get_float(2) 188 )
This actually parses the position data from the robot, but removes the x and z coordinates due to them being too inaccurate and being a major footgun.
@dataclass
class
ChassisAttitude:
191@dataclass 192class ChassisAttitude: 193 """All values are in degrees.""" 194 195 pitch: float 196 roll: float 197 yaw: float 198 199 @staticmethod 200 def parse(data: Response) -> "ChassisAttitude": 201 return ChassisAttitude( 202 pitch = data.get_float(0), 203 roll = data.get_float(1), 204 yaw = data.get_float(2) 205 )
All values are in degrees.
@dataclass
class
ChassisStatus:
208@dataclass 209class ChassisStatus: 210 static: bool 211 up_hill: bool 212 down_hill: bool 213 on_slope: bool 214 pick_up: bool 215 slip: bool 216 impact_x: bool 217 impact_y: bool 218 impact_z: bool 219 roll_over: bool 220 hill_static: bool 221 222 @staticmethod 223 def parse(data: Response) -> "ChassisStatus": 224 return ChassisStatus( 225 static = data.get_bool(0), 226 up_hill = data.get_bool(1), 227 down_hill = data.get_bool(2), 228 on_slope = data.get_bool(3), 229 pick_up = data.get_bool(4), 230 slip = data.get_bool(5), 231 impact_x = data.get_bool(6), 232 impact_y = data.get_bool(7), 233 impact_z = data.get_bool(8), 234 roll_over = data.get_bool(9), 235 hill_static = data.get_bool(10) 236 )
ChassisStatus( static: bool, up_hill: bool, down_hill: bool, on_slope: bool, pick_up: bool, slip: bool, impact_x: bool, impact_y: bool, impact_z: bool, roll_over: bool, hill_static: bool)
222 @staticmethod 223 def parse(data: Response) -> "ChassisStatus": 224 return ChassisStatus( 225 static = data.get_bool(0), 226 up_hill = data.get_bool(1), 227 down_hill = data.get_bool(2), 228 on_slope = data.get_bool(3), 229 pick_up = data.get_bool(4), 230 slip = data.get_bool(5), 231 impact_x = data.get_bool(6), 232 impact_y = data.get_bool(7), 233 impact_z = data.get_bool(8), 234 roll_over = data.get_bool(9), 235 hill_static = data.get_bool(10) 236 )
@dataclass
class
Point:
@dataclass
class
Line:
247@dataclass 248class Line: 249 type: LineType 250 points: list[Point] 251 252 @staticmethod 253 def parse(data: Response) -> "Line": 254 point_count = (len(data.data) - 1) // 4 255 256 match data.get_int(0): 257 case 0: 258 line_type = LineType.NoLine 259 case 1: 260 line_type = LineType.Straight 261 case 2: 262 line_type = LineType.Fork 263 case 3: 264 line_type = LineType.Intersection 265 case _: 266 raise Exception("Invalid line type") 267 268 points: list[Point] = [] 269 270 for i in range(point_count): 271 points.append(Point( 272 x = data.get_float(i * 4 + 1), 273 y = data.get_float(i * 4 + 2), 274 tangent = data.get_float(i * 4 + 3), 275 curvature = data.get_float(i * 4 + 4) 276 )) 277 278 return Line(line_type, points)
type: LineType
points: list[Point]
252 @staticmethod 253 def parse(data: Response) -> "Line": 254 point_count = (len(data.data) - 1) // 4 255 256 match data.get_int(0): 257 case 0: 258 line_type = LineType.NoLine 259 case 1: 260 line_type = LineType.Straight 261 case 2: 262 line_type = LineType.Fork 263 case 3: 264 line_type = LineType.Intersection 265 case _: 266 raise Exception("Invalid line type") 267 268 points: list[Point] = [] 269 270 for i in range(point_count): 271 points.append(Point( 272 x = data.get_float(i * 4 + 1), 273 y = data.get_float(i * 4 + 2), 274 tangent = data.get_float(i * 4 + 3), 275 curvature = data.get_float(i * 4 + 4) 276 )) 277 278 return Line(line_type, points)
@dataclass
class
Colour:
281@dataclass 282class Colour: 283 """All values are from 0 to 255, inclusive.""" 284 285 r: float 286 g: float 287 b: float
All values are from 0 to 255, inclusive.