Joint-python-library 0.0.6__tar.gz → 0.0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/PKG-INFO +1 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/PKG-INFO +1 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/acrome_joint/Slave_Device.py +109 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/acrome_joint/joint.py +115 -3
- joint_python_library-0.0.8/gui/joint_device.py +14 -0
- joint_python_library-0.0.8/gui/limits.py +18 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/gui/main.py +1 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/setup.py +1 -1
- joint_python_library-0.0.6/gui/joint_device.py +0 -6
- joint_python_library-0.0.6/gui/limits.py +0 -17
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/SOURCES.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/dependency_links.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/entry_points.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/requires.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/top_level.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/LICENSE +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/README.md +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/acrome_joint/__init__.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/acrome_joint/serial_port.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/gui/__init__.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/gui/ramp_trajectory.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.8}/setup.cfg +0 -0
{joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Joint-python-library
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.
|
|
5
5
|
Home-page: https://github.com/Acrome-Smart-Motion-Devices/python-library-new
|
|
6
6
|
Author: BeratComputer
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Joint-python-library
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.
|
|
5
5
|
Home-page: https://github.com/Acrome-Smart-Motion-Devices/python-library-new
|
|
6
6
|
Author: BeratComputer
|
|
@@ -10,6 +10,7 @@ HEADER, ID, DEVICE_FAMILY, PACKAGE_SIZE, COMMAND, STATUS, .............. DATA ..
|
|
|
10
10
|
'''
|
|
11
11
|
|
|
12
12
|
PING_PACKAGE_SIZE = 10
|
|
13
|
+
BROADCAST_ID = 255
|
|
13
14
|
|
|
14
15
|
#Classical Device Indexes
|
|
15
16
|
Index_Device_Classical = enum.IntEnum('Index', [
|
|
@@ -86,7 +87,9 @@ class Slave_Device():
|
|
|
86
87
|
SERIAL_HEADER = 0x55
|
|
87
88
|
_BROADCAST_ID = 0xFF
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
# NEW: device_family → variables (Data_ list) kaydı
|
|
91
|
+
_vars_registry = {} # { device_family:int : [Data_, Data_, ...] }
|
|
92
|
+
|
|
90
93
|
def __init__(self, id, device_family, variables, port:SerialPort):
|
|
91
94
|
self._port = port
|
|
92
95
|
self._header = self.SERIAL_HEADER
|
|
@@ -97,6 +100,7 @@ class Slave_Device():
|
|
|
97
100
|
self.__post_sleep = 0.01
|
|
98
101
|
self.__device_init_sleep = 3
|
|
99
102
|
self.write_ack_enable = False
|
|
103
|
+
Slave_Device._vars_registry.setdefault(device_family, variables)
|
|
100
104
|
|
|
101
105
|
def enable_get_ack(self):
|
|
102
106
|
self.write_ack_enable = True
|
|
@@ -312,3 +316,107 @@ class Data_():
|
|
|
312
316
|
|
|
313
317
|
def type(self) -> str:
|
|
314
318
|
return self.__type
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def write_sync_to_many(
|
|
323
|
+
port: SerialPort,
|
|
324
|
+
device_family: int,
|
|
325
|
+
index: int,
|
|
326
|
+
*id_value_pairs,
|
|
327
|
+
expect_ack: bool = False
|
|
328
|
+
) -> bool:
|
|
329
|
+
"""
|
|
330
|
+
Aynı değişken index'ini birden fazla cihaza WRITE_SYNC ile yazar.
|
|
331
|
+
Değer tipi, device_family'nin kayıtlı değişken tablosundan otomatik çekilir.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
port (SerialPort): paylaşılan seri port
|
|
335
|
+
device_family (int): ürün ailesi (ör. Joint için 0xDA)
|
|
336
|
+
index (int | enum.IntEnum): yazılacak değişken indeksi
|
|
337
|
+
*id_value_pairs: [id, value] çiftleri (list/tuple), örn: [0, 123], [1, -45], ...
|
|
338
|
+
expect_ack (bool): ACK beklenip beklenmeyeceği
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
bool: True = yazdı (veya ACK doğrulandı); False = ACK bekleniyorsa doğrulanamadı
|
|
342
|
+
"""
|
|
343
|
+
import struct
|
|
344
|
+
from crccheck.crc import Crc32Mpeg2 as CRC32
|
|
345
|
+
|
|
346
|
+
# Sabitler
|
|
347
|
+
HEADER = Slave_Device.SERIAL_HEADER
|
|
348
|
+
BATCH_ID = Slave_Device._BROADCAST_ID
|
|
349
|
+
PING_PACKAGE_SIZE = 10
|
|
350
|
+
WRITE_SYNC = int(Device_Commands.WRITE_SYNC)
|
|
351
|
+
STATUS = 0
|
|
352
|
+
|
|
353
|
+
# Registry ve tip çözümü
|
|
354
|
+
reg = Slave_Device._vars_registry.get(device_family)
|
|
355
|
+
if reg is None:
|
|
356
|
+
raise RuntimeError(
|
|
357
|
+
f"Device family 0x{device_family:02X} için değişken tablosu bulunamadı. "
|
|
358
|
+
"Bu family’den en az bir cihaz instance'ı oluşturulmuş olmalı."
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
idx_int = int(index)
|
|
362
|
+
try:
|
|
363
|
+
var_type = reg[idx_int].type() # 'f', 'i', 'B', ...
|
|
364
|
+
except Exception as e:
|
|
365
|
+
raise ValueError(f"Geçersiz index: {index} (family=0x{device_family:02X}).") from e
|
|
366
|
+
|
|
367
|
+
# id_value_pairs doğrula ve düzle
|
|
368
|
+
flat = []
|
|
369
|
+
for pair in id_value_pairs:
|
|
370
|
+
if (not isinstance(pair, (list, tuple))) or len(pair) != 2:
|
|
371
|
+
raise ValueError(f"{pair} geçersiz. [ID, value] olmalı.")
|
|
372
|
+
dev_id, val = pair
|
|
373
|
+
if not (0 <= int(dev_id) <= 254):
|
|
374
|
+
raise ValueError(f"ID {dev_id} geçersiz (0..254).")
|
|
375
|
+
# 'val' tipi Data_.type() ile belirlenecek; pack sırasında kontrol olur
|
|
376
|
+
flat.extend([int(dev_id), val])
|
|
377
|
+
|
|
378
|
+
count = len(flat) // 2
|
|
379
|
+
if count == 0:
|
|
380
|
+
raise ValueError("En az bir [ID, value] çifti gerekli.")
|
|
381
|
+
|
|
382
|
+
val_size = struct.calcsize('<' + var_type)
|
|
383
|
+
|
|
384
|
+
# Paket boyutu
|
|
385
|
+
# payload = index(1B) + her cihaz için (ID:1B + value:val_size)
|
|
386
|
+
payload_size = 1 + count * (1 + val_size)
|
|
387
|
+
package_size = PING_PACKAGE_SIZE + payload_size
|
|
388
|
+
|
|
389
|
+
# Format: header, BATCH_ID, family, size, cmd, status, index, (id, value)*N, crc
|
|
390
|
+
fmt = '<BBBBBB' + 'B' + ('B' + var_type) * count
|
|
391
|
+
data_no_crc = struct.pack(
|
|
392
|
+
fmt,
|
|
393
|
+
HEADER,
|
|
394
|
+
BATCH_ID,
|
|
395
|
+
device_family,
|
|
396
|
+
package_size,
|
|
397
|
+
WRITE_SYNC,
|
|
398
|
+
STATUS,
|
|
399
|
+
idx_int,
|
|
400
|
+
*flat
|
|
401
|
+
)
|
|
402
|
+
pkt = data_no_crc + struct.pack('<I', CRC32.calc(data_no_crc))
|
|
403
|
+
|
|
404
|
+
# Gönder
|
|
405
|
+
port._write_bus(pkt)
|
|
406
|
+
|
|
407
|
+
if not expect_ack:
|
|
408
|
+
return True
|
|
409
|
+
|
|
410
|
+
# Basit ACK okuma (PING_PACKAGE_SIZE kadar)
|
|
411
|
+
ack = port._read_bus(size=PING_PACKAGE_SIZE)
|
|
412
|
+
if not ack or len(ack) != PING_PACKAGE_SIZE:
|
|
413
|
+
return False
|
|
414
|
+
|
|
415
|
+
# CRC kontrolü
|
|
416
|
+
try:
|
|
417
|
+
data_part = ack[:-4]
|
|
418
|
+
crc_part = ack[-4:]
|
|
419
|
+
ok = (CRC32.calc(data_part) == struct.unpack('<I', crc_part)[0])
|
|
420
|
+
return bool(ok)
|
|
421
|
+
except Exception:
|
|
422
|
+
return False
|
|
@@ -12,7 +12,8 @@ from acrome_joint.Slave_Device import *
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
# enter here for extra commands:
|
|
15
|
-
|
|
15
|
+
class Device_ExtraCommands(enum.IntEnum):
|
|
16
|
+
PROTOCOL_RESET_ABSOLUTE_ENCODER = 0x11
|
|
16
17
|
# .......... start with 11
|
|
17
18
|
# .......... end of extra commmands max: 39
|
|
18
19
|
|
|
@@ -143,7 +144,7 @@ class Joint(Slave_Device):
|
|
|
143
144
|
Data_(Index_Joint.current_Id, 'f'),
|
|
144
145
|
Data_(Index_Joint.current_Iq, 'f'),
|
|
145
146
|
Data_(Index_Joint.current_velocity, 'f'),
|
|
146
|
-
Data_(Index_Joint.current_position, '
|
|
147
|
+
Data_(Index_Joint.current_position, 'f'),
|
|
147
148
|
Data_(Index_Joint.current_electrical_degree, 'f'),
|
|
148
149
|
Data_(Index_Joint.current_electrical_radian, 'f'),
|
|
149
150
|
Data_(Index_Joint.setpoint_current, 'f'),
|
|
@@ -282,7 +283,17 @@ class Joint(Slave_Device):
|
|
|
282
283
|
return super().set_variables(*idx_val_pairs, ack=ack)
|
|
283
284
|
|
|
284
285
|
|
|
286
|
+
def get_currentStatus_parameters(self):
|
|
287
|
+
classic_package = [
|
|
288
|
+
Index_Joint.Enable,
|
|
289
|
+
Index_Joint.current_Id, Index_Joint.current_Iq,
|
|
290
|
+
Index_Joint.current_velocity, Index_Joint.current_position,
|
|
291
|
+
Index_Joint.Temprature_read,
|
|
292
|
+
Index_Joint.setpoint_current, Index_Joint.setpoint_velocity, Index_Joint.setpoint_position
|
|
293
|
+
]
|
|
294
|
+
return self.get_variables(*classic_package)
|
|
285
295
|
|
|
296
|
+
|
|
286
297
|
def get_FOC_parameters(self, package_number:int):
|
|
287
298
|
if package_number >= 4:
|
|
288
299
|
raise "invalid package number ex: 0, 1, 2"
|
|
@@ -323,4 +334,105 @@ class Joint(Slave_Device):
|
|
|
323
334
|
|
|
324
335
|
elif package_number == 3:
|
|
325
336
|
return self.get_variables(*classic_package)
|
|
326
|
-
|
|
337
|
+
|
|
338
|
+
def reset_absolute_encoder(self):
|
|
339
|
+
self._pure_command_send(Device_ExtraCommands.PROTOCOL_RESET_ABSOLUTE_ENCODER)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def set_joint_variables_sync(port: SerialPort, parameter_idx, *idx_val_pairs):
|
|
343
|
+
"""
|
|
344
|
+
Sync Write paketi oluşturur ve gönderir.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
port: SerialPort nesnesi.
|
|
348
|
+
parameter_idx: Index_Joint enum değeri (örn: Index_Joint.Enable).
|
|
349
|
+
idx_val_pairs: [DeviceID, Value] listeleri. Örn: [0, True], [1, True]
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
# 1. Port Kontrolü
|
|
353
|
+
if port is None:
|
|
354
|
+
raise ValueError("Port tanımlı değil.")
|
|
355
|
+
|
|
356
|
+
# 2. Referans Cihaz Oluşturma
|
|
357
|
+
# Data_ yapısındaki .type() ve .size() metotlarına erişmek için.
|
|
358
|
+
try:
|
|
359
|
+
ref_device = Joint(0, port)
|
|
360
|
+
except Exception as e:
|
|
361
|
+
raise ValueError(f"Referans Joint nesnesi oluşturulamadı: {e}")
|
|
362
|
+
|
|
363
|
+
# 3. Parametre Bilgilerini Çekme
|
|
364
|
+
try:
|
|
365
|
+
var_desc = ref_device._vars[parameter_idx]
|
|
366
|
+
except IndexError:
|
|
367
|
+
raise ValueError(f"Bilinmeyen parametre indeksi: {parameter_idx}")
|
|
368
|
+
except AttributeError:
|
|
369
|
+
raise ValueError("Joint nesnesinde '_vars' listesi bulunamadı.")
|
|
370
|
+
|
|
371
|
+
# --- DÜZELTME BURADA ---
|
|
372
|
+
# .type ve .size muhtemelen metot olduğu için () ile çağırıyoruz.
|
|
373
|
+
val_fmt = var_desc.type() # 'f', 'B', 'I' vb. döndürür
|
|
374
|
+
val_size = var_desc.size() # 4, 1 vb. int döndürür
|
|
375
|
+
|
|
376
|
+
# 4. Veri Çiftlerini Doğrulama
|
|
377
|
+
pairs = []
|
|
378
|
+
for p in idx_val_pairs:
|
|
379
|
+
if not hasattr(p, '__len__') or len(p) != 2:
|
|
380
|
+
raise ValueError(f"Hatalı veri çifti: {p}. Format [ID, Value] olmalı.")
|
|
381
|
+
|
|
382
|
+
dev_id, value = p[0], p[1]
|
|
383
|
+
|
|
384
|
+
# ID Kontrolü
|
|
385
|
+
if not (0 <= int(dev_id) <= 254):
|
|
386
|
+
raise ValueError(f"Device ID aralık dışı (0..254): {dev_id}")
|
|
387
|
+
|
|
388
|
+
pairs.append((int(dev_id), value))
|
|
389
|
+
|
|
390
|
+
if not pairs:
|
|
391
|
+
raise ValueError("Gönderilecek veri çifti bulunamadı.")
|
|
392
|
+
|
|
393
|
+
# 5. Paket Boyutlarını Hesaplama
|
|
394
|
+
# Payload: [PARAM_IDX] + ([ID] + [VALUE]) * N
|
|
395
|
+
# Artık val_size bir int olduğu için toplama işlemi çalışacaktır.
|
|
396
|
+
payload_size = 1 + len(pairs) * (1 + val_size)
|
|
397
|
+
|
|
398
|
+
length_field = payload_size + Joint._PACKAGE_ESSENTIAL_SIZE + 4 # 4 byte CRC ekle
|
|
399
|
+
|
|
400
|
+
# 6. Struct Formatını Hazırlama
|
|
401
|
+
# Header(6 byte) + ParamIdx(1 byte) + (DevID(1 byte) + Value(N byte)) * Adet
|
|
402
|
+
fmt = '<BBBBBB' + 'B' + ''.join(['B' + val_fmt for _ in pairs])
|
|
403
|
+
|
|
404
|
+
# 7. Paket İçeriği (Header, ID, Family, Length, Command...)
|
|
405
|
+
HEADER_BYTE = 0x55
|
|
406
|
+
BROADCAST_ID = 0xFF
|
|
407
|
+
CMD_WRITE_SYNC = Device_Commands.WRITE_SYNC
|
|
408
|
+
device_family = Joint._PRODUCT_TYPE
|
|
409
|
+
|
|
410
|
+
flat = [
|
|
411
|
+
HEADER_BYTE, # Header
|
|
412
|
+
BROADCAST_ID, # Broadcast ID (0xFF)
|
|
413
|
+
device_family, # Device Family
|
|
414
|
+
length_field, # Length
|
|
415
|
+
CMD_WRITE_SYNC, # Command
|
|
416
|
+
0x00, # Status
|
|
417
|
+
int(parameter_idx), # Parametre ID
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
# Değerleri ekle
|
|
421
|
+
for dev_id, value in pairs:
|
|
422
|
+
flat.append(dev_id)
|
|
423
|
+
flat.append(value)
|
|
424
|
+
|
|
425
|
+
# 8. Paketleme
|
|
426
|
+
try:
|
|
427
|
+
pkt_wo_crc = struct.pack(fmt, *flat)
|
|
428
|
+
except struct.error as e:
|
|
429
|
+
# Genellikle float yerine int veya tam tersi gelince oluşur
|
|
430
|
+
raise ValueError(f"Struct paketleme hatası (Veri tipi uyumsuzluğu): {e}")
|
|
431
|
+
|
|
432
|
+
# 9. CRC32
|
|
433
|
+
crc_val = CRC32.calc(pkt_wo_crc)
|
|
434
|
+
pkt = pkt_wo_crc + struct.pack('<I', crc_val)
|
|
435
|
+
|
|
436
|
+
# 10. Gönder
|
|
437
|
+
written = port._write_bus(pkt)
|
|
438
|
+
return written
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from acrome_joint.joint import*
|
|
2
|
+
|
|
3
|
+
keyword_for_usb = "USB-SERIAL"
|
|
4
|
+
altarnate_keyword_for_usb = "USB-Enhanced-SERIAL"
|
|
5
|
+
if(not USB_serial_port(keyword_for_usb)):
|
|
6
|
+
if(not USB_serial_port(altarnate_keyword_for_usb)):
|
|
7
|
+
raise Exception("No USB serial port found. Please check your connections.")
|
|
8
|
+
else:
|
|
9
|
+
keyword_for_usb = altarnate_keyword_for_usb
|
|
10
|
+
|
|
11
|
+
port = SerialPort(USB_serial_port(keyword_for_usb), baudrate=921600, timeout=0.1)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Device = Joint(1, port)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
# SPEED = RPM, ACC= RPM/s
|
|
3
|
+
ENCODER_CPR = 16384
|
|
4
|
+
|
|
5
|
+
MOTOR_VEL_MAX = 3000.0 # in rpm
|
|
6
|
+
MOTOR_ACC_MAX = 3000.0
|
|
7
|
+
|
|
8
|
+
ENC_TO_RPM_CONSTANT = ENCODER_CPR / 60
|
|
9
|
+
|
|
10
|
+
MOTOR_VEL_MAX_IN_ENC_TYPE = MOTOR_VEL_MAX * ENC_TO_RPM_CONSTANT
|
|
11
|
+
MOTOR_ACC_MAX_IN_ENC_TYPE = MOTOR_ACC_MAX * ENC_TO_RPM_CONSTANT
|
|
12
|
+
|
|
13
|
+
def rpm_to_tick_per_second(rpm:float):
|
|
14
|
+
return rpm*ENCODER_CPR/60
|
|
15
|
+
|
|
16
|
+
def tick_per_second_to_rpm(tick_per_second:float):
|
|
17
|
+
return tick_per_second*60/ENCODER_CPR
|
|
18
|
+
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="Joint-python-library",
|
|
8
|
-
version="0.0.
|
|
8
|
+
version="0.0.8",
|
|
9
9
|
author="BeratComputer",
|
|
10
10
|
author_email="beratdogan@acrome.net",
|
|
11
11
|
description="Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# SPEED = RPM, ACC= RPM/s
|
|
3
|
-
ENCODER_CPR = 4096
|
|
4
|
-
|
|
5
|
-
MOTOR_VEL_MAX = 150.0 # in rpm
|
|
6
|
-
MOTOR_ACC_MAX = 500.0
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
MOTOR_VEL_MAX_IN_ENC_TYPE = MOTOR_VEL_MAX * 68.2666
|
|
10
|
-
MOTOR_ACC_MAX_IN_ENC_TYPE = MOTOR_ACC_MAX * 68.2666
|
|
11
|
-
|
|
12
|
-
def rpm_to_tick_per_second(rpm:float):
|
|
13
|
-
return rpm*ENCODER_CPR/60
|
|
14
|
-
|
|
15
|
-
def tick_per_second_to_rpm(tick_per_second:float):
|
|
16
|
-
return tick_per_second*60/ENCODER_CPR
|
|
17
|
-
|
{joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{joint_python_library-0.0.6 → joint_python_library-0.0.8}/Joint_python_library.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|