async def read(self): input = _pi3hat_router.Input() input.force_can_check = 0x3f input.max_rx = 1 output = await self._cycle(input) return None if not output.rx_can else output.rx_can[0]
async def write(self, command): input = _pi3hat_router.Input() input.tx_can = [self._make_single_can(command)] input.max_rx = 0 await self._cycle(input) return []
async def read(self): '''Read at most one message from any BUS.''' input = _pi3hat_router.Input() input.force_can_check = 0x3f input.max_rx = 1 output = await self._cycle(input) return None if not output.rx_can else output.rx_can[0]
async def attitude(self): '''Return the current IMU value The return object will have the following fields: - attitude: a Quaternion with w, x, y, z fields - rate_dps: a Point3D with x, y, z fields - accel_mps2: a Point3D with x, y, z fields - euler_rad: a Euler with roll, pitch, yaw fields (redundant with attitude) ''' input = _pi3hat_router.Input() input.request_attitude = True output = await self._cycle(input) return output.attitude if output.attitude_present else None
async def cycle(self, commands): input = _pi3hat_router.Input() input.tx_can = [self._make_single_can(command) for command in commands] output = await self._cycle(input) result = [] for single_rx in output.rx_can: maybe_command = [ x for x in commands if x.destination == (single_rx.arbitration_id) >> 8 ] if maybe_command: command = maybe_command[0] result.append(command.parse(single_rx)) return result
async def cycle(self, commands, force_can_check=0, max_rx=-1, timeout_ns=1000000, min_tx_wait_ns=1000000, rx_extra_wait_ns=40000, request_attitude=False): '''Operate one CAN cycle of the pi3hat :param commands: A list of moteus.Command structures :param force_can_check: A bitmask list CAN channels which should be listened to, even if no commands on that bus were marked as expecting a reply. :param max_rx: The maximum number of receive packets to return, the default -1, means return as many as possible. :param timeout_ns: If specified, require waiting at least this long for replies. :param min_tx_wait_ns: If specified, change the amount of time waited after the last transmit on a given bus if replies are expected. :param rx_extra_wait_ns: After a successful receipt, wait this much longer for more replies. :param request_attitude: If True, then the attitude will be queried in the same cycle, and returned as a message with id=-1/bus=-1 and the type moteus_pi3hat.CanAttitudeWrapper. ''' input = _pi3hat_router.Input() input.tx_can = [self._make_single_can(command) for command in commands] input.force_can_check = force_can_check input.max_rx = max_rx input.timeout_ns = timeout_ns input.min_tx_wait_ns = min_tx_wait_ns input.rx_extra_wait_ns = rx_extra_wait_ns input.request_attitude = request_attitude output = await self._cycle(input) result = [] for single_rx in output.rx_can: # For commands that were raw, we can't associate them with # a response. They will just get returned as a python-can # style class instead of a parsed structure. def match_id(cmd, aid): if (hasattr(cmd, 'can_prefix') and ((aid >> 16) & 0x1fff) != cmd.can_prefix): return False return cmd.destination == (aid >> 8) & 0xff maybe_command = [ x for x in commands if (not getattr(x, 'raw', False) and match_id(x, single_rx.arbitration_id)) ] if maybe_command: command = maybe_command[0] result.append(command.parse(single_rx)) else: # We didn't associate this with a command, so just # return it raw. result.append(single_rx) if output.attitude_present: # For now, we return this as a "pseudo-can" message, with # a negative ID. result.append(CanAttitudeWrapper(output.attitude)) return result