Skip to content

Commit 49a89e8

Browse files
Merge pull request #62 from poppy-project/aristofor-dev/shell
Add a reset_factory instruction and a console script for setting motor to poppy config.
2 parents 372bc35 + ce403ca commit 49a89e8

File tree

7 files changed

+185
-3
lines changed

7 files changed

+185
-3
lines changed

pypot/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '2.3.1'
1+
__version__ = '2.4.0'

pypot/dynamixel/io/io.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
from .abstract_io import AbstractDxlIO, _DxlControl, _DxlAccess
1+
from .abstract_io import (AbstractDxlIO, _DxlControl,
2+
_DxlAccess, DxlTimeoutError)
23
from ..protocol import v1 as v1
34
from ..conversion import *
45

56

67
class DxlIO(AbstractDxlIO):
78
_protocol = v1
89

10+
def factory_reset(self):
11+
""" Reset all motors on the bus to their factory default settings. """
12+
try:
13+
self._send_packet(self._protocol.DxlResetPacket())
14+
15+
except DxlTimeoutError:
16+
pass
17+
918
# MARK: - Generate the accessors
1019

1120

pypot/dynamixel/io/io_320.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from .abstract_io import AbstractDxlIO, _DxlControl, _DxlAccess
1+
from .abstract_io import (AbstractDxlIO, _DxlControl,
2+
_DxlAccess, DxlTimeoutError)
23
from .. import conversion as conv
34
from ..protocol import v2 as v2
45

@@ -20,6 +21,18 @@ def set_goal_position_speed_load(self, value_for_ids):
2021

2122
self.set_torque_limit(dict(zip(value_for_ids.keys(), values[2])))
2223

24+
def factory_reset(self, ids, except_ids=False, except_baudrate_and_ids=False):
25+
""" Reset all motors on the bus to their factory default settings. """
26+
27+
mode = (0x02 if except_baudrate_and_ids else
28+
0x01 if except_ids else 0xFF)
29+
30+
for id in ids:
31+
try:
32+
self._send_packet(self._protocol.DxlResetPacket(id, mode))
33+
34+
except DxlTimeoutError:
35+
pass
2336

2437
# TODO:
2538
# * error

pypot/dynamixel/protocol/v1.py

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class DxlInstruction(object):
1414
PING = 0x01
1515
READ_DATA = 0x02
1616
WRITE_DATA = 0x03
17+
RESET = 0x06
1718
SYNC_WRITE = 0x83
1819
SYNC_READ = 0x84
1920

@@ -81,6 +82,13 @@ def __repr__(self):
8182
return 'DxlPingPacket(id={})'.format(self.id)
8283

8384

85+
class DxlResetPacket(DxlInstructionPacket):
86+
""" This class is used to represent reset packet. """
87+
def __new__(cls):
88+
return DxlInstructionPacket.__new__(cls, DxlBroadcast,
89+
DxlInstruction.RESET, ())
90+
91+
8492
class DxlReadDataPacket(DxlInstructionPacket):
8593
""" This class is used to represent read data packet (to read value). """
8694
def __new__(cls, id, address, length):

pypot/dynamixel/protocol/v2.py

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class DxlInstruction(object):
1414
PING = 0x01
1515
READ_DATA = 0x02
1616
WRITE_DATA = 0x03
17+
RESET = 0x06
1718
SYNC_READ = 0x82
1819
SYNC_WRITE = 0x83
1920

@@ -84,6 +85,13 @@ def __repr__(self):
8485
return 'DxlPingPacket(id={})'.format(self.id)
8586

8687

88+
class DxlResetPacket(DxlInstructionPacket):
89+
""" This class is used to represent factory reset packet. """
90+
def __new__(cls, id, mode):
91+
return DxlInstructionPacket.__new__(cls, id,
92+
DxlInstruction.RESET, (mode, ))
93+
94+
8795
class DxlReadDataPacket(DxlInstructionPacket):
8896
""" This class is used to represent read data packet (to read value). """
8997
def __new__(cls, id, address, length):

