Skip to content

Commit 69cb422

Browse files
committed
Use enumerations for motor constants
This avoids using int everywhere. Using enumerations allows type checking. Also add Brick.get_motor() to create a Motor instance.
1 parent 4a2fc11 commit 69cb422

9 files changed

Lines changed: 317 additions & 253 deletions

File tree

docs/api/brick.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Brick
3838

3939
This part is still a work in progress.
4040

41+
.. automethod:: Brick.get_motor
4142
.. automethod:: Brick.get_sensor
4243

4344
Programs

docs/migration.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,33 @@ use this code before calling any NXT-Python function::
4545
The :mod:`!nxt` module no longer exports name from sub-modules. In general,
4646
NXT-Python now avoids to have two names for the same object.
4747

48+
Output port constants are replaced by enumerations, using the :mod:`enum`
49+
module:
50+
51+
.. py:currentmodule:: nxt.motor
52+
53+
=============================== ============================
54+
NXT-Python 2 NXT-Python 3
55+
=============================== ============================
56+
:data:`!PORT_A` :attr:`Port.A`
57+
:data:`!PORT_B` :attr:`Port.B`
58+
:data:`!PORT_C` :attr:`Port.C`
59+
:data:`!MODE_IDLE` :attr:`Mode.IDLE`
60+
:data:`!MODE_MOTOR_ON` :attr:`Mode.ON`
61+
:data:`!MODE_BRAKE` :attr:`Mode.BRAKE`
62+
:data:`!MODE_REGULATED` :attr:`Mode.REGULATED`
63+
:data:`!REGULATION_IDLE` :attr:`RegulationMode.IDLE`
64+
:data:`!REGULATION_MOTOR_SPEED` :attr:`RegulationMode.SPEED`
65+
:data:`!REGULATION_MOTOR_SYNC` :attr:`RegulationMode.SYNC`
66+
:data:`!RUN_STATE_IDLE` :attr:`RunState.IDLE`
67+
:data:`!RUN_STATE_RAMP_UP` :attr:`RunState.RAMP_UP`
68+
:data:`!RUN_STATE_RUNNING` :attr:`RunState.RUNNING`
69+
:data:`!RUN_STATE_RAMP_DOWN` :attr:`RunState.RAMP_DOWN`
70+
=============================== ============================
71+
72+
You can now create :class:`nxt.motor.Motor` objects using
73+
:meth:`nxt.brick.Brick.get_motor`, however direct creation still works.
74+
4875

4976
Text String or Binary String
5077
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

nxt/brick.py

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import time
2020

2121
import nxt.error
22+
import nxt.motor
2223
import nxt.sensor
2324
from nxt.telegram import Opcode, Telegram
2425

@@ -272,6 +273,15 @@ def find_modules(self, pattern="*.*"):
272273

273274
get_sensor = nxt.sensor.get_sensor
274275

