Joint-python-library 0.0.6__tar.gz → 0.0.7__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.7}/Joint_python_library.egg-info/PKG-INFO +1 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/PKG-INFO +1 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/Slave_Device.py +109 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/joint.py +110 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/setup.py +1 -1
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/SOURCES.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/dependency_links.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/entry_points.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/requires.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/top_level.txt +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/LICENSE +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/README.md +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/__init__.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/serial_port.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/__init__.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/joint_device.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/limits.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/main.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/ramp_trajectory.py +0 -0
- {joint_python_library-0.0.6 → joint_python_library-0.0.7}/setup.cfg +0 -0
{joint_python_library-0.0.6 → joint_python_library-0.0.7}/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.7
|
|
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.7
|
|
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
|
|
@@ -323,4 +323,113 @@ class Joint(Slave_Device):
|
|
|
323
323
|
|
|
324
324
|
elif package_number == 3:
|
|
325
325
|
return self.get_variables(*classic_package)
|
|
326
|
-
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def set_joint_variables_sync(port:SerialPort, parameter_idx, *idx_val_pairs):
|
|
330
|
+
"""
|
|
331
|
+
Build & send a WRITE_SYNC packet:
|
|
332
|
+
[HEADER, 0xFF, DEVICE_FAMILY, LENGTH, WRITE_SYNC, 0, PARAM_IDX, (ID, VALUE)*, CRC32]
|
|
333
|
+
- parameter_idx: single parameter index to write on each target
|
|
334
|
+
- idx_val_pairs: variadic list of 2-tuples/lists like (id, value) or [id, value]
|
|
335
|
+
- port: SerialPort-like object that has write(bytes) method
|
|
336
|
+
|
|
337
|
+
Returns: number of bytes written.
|
|
338
|
+
Raises: ValueError on malformed inputs.
|
|
339
|
+
"""
|
|
340
|
+
|
|
341
|
+
# --- Validate & fetch parameter meta
|
|
342
|
+
if parameter_idx not in VARS:
|
|
343
|
+
raise ValueError(f"Unknown parameter index: {parameter_idx}")
|
|
344
|
+
|
|
345
|
+
var_desc = VARS[parameter_idx]
|
|
346
|
+
val_fmt = var_desc.type() # e.g., 'f', 'i', 'H', etc. (little-endian will be applied later)
|
|
347
|
+
val_size = var_desc.size() # size in bytes
|
|
348
|
+
|
|
349
|
+
# --- Validate pairs; normalize to tuples
|
|
350
|
+
pairs = []
|
|
351
|
+
for p in idx_val_pairs:
|
|
352
|
+
if not hasattr(p, '__len__') or len(p) != 2:
|
|
353
|
+
raise ValueError(f"{p} must be a pair like [ID, value]")
|
|
354
|
+
dev_id, value = p[0], p[1]
|
|
355
|
+
|
|
356
|
+
# Device ID range (0..254), 255 is reserved for broadcast in header
|
|
357
|
+
if not (0 <= int(dev_id) <= 254):
|
|
358
|
+
raise ValueError(f"Device ID out of range (0..254): {dev_id}")
|
|
359
|
+
|
|
360
|
+
pairs.append((int(dev_id), value))
|
|
361
|
+
|
|
362
|
+
if not pairs:
|
|
363
|
+
raise ValueError("At least one [ID, value] pair is required.")
|
|
364
|
+
|
|
365
|
+
# --- Compute size field used by your protocol
|
|
366
|
+
# Payload after the 6 fixed header bytes:
|
|
367
|
+
# PARAM_IDX (1 byte)
|
|
368
|
+
# + for each pair: ID (1 byte) + VALUE (val_size bytes)
|
|
369
|
+
payload_size = 1 + len(pairs) * (1 + val_size)
|
|
370
|
+
|
|
371
|
+
# Protocol total-length field used in your other function:
|
|
372
|
+
# size + PING_PACKAGE_SIZE (to mirror your existing framing)
|
|
373
|
+
length_field = payload_size + PING_PACKAGE_SIZE
|
|
374
|
+
|
|
375
|
+
# --- Build struct format string & flat args
|
|
376
|
+
# Fixed header: '<BBBBBB'
|
|
377
|
+
# Then: PARAM_IDX (B)
|
|
378
|
+
# Then for each pair: ID (B) + VALUE (val_fmt)
|
|
379
|
+
fmt = '<BBBBBB' + 'B' + ''.join(['B' + val_fmt for _ in pairs])
|
|
380
|
+
|
|
381
|
+
flat = [
|
|
382
|
+
dev.SERIAL_HEADER, # header
|
|
383
|
+
0xFF, # broadcast ID
|
|
384
|
+
DEVICE_FAMILY, # device family
|
|
385
|
+
length_field, # total length field
|
|
386
|
+
Device_Commands.WRITE_SYNC, # command
|
|
387
|
+
0x00, # reserved
|
|
388
|
+
int(parameter_idx), # parameter index
|
|
389
|
+
]
|
|
390
|
+
|
|
391
|
+
# Append all (ID, VALUE) flattened; VALUE goes in native python type, struct packs it
|
|
392
|
+
for dev_id, value in pairs:
|
|
393
|
+
flat.append(dev_id)
|
|
394
|
+
flat.append(value)
|
|
395
|
+
|
|
396
|
+
# --- Pack without CRC
|
|
397
|
+
pkt_wo_crc = struct.pack(fmt, *flat)
|
|
398
|
+
|
|
399
|
+
# --- Append CRC32 (little-endian uint32 of the bytes above)
|
|
400
|
+
pkt = pkt_wo_crc + struct.pack('<I', CRC32.calc(pkt_wo_crc))
|
|
401
|
+
|
|
402
|
+
# --- Send over the provided port (broadcast sync write typically has no ACK)
|
|
403
|
+
written = port.write(pkt)
|
|
404
|
+
return written
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def set_variables(self, *idx_val_pairs, ack = False):
|
|
408
|
+
# returns : did ACK come?
|
|
409
|
+
fmt_str = '<BBBBBB'
|
|
410
|
+
var_count = 0
|
|
411
|
+
size = 0
|
|
412
|
+
for one_pair in idx_val_pairs:
|
|
413
|
+
try:
|
|
414
|
+
if len(one_pair) != 2:
|
|
415
|
+
raise ValueError(f"{one_pair} more than a pair! It is not a pair")
|
|
416
|
+
else:
|
|
417
|
+
fmt_str += ('B' + self._vars[one_pair[0]].type())
|
|
418
|
+
var_count+=1
|
|
419
|
+
size += (1 + self._vars[one_pair[0]].size())
|
|
420
|
+
except:
|
|
421
|
+
raise ValueError(f"{one_pair} is not proper pair")
|
|
422
|
+
|
|
423
|
+
flattened_list = [item for sublist in idx_val_pairs for item in sublist]
|
|
424
|
+
|
|
425
|
+
struct_out = list(struct.pack(fmt_str, *[self._header, self._id, self._device_family, size + PING_PACKAGE_SIZE, Device_Commands.WRITE, 0, *flattened_list]))
|
|
426
|
+
struct_out = bytes(struct_out) + struct.pack('<' + 'I', CRC32.calc(struct_out))
|
|
427
|
+
self._ack_size = PING_PACKAGE_SIZE
|
|
428
|
+
|
|
429
|
+
self._write_port(struct_out)
|
|
430
|
+
if(self.write_ack_enable):
|
|
431
|
+
if self._read_ack():
|
|
432
|
+
return True
|
|
433
|
+
else:
|
|
434
|
+
return False
|
|
435
|
+
return False
|
|
@@ -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.7",
|
|
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.",
|
{joint_python_library-0.0.6 → joint_python_library-0.0.7}/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.7}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|