pypot/tools/dxl_reset.py

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
"""
5+
Reset a dynamixel motor to "poppy" configuration.
6+
7+
This utility should only be used with a single motor connected to the bus. For the moment it's only working with robotis protocol v1 (AX, RX, MX motors).
8+
9+
To run it:
10+
$ poppy-reset-motor 42
11+
12+
The motor will now have the id 42, use a 1000000 baud rates, a 0µs return delay time. The angle limit are also set (by default to (-150, 150)). Its position is also set to its base position (default: 0).
13+
14+
For more complex use cases, see:
15+
$ poppy-reset-motor --help
16+
17+
"""
18+
19+
import logging
20+
import time
21+
import sys
22+
23+
from argparse import ArgumentParser
24+
25+
from pypot.dynamixel import DxlIO, get_available_ports
26+
from pypot.dynamixel.io import DxlError
27+
28+
29+
logging.basicConfig(level=logging.ERROR)
30+
logger = logging.getLogger(__name__)
31+
32+
FACTORY_BAUDRATE = 57600
33+
TARGET_BAUDRATE = 1000000
34+
35+
36+
def leave(msg):
37+
print('{} Exiting now...'.format(msg))
38+
sys.exit(1)
39+
40+
def almost_equal(a, b):
41+
return abs(a - b) < 5.
42+
43+
44+
def main():
45+
parser = ArgumentParser(description='Set a dynamixel motor to'
46+
' a "poppy-like" configuration. '
47+
'Only one motor should be connected!')
48+
49+
parser.add_argument(dest='id', type=int,
50+
help='Dynamixel target #id.')
51+
52+
parser.add_argument('-p', '--port', default=None,
53+
choices=get_available_ports(),
54+
help='Serial port, default: autoselect')
55+
56+
parser.add_argument('--log-level', default='ERROR',
57+
help='Log level : CRITICAL, ERROR, WARNING, INFO, DEBUG')
58+
59+
parser.add_argument('--position', type=float, default=0.0,
60+
help='Position set to the motor (in degrees)')
61+
62+
parser.add_argument('--angle-limit', type=float, nargs=2, default=[-150, 150],
63+
help='Angle limits of the motor (in degrees)')
64+
65+
args = parser.parse_args()
66+
67+
if not (1 <= args.id <= 253):
68+
leave('Motor id should be in range [1:253]!')
69+
70+
log_level = args.log_level.upper()
71+
logger.setLevel(log_level)
72+
73+
# First, we make sure that there is at least one available ports
74+
try:
75+
port = get_available_ports()[0]
76+
except IndexError:
77+
leave('You need to connect at least one dynamixel port!')
78+
79+
print('Resetting to factory settings...')
80+
for br in [FACTORY_BAUDRATE, TARGET_BAUDRATE]:
81+
with DxlIO(port, br) as dxl:
82+
dxl.factory_reset()
83+
time.sleep(.5)
84+
print('Done!')
85+
86+
print('Setting the motor to a "poppy" configuration')
87+
with DxlIO(port, FACTORY_BAUDRATE) as dxl:
88+
# We make sure that there was only one motor on the bus
89+
try:
90+
assert dxl.scan([1]) == [1]
91+
except AssertionError:
92+
leave('No motor found, check the connection!')
93+
except DxlError:
94+
leave('You should only connect one motor at'
95+
' a time when doing factory reset!')
96+
97+
if args.id != 1:
98+
print('Changing the id to {}...'.format(args.id))
99+
dxl.change_id({1: args.id})
100+
101+
print('Changing the return delay time to {}...'.format(0))
102+
dxl.set_return_delay_time({args.id: 0})
103+
104+
print('Changing the angle limit to {}...').format(args.angle_limit)
105+
dxl.set_angle_limit({args.id: args.angle_limit})
106+
107+
print('Changing the baudrate to {}...'.format(TARGET_BAUDRATE))
108+
dxl.change_baudrate({args.id: TARGET_BAUDRATE})
109+
time.sleep(.5)
110+
print('Done!')
111+
112+
print('Now, checking that everything went well...')
113+
with DxlIO(port) as dxl:
114+
try:
115+
assert dxl.ping(args.id)
116+
assert dxl.get_return_delay_time([args.id]) == (0, )
117+
118+
except AssertionError:
119+
leave('Something went wrong with the settings of "Poppy-like"'
120+
' motors configuration.\nThis is probably due to'
121+
' a communication error. Please try again.')
122+
123+
lim = dxl.get_angle_limit([args.id])[0]
124+
if not all(map(almost_equal, lim, args.angle_limit)):
125+
print('Angle limit incorrect set {} instead of {}'.format(
126+
lim, args.angle_limit))
127+
128+
dxl.set_goal_position({args.id: args.position})
129+
while any(dxl.is_moving((args.id, ))):
130+
time.sleep(.1)
131+
132+
pos = dxl.get_present_position((args.id, ))[0]
133+
if not almost_equal(args.position, pos):
134+
print('Target position not reached: {} instead of {}.'.format(
135+
pos, args.position))
136+
137+
print('Done!')
138+
139+
140+
if __name__ == '__main__':
141+
main()

setup.py

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ def version():
3131
},
3232

3333
entry_points={
34+
'console_scripts': [
35+
'poppy-motor-reset = pypot.tools.dxl_reset:main'
36+
],
3437
'gui_scripts': [
3538
'herborist = pypot.tools.herborist.herborist:main [tools]',
3639
],

0 commit comments

Comments
 (0)