276+
def get_motor(self, port):
277+
"""Return a motor object connected to one of the brick output port.
278+
279+
:param nxt.motor.Port port: Output port identifier.
280+
:return: The motor object.
281+
:rtype: nxt.motor.Motor
282+
"""
283+
return nxt.motor.Motor(self, port)
284+
275285
def _cmd(self, tgram):
276286
"""Send a message to the NXT brick and read reply.
277287
@@ -332,27 +342,30 @@ def play_tone(self, frequency_hz, duration_ms):
332342
self._cmd(tgram)
333343

334344
def set_output_state(
335-
self, port, power, mode, regulation, turn_ratio, run_state, tacho_limit
345+
self, port, power, mode, regulation_mode, turn_ratio, run_state, tacho_limit
336346
):
337347
"""Set output port state on the brick.
338348
339-
:param int port: Output port constant.
349+
:param nxt.motor.Port port: Output port identifier.
340350
:param int power: Motor speed or power level (-100 to 100).
341-
:param int mode: Motor power mode.
342-
:param int regulation: Motor regulation mode.
351+
:param nxt.motor.Mode mode: Motor power mode.
352+
:param nxt.motor.RegulationMode regulation_mode: Motor regulation mode.
343353
:param int turn_ratio: Turn ratio (-100 to 100). Negative value shift power to
344354
the left motor.
345-
:param int run_state: Motor run state.
355+
:param nxt.motor.RunState run_state: Motor run state.
346356
:param int tacho_limit: Number of degrees the motor should rotate relative to
347357
the current position.
358+
359+
.. warning:: This is a low level function, prefer to use
360+
:meth:`nxt.motor.Motor`, you can get one from :meth:`get_motor`.
348361
"""
349362
tgram = Telegram(Opcode.DIRECT_SET_OUT_STATE, reply_req=False)
350-
tgram.add_u8(port)
363+
tgram.add_u8(port.value)
351364
tgram.add_s8(power)
352-
tgram.add_u8(mode)
353-
tgram.add_u8(regulation)
365+
tgram.add_u8(mode.value)
366+
tgram.add_u8(regulation_mode.value)
354367
tgram.add_s8(turn_ratio)
355-
tgram.add_u8(run_state)
368+
tgram.add_u8(run_state.value)
356369
tgram.add_u32(tacho_limit)
357370
self._cmd(tgram)
358371

@@ -372,18 +385,19 @@ def set_input_mode(self, port, sensor_type, sensor_mode):
372385
def get_output_state(self, port):
373386
"""Get output port state from the brick.
374387
375-
:param int port: Output port constant.
376-
:return: A tuple with `port`, `power`, `mode`, `regulation`, `turn_ratio`,
388+
:param nxt.motor.Port port: Output port identifier.
389+
:return: A tuple with `port`, `power`, `mode`, `regulation_mode`, `turn_ratio`,
377390
`run_state`, `tacho_limit`, `tacho_count`, `block_tacho_count`, and
378391
`rotation_count`.
379-
:rtype: (int, int, int, int, int, int, int, int, int, int)
392+
:rtype: (nxt.motor.Port, int, nxt.motor.Mode, nxt.motor.RegulationMode, int,
393+
nxt.motor.RunState, int, int, int, int)
380394
381395
Return value details:
382396
383-
- **port** Output port constant.
397+
- **port** Output port identifier.
384398
- **power** Motor speed or power level (-100 to 100).
385399
- **mode** Motor power mode.
386-
- **regulation** Motor regulation mode.
400+
- **regulation_mode** Motor regulation mode.
387401
- **turn_ratio** Turn ratio (-100 to 100). Negative value shift power to the
388402
left motor.
389403
- **run_state** Motor run state.
@@ -392,16 +406,19 @@ def get_output_state(self, port):
392406
"block" start.
393407
- **rotation_count** Number of degrees the motor rotated relative to the program
394408
start.
409+
410+
.. warning:: This is a low level function, prefer to use
411+
:meth:`nxt.motor.Motor`, you can get one from :meth:`get_motor`.
395412
"""
396413
tgram = Telegram(Opcode.DIRECT_GET_OUT_STATE)
397-
tgram.add_u8(port)
414+
tgram.add_u8(port.value)
398415
tgram = self._cmd(tgram)
399-
port = tgram.parse_u8()
416+
port = nxt.motor.Port(tgram.parse_u8())
400417
power = tgram.parse_s8()
401-
mode = tgram.parse_u8()
402-
regulation = tgram.parse_u8()
418+
mode = nxt.motor.Mode(tgram.parse_u8())
419+
regulation_mode = nxt.motor.RegulationMode(tgram.parse_u8())
403420
turn_ratio = tgram.parse_s8()
404-
run_state = tgram.parse_u8()
421+
run_state = nxt.motor.RunState(tgram.parse_u8())
405422
tacho_limit = tgram.parse_u32()
406423
tacho_count = tgram.parse_s32()
407424
block_tacho_count = tgram.parse_s32()
@@ -410,7 +427,7 @@ def get_output_state(self, port):
410427
port,
411428
power,
412429
mode,
413-
regulation,
430+
regulation_mode,
414431
turn_ratio,
415432
run_state,
416433
tacho_limit,
@@ -494,12 +511,15 @@ def message_write(self, inbox, message):
494511
def reset_motor_position(self, port, relative):
495512
"""Reset block or program motor position for a brick output port.
496513
497-
:param int port: Output port constant.
514+
:param nxt.motor.Port port: Output port identifier.
498515
:param bool relative: If ``True``, reset block position, if ``False``, reset
499516
program position.
517+
518+
.. warning:: This is a low level function, prefer to use
519+
:meth:`nxt.motor.Motor`, you can get one from :meth:`get_motor`.
500520
"""
501521
tgram = Telegram(Opcode.DIRECT_RESET_POSITION)
502-
tgram.add_u8(port)
522+
tgram.add_u8(port.value)
503523
tgram.add_bool(relative)
504524
self._cmd(tgram)
505525

nxt/motcont.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ def _decode_ports(self, ports, max_ports):
8989
except TypeError:
9090
ports = frozenset((ports,))
9191
mapping = {
92-
frozenset((nxt.motor.PORT_A,)): "0",
93-
frozenset((nxt.motor.PORT_B,)): "1",
94-
frozenset((nxt.motor.PORT_C,)): "2",
95-
frozenset((nxt.motor.PORT_A, nxt.motor.PORT_B)): "3",
96-
frozenset((nxt.motor.PORT_A, nxt.motor.PORT_C)): "4",
97-
frozenset((nxt.motor.PORT_B, nxt.motor.PORT_C)): "5",
98-
frozenset((nxt.motor.PORT_A, nxt.motor.PORT_B, nxt.motor.PORT_C)): "6",
92+
frozenset((nxt.motor.Port.A,)): "0",
93+
frozenset((nxt.motor.Port.B,)): "1",
94+
frozenset((nxt.motor.Port.C,)): "2",
95+
frozenset((nxt.motor.Port.A, nxt.motor.Port.B)): "3",
96+
frozenset((nxt.motor.Port.A, nxt.motor.Port.C)): "4",
97+
frozenset((nxt.motor.Port.B, nxt.motor.Port.C)): "5",
98+
frozenset((nxt.motor.Port.A, nxt.motor.Port.B, nxt.motor.Port.C)): "6",
9999
}
100100
if ports not in mapping or len(ports) > max_ports:
101101
raise ValueError("invalid combination of ports")
@@ -106,9 +106,9 @@ def cmd(
106106
):
107107
"""Send a CONTROLLED_MOTORCMD to MotorControl.
108108
109-
:param ports: Port or ports to control, use one of the port constant of
110-
:mod:`nxt.motor`, or a tuple with one or two of them.
111-
:type ports: int or Iterable[int]
109+
:param ports: Port or ports to control, use one of the port identifiers, or
110+
an iterable returning one or two of them.
111+
:type ports: nxt.motor.Port or Iterable[nxt.motor.Port]
112112
:param int power: Speed or power, -100 to 100.
113113
:param int tacholimit: Position to drive to, 1 to 999999, or 0 for unlimited.
114114
:param bool speedreg: ``True`` to enable regulation.
@@ -126,9 +126,9 @@ def cmd(
126126
def reset_tacho(self, ports):
127127
"""Reset NXT tacho count.
128128
129-
:param ports: Port or ports to control, use one of the port constant of
130-
:mod:`nxt.motor`, or a tuple with one to three of them.
131-
:type ports: int or Iterable[int]
129+
:param ports: Port or ports to control, use one of the port identifiers, or
130+
an iterable returning one to three of them.
131+
:type ports: nxt.motor.Port or Iterable[nxt.motor.Port]
132132
"""
133133
self._interval_is_ready()
134134
ports, strports = self._decode_ports(ports, 3)
@@ -139,9 +139,9 @@ def reset_tacho(self, ports):
139139
def is_ready(self, port):
140140
"""Determine the state of a single motor.
141141
142-
:param port: Port to control, use one of the port constant of :mod:`nxt.motor`.
143-
or a tuple with one of them.
144-
:type port: int or Iterable[int]
142+
:param port: Port to control, use one of the port identifiers, or an iterable
143+
returning one of them.
144+
:type port: nxt.motor.Port or Iterable[nxt.motor.Port]
145145
:return: ``True`` if the motor is ready to accept new commands.
146146
:rtype: bool
147147
"""
@@ -160,9 +160,9 @@ def is_ready(self, port):
160160
def set_output_state(self, ports, power, tacholimit, speedreg=True):
161161
"""Send a CLASSIC_MOTORCMD to MotorControl.
162162
163-
:param ports: Port or ports to control, use one of the port constant of
164-
:mod:`nxt.motor`, or a tuple with one or two of them.
165-
:type ports: int or Iterable[int]
163+
:param ports: Port or ports to control, use one of the port identifiers, or
164+
an iterable returning one or two of them.
165+
:type ports: nxt.motor.Port or Iterable[nxt.motor.Port]
166166
:param int power: Speed or power, -100 to 100.
167167
:param int tacholimit: Position to drive to, 1 to 999999, or 0 for unlimited.
168168
:param bool speedreg: ``True`` to enable regulation.

0 commit comments

Comments
 (0)