Compare commits

..

No commits in common. "urdf" and "bx-1198-class_refactor" have entirely different histories.

70 changed files with 27184 additions and 4408 deletions

7
.gitignore vendored
View File

@ -2,9 +2,4 @@ __pycache__/
.venv/
.vscode/
build/
data/*
/dist/**/*
dist.zip
.venv
*.log
log/*
dist/

View File

@ -1,16 +0,0 @@
## Работа с роботом
### Окружение
* Запустить сокет сервер - для теста
* Запустить pybullet сервер - визуализация в отдельном ПРОЦЕССЕ
* Запустить gui
### Локальный запуск
* `poetry install`
* Запустить в отдельном окне тестовый сокет `poetry run python utils/test_socket_server.py`
* Запустить программу с визуализацией в отдельном окне `poetry run python ru.py --start-py --bullet-gui`
### На чем работает
* Визуализация и расчет положения робота - pybullet
* Паллетизация py3dbp
* Отправка данных по сокету `robot/socket_manager.py` и подготовка данных в нужном формате `robot/prepare_data.py`

View File

View File

@ -8,25 +8,23 @@ import tkinter as tk
from func import *
window = tk.Tk()
window.geometry("520x300")
window.geometry('520x300')
label = tk.Label(window, text="Hello, world!")
label.pack()
all_files = glob.glob("data/*.nc")
all_files = glob.glob("data/data.txt")
file = all_files[0]
data = [
("line", 0, 0, 277.8, 0, 5, 0),
]
# with open(file, "r") as fp:
# lines = fp.readlines()
# for l in lines:
# r = l.strip().split(",")
# r[1] = float(r[1])
# r[2] = float(r[2])
# r[3] = float(r[3])
data = []
with open(file, "r") as fp:
lines = fp.readlines()
for l in lines:
r = l.strip().split(",")
r[1] = float(r[1])
r[2] = float(r[2])
r[3] = float(r[3])
# data.append(r)
data.append(r)
client = ModbusTcpClient(
host=MODBUS_SERVER_HOST,
@ -115,5 +113,5 @@ except Exception as e:
finally:
client.close()
if __name__ == "__main__":
if __name__=="__main__":
window.mainloop()

230
client_socket.py Normal file
View File

@ -0,0 +1,230 @@
import socket
import json
import sys
from pprint import pprint
import tkinter
from func import *
class SocketRobotArm:
line_speed = 100.0
line_smooth = 9
line_tool = 1
global_speed = 100
physical_speed = 50
# laser_id = 15
laser_id = 14
# filename = 'half-sphere-no-angle'
filename = "half-sphere"
pass_size = 4
def __init__(self, *args, **kwargs):
self.socket = socket.socket()
self.host = MODBUS_SERVER_HOST
self.port = 9760
# self.host = "127.0.0.1"
# self.port = 65432
self.tkinter_root = tkinter.Tk()
self.connect()
def __exit__(self, exc_type, exc_value, traceback):
self.socket.close()
def close(self):
self.socket.close()
self.tkinter_root.destroy()
sys.exit()
def set_text(self, text):
label = tkinter.Label(self.tkinter_root, text=text)
label.pack()
self.tkinter_root.update()
def connect(self):
self.socket.connect((self.host, self.port))
self.tkinter_root.geometry("500x300")
self.get_axis()
self.set_text(text=f"Координаты осей {self.start_axis_coordinates}")
self.get_world()
self.set_text( text=f"Мировые координаты {self.start_world_coordinates}")
self.get_command_count()
self.set_text( text=f"Команд в очереди {self.remote_command_count}")
self.send_data(self.set_global_speed())
self.set_text( text=f"Установили глобальную скорость {self.global_speed}")
self.send_data(self.start_cycle())
self.set_text( text=f"Старт одиночного цикла")
self.add_rcc_list = (
[self.set_physical_speed(True), self.set_output_laser(True)]
+ self.steps_from_file()
+ [self.set_physical_speed(False), self.set_output_laser(False)]
)
my_label = tkinter.Label(self.tkinter_root, text=f"Отправка данных")
my_label.pack()
self.tkinter_root.update()
exit_button = tkinter.Button(self.tkinter_root, text="Exit", command=self.close)
exit_button.pack(pady=20)
step = 2
for i in range(0, len(self.add_rcc_list), step):
print(f"Отправка данных {i}...{i+step-1}")
# self.update_text(m, text=f"Отправка данных {i}...{i+step-1}")
my_label.config(text=f"Отправка данных {i}...{i+step-1}")
self.tkinter_root.update()
self.send_data(
make_addrcc_data(self.add_rcc_list[i : i + step], int(not i))
)
time.sleep(0.5)
def send_data(self, data):
response = None
# if data["reqType"] == "AddRCC":
# return
self.socket.send(str.encode(json.dumps(data)))
response_data = self.socket.recv(1024)
response = json.loads(response_data)
if data["reqType"] == "query":
return response["queryData"]
elif data["reqType"] == "command":
return response["cmdReply"]
elif data["reqType"] == "AddRCC" and "cmdReply" in response.keys():
return response["cmdReply"]
else:
pprint(response)
def get_axis(self):
axis_coord_raw = self.send_data(
make_query_data(
["axis-0", "axis-1", "axis-2", "axis-3", "axis-4", "axis-5"]
)
)
self.start_axis_coordinates = [float(i) for i in axis_coord_raw]
print("start_axis_coordinates", self.start_axis_coordinates)
def get_world(self):
world_coord_raw = self.send_data(
make_query_data(
["world-0", "world-1", "world-2", "world-3", "world-4", "world-5"]
)
)
self.start_world_coordinates = [float(i) for i in world_coord_raw]
print("start_world_coordinates", self.start_world_coordinates)
def get_command_count(self):
res = self.send_data(make_query_data(["RemoteCmdLen"]))
self.remote_command_count = res
print(res)
def set_global_speed(self):
# Изменили глобальную скорость на global_speed%
return make_command_data(["modifyGSPD", str(self.global_speed * 10)])
def start_cycle(self):
return make_command_data(["actionSingleCycle"])
def round(v):
return round(v, 3)
def make_world_step(self, type, point):
step = {
"oneshot": "0",
"delay": "0.0",
"speed": str(self.line_speed),
"smooth": str(self.line_smooth),
"coord": "0",
"tool": str(self.line_tool),
"ckStatus": "0x3F",
}
if type == "line":
pairs = zip(self.start_world_coordinates, point)
m0, m1, m2, m3, m4, m5 = [round(sum(i), 3) for i in pairs]
step.update({"action": "10"})
step.update({"m0": m0, "m1": m1, "m2": m2, "m3": m3, "m4": m4, "m5": m5})
step.update({"m6": 0, "m7": 0})
elif type == "curve":
pairs = zip(self.start_world_coordinates, point[:5])
m0, m1, m2, m3, m4, m5 = [round(sum(i), 3) for i in pairs]
pairs_p = zip(self.start_world_coordinates, point[6:])
m0_p, m1_p, m2_p, m3_p, m4_p, m5_p = [round(sum(i), 3) for i in pairs_p]
step.update({"action": "17"})
step.update({"m0": m0, "m1": m1, "m2": m2, "m3": m3, "m4": m4, "m5": m5})
step.update({"m6": 0, "m7": 0})
step.update(
{
"m0_p": m0_p,
"m1_p": m1_p,
"m2_p": m2_p,
"m3_p": m3_p,
"m4_p": m4_p,
"m5_p": m5_p,
}
)
step.update({"m6_p": 0, "m7_p": 0})
for s in step:
step[s] = str(step[s])
return step
def set_physical_speed(self, status: bool = False):
return (
{
"oneshot": "0",
"action": "51",
"isUse": str(int(status)),
"speed": str(self.physical_speed * 1000),
},
)
def set_output_laser(self, status: bool = False):
return (
{
"oneshot": "0",
"action": "200",
"type": "0",
"io_status": str(int(status)),
"point": str(self.laser_id),
},
)
def steps_from_file(self):
result = []
with open(f"data/{self.filename}.nc.result", "r") as fp:
for line in fp:
data = line.strip().split(" ")
prep = {}
for item in data:
prep[item[:1]] = float(item[1:])
result.append(
self.make_world_step(
"line",
(
prep.get("X", 0),
prep.get("Y", 0),
prep.get("Z", 0),
prep.get("U", 0),
prep.get("V", 0),
prep.get("W", 0),
),
)
)
return result
SocketRobotArm()

11119
data/half-sphere-no-angle.nc Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

11001
data/half-sphere.nc Normal file

File diff suppressed because it is too large Load Diff

2192
data/half-sphere.nc.result Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
X0 Y0 Z0
X-300 Y0 Z0
X-300 Y-300 Z0
X0 Y-300 Z0
X0 Y0 Z0
X0 Y0 Z300
X-300 Y0 Z300
X-300 Y-300 Z300
X0 Y-300 Z300
X0 Y0 Z300
X0 Y0 Z0

View File

View File

@ -1,9 +1,7 @@
# Настройки клиента Modbus
MODBUS_SERVER_HOST = "192.168.70.55" # IP-адрес Modbus-сервера
# MODBUS_SERVER_HOST = "192.168.70.65" # IP-адрес Modbus-сервера
MODBUS_SERVER_PORT = 502
MODBUS_SLAVE_ID = 11
# MODBUS_SLAVE_ID = 22
indent = 21100
s = 800
@ -24,7 +22,7 @@ def two_byte_convert(result):
return value
def bulb(addr, new_state, client, slave_id):
def bulb(addr, new_state, client):
try:
coils = client.read_coils(addr, 1, MODBUS_SLAVE_ID)
# print("читаем начальное состояние", coils.bits)

View File

@ -1,55 +0,0 @@
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QPushButton
from PyQt6.QtCore import QTimer, Qt
import time
from logger import logger
class Command(QWidget):
def __init__(self, startCommand, changeType, command_data, command_type):
super().__init__()
self.command_data = command_data
self.command_type = command_type
self.startCommand = startCommand
self.changeType = changeType
self.initUI()
self.timer = QTimer()
self.timer.timeout.connect(self.updateState)
self.timer.start(int(100))
def initUI(self):
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.stepLabel = QLabel(text="Загрузка данных")
self.commandLabel = QLabel(text="Тип загрузки")
for l in [self.commandLabel, self.stepLabel]:
l.setWordWrap(True)
self.layout.addWidget(l)
self.updButton = QPushButton("Запустить single cycle")
self.updButton.clicked.connect(self.startCommand)
self.layout.addWidget(self.updButton)
self.chgButton = QPushButton("Изменить тип")
cur_types = ["base", "calc", "pallette"]
self.chgButton.clicked.connect(
lambda: self.changeType(
cur_types[(cur_types.index(self.command_type()) + 1) % len(cur_types)]
)
)
self.layout.addWidget(self.chgButton)
def paintEvent(self, event):
# Установка цвета фона
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
def updateState(self):
self.stepLabel.setText(f"{self.command_data()}")
self.commandLabel.setText(f"Тип загрузки {self.command_type()}")

View File

@ -1,55 +0,0 @@
import time
from PyQt6.QtWidgets import (
QWidget,
QVBoxLayout,
QLabel,
QRadioButton,
QPushButton,
QButtonGroup,
)
from PyQt6.QtCore import Qt, QTimer
from logger import logger
class ChangeFile(QWidget):
def __init__(self, files, getFilename, setFilename):
super().__init__()
self.files = files or []
self.getFilename = getFilename
self.setFilename = setFilename
self.initUI()
self.old_status = None
self.counter = 0
def initUI(self):
self.layout = QVBoxLayout()
self.fileLabel = QLabel("Выберите файл")
self.layout.addWidget(self.fileLabel)
self.buttonGroup = QButtonGroup(self)
self.fileRadio = []
for i, r in enumerate(self.files):
radioButton = QRadioButton(r)
self.buttonGroup.addButton(radioButton, i)
self.fileRadio.append(radioButton)
self.layout.addWidget(radioButton)
self.setButton = QPushButton("Указать")
self.setButton.clicked.connect(self.setFilenameFunc)
self.layout.addWidget(self.setButton)
self.setLayout(self.layout)
def setFilenameFunc(self):
selectedId = self.buttonGroup.checkedId()
v = self.files[selectedId].split('.')[0]
self.setFilename(v)
def paintEvent(self, event):
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
super().paintEvent(event)

View File

@ -1,42 +0,0 @@
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QPushButton
from PyQt6.QtCore import QTimer, Qt
import time
from logger import logger
class Imitator(QWidget):
def __init__(self, startImitate, imitate_point):
super().__init__()
self.imitate_point = imitate_point
self.startImitate = startImitate
self.initUI()
self.timer = QTimer()
self.timer.timeout.connect(self.updateState)
self.timer.start(int(100))
def initUI(self):
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.stepLabel = QLabel(f"Отправлено шагов {0}")
for l in [self.stepLabel]:
l.setWordWrap(True)
self.layout.addWidget(l)
self.updButton = QPushButton("Запустить имитацию")
self.updButton.clicked.connect(self.startImitate)
self.layout.addWidget(self.updButton)
def paintEvent(self, event):
# Установка цвета фона
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
def updateState(self):
self.stepLabel.setText(f"Отправлено шагов {self.imitate_point()}")

View File

@ -1,51 +0,0 @@
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QPushButton
from PyQt6.QtCore import QTimer, Qt
import time
from logger import logger
class Informer(QWidget):
def __init__(self, updateData, world_coord, axis_coord, command_count):
super().__init__()
self.world_coord = world_coord
self.axis_coord = axis_coord
self.command_count = command_count
self.updateData = updateData
self.timer = QTimer()
self.timer.timeout.connect(self.updateState)
self.timer.start(int(100))
# Инициализация пользовательского интерфейса
self.initUI()
def initUI(self):
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.wLabel = QLabel(f'Мировые координаты {self.world_coord()}')
self.aLabel = QLabel(f'Поворот осей {self.axis_coord()}')
self.cLabel = QLabel(f'Количество команд в стеке {self.command_count()}')
for l in [self.wLabel, self.aLabel, self.cLabel]:
l.setWordWrap(True)
self.layout.addWidget(l)
self.updButton = QPushButton('Обновить данные')
self.updButton.clicked.connect(self.updateData)
self.layout.addWidget(self.updButton)
def paintEvent(self, event):
# Установка цвета фона
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
def updateState(self):
self.wLabel.setText(f'Мировые координаты {self.world_coord()}')
self.aLabel.setText(f'Поворот осей {self.axis_coord()}')
self.cLabel.setText(f'Количество команд в стеке {self.command_count()}')

View File

@ -1,126 +0,0 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QColor, QPalette
from gui.robot import ChangeRobot
from gui.filename import ChangeFile
from gui.status import Status
from gui.informer import Informer
from gui.imitator import Imitator
from gui.command import Command
from gui.visualize import Visualize
from gui.palletizing import Palletizing
from gui.observable import Observable
from logger import logger
class MyPanel(QWidget):
def __init__(self, panels, color):
super().__init__()
layout = QVBoxLayout()
for panel in panels:
layout.addWidget(panel)
self.color = QColor(*color)
self.setLayout(layout)
self.initUI()
def initUI(self):
palette = self.palette()
palette.setColor(QPalette.ColorRole.Window, self.color)
self.setAutoFillBackground(True)
self.setPalette(palette)
class MainContentComponent(QWidget):
def __init__(self, **kwargs):
super().__init__()
self.observable = Observable(kwargs.get("get_status"))
self.observable.value_changed.connect(self.handle_value_change)
robotArgs = kwargs.get("robotPanel", {})
self.robotPanel = ChangeRobot(**robotArgs)
statusArgs = kwargs.get("statusPanel", {})
self.statusPanel = Status(**statusArgs)
informerArgs = kwargs.get("informerPanel", {})
self.informerPanel = Informer(**informerArgs)
filenameArgs = kwargs.get("filenamePanel", {})
self.filenamePanel = ChangeFile(**filenameArgs)
imitatorArgs = kwargs.get("imitatorPanel", {})
self.imitatorPanel = Imitator(**imitatorArgs)
commandArgs = kwargs.get("commandPanel", {})
self.commandPanel = Command(**commandArgs)
palletizingArgs = kwargs.get("palletizingPanel", {})
self.palletizingPanel = Palletizing(**palletizingArgs)
self.rightPanel = MyPanel(
panels=[
# self.statusPanel,
self.robotPanel,
self.informerPanel,
# self.filenamePanel,
# self.imitatorPanel,
self.palletizingPanel,
self.commandPanel,
],
color=(169, 169, 169),
)
visArgs = kwargs.get("visPanel", {})
self.visPanel = Visualize(**visArgs)
self.mainPanel = MyPanel(
panels=[
self.visPanel,
],
color=(200, 200, 200),
)
layout = QHBoxLayout()
layout.addWidget(self.mainPanel)
layout.addWidget(self.rightPanel)
self.setLayout(layout)
self.setFixedSize(800, 800)
self.initUI()
def initUI(self):
palette = QPalette()
palette.setColor(QPalette.ColorRole.Window, QColor(240, 240, 240))
self.setPalette(palette)
def resizeEvent(self, event):
width = self.width()
rightPanelWidth = int(width * 0.25)
self.rightPanel.setFixedWidth(rightPanelWidth)
super().resizeEvent(event)
def handle_value_change(self, new_value):
panels = [
self.informerPanel,
self.filenamePanel,
self.imitatorPanel,
self.commandPanel,
self.palletizingPanel,
]
for p in panels:
if new_value == "not_connected":
p.setDisabled(True)
if new_value == "connected":
p.setDisabled(False)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainContentComponent(
robotPanel={"arg1": "value1"}, statusPanel={"arg1": "value1"}
)
mainWindow.show()
sys.exit(app.exec_())

View File

@ -1,22 +0,0 @@
from PyQt6.QtCore import pyqtSignal, QObject, QTimer
from logger import logger
class Observable(QObject):
value_changed = pyqtSignal(object) # Сигнал с переданным значением
def __init__(self, func, interval=1000):
super().__init__()
self.get_dynamic_value = func
self._value = None
# Таймер для периодической проверки значения
self.timer = QTimer(self)
self.timer.timeout.connect(self.check_function) # Вызываем some_function на каждом таймере
self.timer.start(interval) # Интервал в миллисекундах
def check_function(self):
# Пример функции, которая обновляет значение
new_value = self.get_dynamic_value()
if new_value != self._value:
self._value = new_value
self.value_changed.emit(new_value)

View File

@ -1,40 +0,0 @@
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
from PyQt6.QtCore import Qt, QTimer
from logger import logger
class Palletizing(QWidget):
def __init__(self, load_palletizing, start_moving):
super().__init__()
self.load_palletizing = load_palletizing
self.start_moving = start_moving
self.initUI()
def initUI(self):
self.layout = QVBoxLayout()
self.robotsLabel = QLabel("Паллетирование")
self.layout.addWidget(self.robotsLabel)
self.palletButton = QPushButton("Визуализировать")
self.palletButton.clicked.connect(self.startPalletzing)
self.layout.addWidget(self.palletButton)
self.startButton = QPushButton("Конвейер")
self.startButton.clicked.connect(self.startMoving)
self.layout.addWidget(self.startButton)
self.setLayout(self.layout)
def startPalletzing(self):
self.load_palletizing()
def startMoving(self):
self.start_moving()
def paintEvent(self, event):
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
super().paintEvent(event)

View File

@ -1,87 +0,0 @@
import time
from PyQt6.QtWidgets import (
QWidget,
QVBoxLayout,
QLabel,
QRadioButton,
QPushButton,
QButtonGroup,
)
from PyQt6.QtCore import Qt, QTimer
from logger import logger
class ChangeRobot(QWidget):
def __init__(self, robots, updateRobot, status):
super().__init__()
self.robots = robots or []
self.updateRobot = updateRobot
self.status = status
self.initUI()
self.old_status = None
self.counter = 0
self.timer = QTimer(self)
self.timer.timeout.connect(self.timerCallback)
def initUI(self):
self.layout = QVBoxLayout()
self.robotsLabel = QLabel("Выберите робота")
self.layout.addWidget(self.robotsLabel)
self.buttonGroup = QButtonGroup(self)
self.robotsRadio = []
for i, r in enumerate(self.robots):
radioButton = QRadioButton(r["name"])
self.buttonGroup.addButton(radioButton, i)
self.robotsRadio.append(radioButton)
self.layout.addWidget(radioButton)
self.connectButton = QPushButton("Соединить")
self.connectButton.clicked.connect(self.connectRobot)
self.layout.addWidget(self.connectButton)
self.setLayout(self.layout)
self.updateConnectButtonText()
def updateConnectButtonText(self):
radioState = True
if self.status() == "not_connected":
self.connectButton.setText("Соединить")
elif self.status() == "connected":
self.connectButton.setText("Отключить")
radioState = False
for radioButton in self.robotsRadio:
radioButton.setEnabled(radioState)
def timerCallback(self):
new_status = self.status()
self.counter += 1
if new_status == self.old_status and self.counter <= 10:
self.connectButton.setText(self.connectButton.text() + ".")
else:
self.old_status = None
self.timer.stop()
self.updateConnectButtonText()
def connectRobot(self):
self.updateConnectButtonText()
selectedId = self.buttonGroup.checkedId()
if selectedId == -1:
self.connectButton.setText("Выберите робота")
return
self.old_status = self.status()
self.timer.start(500)
time.sleep(0.3)
self.updateRobot(self.robots[selectedId])
def paintEvent(self, event):
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
super().paintEvent(event)

View File

@ -1,37 +0,0 @@
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication
from PyQt6.QtCore import QTimer, Qt
class Status(QWidget):
def __init__(self, status):
super().__init__()
self.status = status
# Инициализация пользовательского интерфейса
self.initUI()
# Таймер для обновления статуса
self.timer = QTimer(self)
self.timer.timeout.connect(self.updateStatus)
self.timer.start(1000) # Обновление каждые 1000 мс (1 секунда)
def initUI(self):
self.layout = QVBoxLayout()
# Создание метки для отображения статуса
self.statusLabel = QLabel(self.status())
self.layout.addWidget(self.statusLabel)
self.setLayout(self.layout)
self.setFixedHeight(100)
def paintEvent(self, event):
# Установка цвета фона
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.lightGray)
self.setPalette(p)
def updateStatus(self):
# Обновление текста метки статуса
self.statusLabel.setText(self.status())

View File

@ -1,53 +0,0 @@
import time
import numpy as np
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtCore import Qt, QTimer
from logger import logger
class Visualize(QWidget):
def __init__(self, get_pybullet_image):
super().__init__()
self.get_pybullet_image = get_pybullet_image
# Настройка компоновки
self.layout = QVBoxLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0) # Убираем отступы по краям
self.h_layout = QHBoxLayout()
self.h_layout.setContentsMargins(0, 0, 0, 0) # Убираем отступы по краям
self.label = QLabel(self)
self.layout.addWidget(self.label)
# Таймер для обновления изображения
self.timer = QTimer()
self.timer.timeout.connect(self.update_image)
self.timer.start(300)
def update_image(self):
res = self.get_pybullet_image()
if not res:
return
(rgb, width, height) = res
rgb_array = np.array(rgb, dtype=np.uint8)
bytesPerLine = 4 * width
# print(type(rgb))
image = QImage(rgb_array, width, height, bytesPerLine, QImage.Format.Format_RGBA8888).rgbSwapped()
image = image.convertToFormat(QImage.Format.Format_RGB888)
pixmap = QPixmap.fromImage(image)
self.label.setPixmap(pixmap)
self.label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
self.label.update()
def paintEvent(self, event):
p = self.palette()
p.setColor(self.backgroundRole(), Qt.GlobalColor.magenta)
self.setPalette(p)
super().paintEvent(event)

View File

@ -1,14 +0,0 @@
import sys
import logging
# Настройка логгера
logging.basicConfig(
level=logging.DEBUG, # Уровень логирования
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(filename)s - %(lineno)d",
handlers=[
logging.FileHandler("app.log"), # Запись в файл
logging.StreamHandler(sys.stdout), # Вывод в консоль
],
)
logger = logging.getLogger("logger")

202
main.py
View File

@ -1,202 +0,0 @@
import os
import sys
import glob
import json
import time
import argparse
import threading
from PyQt6.QtCore import QThread
from PyQt6.QtWidgets import QApplication
from robot.client_socket import SocketRobotArm
from gui.init import MainContentComponent
from logger import logger
class MyApp:
if getattr(sys, "frozen", False):
# Если приложение собрано в один файл
application_path = os.path.dirname(sys.executable)
else:
# Если приложение запускается как скрипт
application_path = os.path.dirname(os.path.abspath(__file__))
robots_json_path = os.path.join(application_path, "robots.json")
with open(robots_json_path, "r") as file:
robots = json.load(file)
robot_app = None
def __init__(self, mode):
self.mode = mode
self.startGui()
self.startRobot()
self.startWindow()
def startGui(self):
self.app = QApplication(sys.argv)
mainWindow = MainContentComponent(
get_status=self.get_status,
robotPanel={
"robots": self.robots,
"updateRobot": self.updateRobot,
"status": self.get_status,
},
statusPanel={
"status": self.get_status,
},
informerPanel={
"world_coord": self.get_world_coordinates,
"axis_coord": self.get_axis_coordinates,
"command_count": self.get_command_count,
"updateData": self.update_data_wrapper,
},
imitatorPanel={
"startImitate": self.imitate_wrapper,
"imitate_point": self.get_imitate_point,
},
commandPanel={
"startCommand": self.command_wrapper,
"changeType": self.change_type_wrapper,
"command_data": self.get_command_data,
"command_type": self.get_command_type,
},
visPanel={
"get_pybullet_image": self.get_pybullet_image_wrapper,
},
filenamePanel={
"files": self.get_data_files(),
"getFilename": self.get_filename,
"setFilename": self.set_filename,
},
palletizingPanel={
"load_palletizing": self.load_palletizing,
"start_moving": self.start_moving
},
)
mainWindow.setWindowTitle("ROBOT GUI")
self.window = mainWindow
def get_data_files(self):
files = glob.glob(f"{self.application_path}/data/*.nc.result")
return [os.path.basename(x) for x in files]
def startWindow(self):
self.window.show()
sys.exit(self.app.exec())
def startRobot(self):
self.robot_app = SocketRobotArm(application_path=self.application_path)
# Запускаем SocketRobotArm в отдельном потоке
threading.Thread(target=self.run_robot_arm, daemon=True).start()
def run_robot_arm(self):
time.sleep(1)
self.robot_app.start("SHARED_MEMORY")
def updateRobot(self, robot):
if robot in self.robots:
selected_robot = robot
if self.mode == "test":
robot["host"] = "127.0.0.1"
if self.robot_app.status == "connected":
self.robot_app.close()
time.sleep(0.3)
else:
self.robot_app.connect(
selected_robot["host"], selected_robot["slave_id"]
)
self.robot_app.start_loop(selected_robot["urdf"])
def check_robot_app(func):
def wrapper(self, *args, **kwargs):
if self.robot_app:
return func(self, *args, **kwargs)
else:
logger.info(f"robot_app еще не инициализирован. Метод: {func.__name__}")
return None # Или любое значение по умолчанию
return wrapper
@check_robot_app
def get_status(self):
return self.robot_app.get_status()
@check_robot_app
def get_world_coordinates(self):
return self.robot_app.world_coordinates
@check_robot_app
def get_axis_coordinates(self):
return self.robot_app.axis_coordinates
@check_robot_app
def get_command_count(self):
return self.robot_app.command_count
@check_robot_app
def get_command_data(self):
return self.robot_app.get_command_data()
@check_robot_app
def get_command_type(self):
return self.robot_app.get_command_type()
@check_robot_app
def get_imitate_point(self):
return self.robot_app.get_imitate_point()
@check_robot_app
def change_type_wrapper(self, type="base"):
return self.robot_app.set_command_type(type)
@check_robot_app
def command_wrapper(self, *args, **kwargs):
# logger.info(args)
# logger.info(kwargs)
return self.robot_app.cycle_start()
@check_robot_app
def imitate_wrapper(self, *args, **kwargs):
return self.robot_app.imitate()
@check_robot_app
def update_data_wrapper(self, *args, **kwargs):
return self.robot_app.upd_model()
@check_robot_app
def get_pybullet_image_wrapper(self):
return self.robot_app.get_pybullet_image()
@check_robot_app
def get_filename(self):
return self.robot_app.filename
@check_robot_app
def set_filename(self, filename):
self.robot_app.filename = filename
@check_robot_app
def load_palletizing(self):
return self.robot_app.load_palletizing()
@check_robot_app
def start_moving(self):
return self.robot_app.start_moving()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MyApp Command Line Interface")
parser.add_argument(
"--mode",
type=str,
choices=["test", "prod"],
default="prod",
help="Mode of operation",
)
# MyApp()
args = parser.parse_args()
app = MyApp(args.mode)

View File

@ -1,39 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=['.', './.venv', './.venv/Lib', './.venv/Lib/site-packages', 'robot/', 'gui/'],
binaries=[],
datas=[('robots.json', '.'), ('urdf', 'urdf'), ('data', 'data')],
hiddenimports=['numpy', 'libpython3.10'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
contents_directory='test',
)

View File

@ -1,45 +0,0 @@
from py3dbp import Packer, Bin, Item
from logger import logger
class PalletPacker:
def __init__(self, pallet: dict, box: dict):
self.pallet_width = pallet.get("x", 1.2)
self.pallet_height = pallet.get("y", 0.8)
self.pallet_depth = pallet.get("z", 0.144)
gap = 0
self.box_width = box.get("x", 0.2) + gap
self.box_height = box.get("y", 0.2) + gap
self.box_depth = box.get("z", 0.2)
def pack(self):
packer = Packer()
packer.add_bin(
Bin(
"pallet", self.pallet_width, self.pallet_height, self.pallet_depth, 1000
)
)
# Вычисляем, сколько коробок поместится на паллете в один слой
num_boxes_x = self.pallet_width // self.box_width
num_boxes_y = self.pallet_height // self.box_height
num_boxes = int(num_boxes_x * num_boxes_y)
# Добавляем коробки в пакер
for i in range(num_boxes):
packer.add_item(
Item(f"box{i}", self.box_width, self.box_height, self.box_depth, 1)
)
# Упаковываем коробки
packer.pack()
# Получаем результат
coordinates = []
for b in packer.bins:
for item in b.items:
coordinates.append([float(i) for i in item.position])
return coordinates

File diff suppressed because one or more lines are too long

View File

@ -1,969 +0,0 @@
[
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">pociya_1_korobki</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:1092.016,Y:417.880,Z:-297.773,U:-179.999,V:0.000,W:-90.004 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:None tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "pociya_1_korobki",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 12,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "1092.016",
"m1": "417.880",
"m2": "-297.773",
"m3": "-179.999",
"m4": "0.000",
"m5": "-90.004",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 12
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">po_odnoj_1korobka</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:1225.936,Y:417.871,Z:-297.768,U:-179.998,V:0.000,W:-90.006 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:None tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "po_odnoj_1korobka",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 19,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "1225.936",
"m1": "417.871",
"m2": "-297.768",
"m3": "-179.998",
"m4": "0.000",
"m5": "-90.006",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 19
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">free_poziciya</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:877.893,Y:-470.669,Z:1124.063,U:-180.000,V:-0.015,W:151.736 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:None tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "free_poziciya",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 1,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "877.893",
"m1": "-470.669",
"m2": "1124.063",
"m3": "-180.000",
"m4": "-0.015",
"m5": "151.736",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 1
},
{
"action": 4,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "startovaya_poziciya",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 2,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "-28.261",
"m1": "0.281",
"m2": "-2.815",
"m3": "0.000",
"m4": "-87.481",
"m5": "0.002",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
{
"action": 401,
"counterID": "0",
"customName": "ochischaem_schetchik",
"insertedIndex": 3
},
{
"action": 59999,
"comment": "start_cikla",
"customName": "nachalo_cikla_ukladki",
"flag": 0,
"insertedIndex": 4
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">u_konveera</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:685.097,Y:-1139.102,Z:205.713,U:-179.991,V:-0.002,W:179.468 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:None tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "u_konveera",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 4,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "685.097",
"m1": "-1139.102",
"m2": "205.713",
"m3": "-179.991",
"m4": "-0.002",
"m5": "179.468",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 5
},
{
"action": 4,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "podhod_k_konveeru",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 6,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "-59.023",
"m1": "-50.957",
"m2": "-0.568",
"m3": "-0.009",
"m4": "-38.466",
"m5": "-58.482",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">naezd_na_korobki</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:829.456,Y:-1139.107,Z:205.720,U:-179.989,V:0.000,W:179.464 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:None tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "naezd_na_korobki",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 5,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "829.456",
"m1": "-1139.107",
"m2": "205.720",
"m3": "-179.989",
"m4": "0.000",
"m5": "179.464",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 7
},
{
"action": 4,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "naezd_na_korobku",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 8,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "-53.983",
"m1": "-55.666",
"m2": "8.628",
"m3": "-0.009",
"m4": "-42.953",
"m5": "-53.440",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 0,
"speed": "50.0",
"toolCoord": 0
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">otriv_korobok_promezutochnaya</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:829.493,Y:-1139.102,Z:443.818,U:-179.987,V:0.002,W:179.461 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:9 tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "otriv_korobok_promezutochnaya",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 6,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "829.493",
"m1": "-1139.102",
"m2": "443.818",
"m3": "-179.987",
"m4": "0.002",
"m5": "179.461",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 9
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">start_na_paletu</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:829.539,Y:-775.127,Z:605.033,U:-179.979,V:-0.003,W:-89.998 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:9 tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "start_na_paletu",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 7,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "829.539",
"m1": "-775.127",
"m2": "605.033",
"m3": "-179.979",
"m4": "-0.003",
"m5": "-89.998",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 10
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:640.604,Y:-775.059,Z:1023.864,U:-179.946,V:0.000,W:-90.341 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V50.0 DLY0.000 Smooth:9 tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 28,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "640.604",
"m1": "-775.059",
"m2": "1023.864",
"m3": "-179.946",
"m4": "0.000",
"m5": "-90.341",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "50.0",
"toolCoord": 0
},
"insertedIndex": 11
},
{
"action": 4,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "podjem_korobki",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 12,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "-35.787",
"m1": "-6.346",
"m2": "-2.779",
"m3": "0.028",
"m4": "-80.826",
"m5": "-125.450",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "100.0",
"toolCoord": 0
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<font size=\"4\" color=\"green\">vozvrat_k_konveeru</font> Line3D-Pose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next:X:829.556,Y:-775.120,Z:605.066,U:179.571,V:-0.005,W:-152.101 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V100.0 DLY0.000 Smooth:9 tool:0:Null coord:0:Null ",
"commentAction": {
"action": 10,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "vozvrat_k_konveeru",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 13,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "829.556",
"m1": "-775.120",
"m2": "605.066",
"m3": "179.571",
"m4": "-0.005",
"m5": "-152.101",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "100.0",
"toolCoord": 0
},
"insertedIndex": 13
},
{
"action": 300,
"away_xoffset": "0.000",
"away_yoffset": "0.000",
"away_zoffset": "0.000",
"counterID": 0,
"customName": "plan_paletirovaniya",
"fullAlarm": 0,
"insertedIndex": 20,
"interval_always_out": 0,
"interval_en": 0,
"interval_number": "10",
"interval_out_choose": -1,
"interval_out_id": -1,
"interval_out_time": "1",
"intervalbox_always_out": 0,
"intervalbox_en": 0,
"intervalbox_number": "10",
"intervalbox_out_choose": 0,
"intervalbox_out_id": 0,
"intervalbox_out_time": "1",
"ls_xdir": 0,
"ls_ydir": 0,
"ls_zdir": 0,
"put_stack": true,
"ready_xoffset": 1,
"ready_yoffset": "0.000",
"ready_zoffset": "0.000",
"rs_xdir": 0,
"rs_ydir": 0,
"rs_zdir": 0,
"set_leave_point": 0,
"set_ready_point": 0,
"speed0": "80.0",
"speed1": "80.0",
"speedY": "80.0",
"speedZ": "80.0",
"stackID": "1",
"stack_delay": "0.0"
},
{
"actType": 1,
"action": 50,
"coord": "1",
"customName": "trans_points",
"delay": "0.00",
"insertedIndex": 21,
"pathAction": 10,
"pointType": 0,
"smooth": 9,
"speed": "80.0",
"stackId": "1",
"tool": "0"
},
{
"actType": 1,
"action": 50,
"coord": "1",
"customName": "ready_points",
"delay": "0.00",
"insertedIndex": 22,
"pathAction": 10,
"pointType": 1,
"smooth": 9,
"speed": "80.0",
"stackId": "1",
"tool": "0"
},
{
"actType": 1,
"action": 50,
"coord": "1",
"customName": "point_ukladki",
"delay": "0.00",
"insertedIndex": 23,
"pathAction": 10,
"pointType": 2,
"smooth": 0,
"speed": "80.0",
"stackId": "1",
"tool": "0"
},
{
"actType": 1,
"action": 50,
"coord": "1",
"customName": "othod_ot_ustanovlennoj_korobki",
"delay": "0.00",
"insertedIndex": 24,
"pathAction": 10,
"pointType": 3,
"smooth": 9,
"speed": "80.0",
"stackId": "1",
"tool": "0"
},
{
"action": 4,
"bindIOInfo": 0,
"ckStatus": "63",
"customName": "vozvrat_v_nachalnuyu_pozciu",
"delay": "0.000",
"distance": "0.000",
"insertedIndex": 14,
"passTrans": 0,
"points": [
{
"pointName": "",
"pos": {
"m0": "-62.233",
"m1": "-24.320",
"m2": "5.996",
"m3": "0.000",
"m4": "-71.666",
"m5": "-61.820",
"m6": "0.000",
"m7": "0.000"
}
}
],
"quotePoint": [
0,
0,
0
],
"relativeType": 0,
"smooth": 9,
"speed": "100.0",
"toolCoord": 0
},
{
"action": 400,
"counterID": "0",
"customName": "uvelichivaem_schetchik",
"insertedIndex": 15
},
{
"action": 10002,
"autoClear": false,
"compareID": 7,
"compareTarget": "10",
"counterID": 0,
"customName": "proveka_usloviya_cikla",
"flag": 0,
"insertedIndex": 16
},
{
"action": 50000,
"comment": "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cmd Set:Stop",
"commentAction": {
"action": 53000,
"addr": 98304,
"data": 2561,
"insertedIndex": 17,
"op": 0,
"specialType": 1,
"type": 0,
"typeSel": 1
},
"insertedIndex": 17
},
{
"action": 60000,
"insertedIndex": 18
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
]{
"0": {
"si0": {
"m0pos": "0",
"m1pos": "0",
"m2pos": "0",
"m3pos": "0",
"m4pos": "0",
"m5pos": "0",
"space0": "0",
"space1": "0",
"space2": "0",
"count0": "0",
"count1": "0",
"count2": "0",
"sequence": 0,
"dir0": 0,
"dir1": 0,
"dir2": 0,
"doesBindingCounter": true,
"counterID": 0,
"isOffsetEn": false,
"isZWithYEn": false,
"offsetX": "0",
"offsetY": "0",
"offsetZ": "0",
"dataSourceName": "Custom Pos",
"dataSourceID": "custompoint[0]",
"runSeq": 3,
"holdSel": 0,
"armSel": 0,
"coordinate": 1,
"tool": 0
},
"si1": {
"m0pos": "0",
"m1pos": "0",
"m2pos": "0",
"m3pos": "0",
"m4pos": "0",
"m5pos": "0",
"space0": "0",
"space1": "0",
"space2": "0",
"count0": "0",
"count1": "0",
"count2": "0",
"sequence": 0,
"dir0": 0,
"dir1": 0,
"dir2": 0,
"doesBindingCounter": true,
"counterID": 0,
"isOffsetEn": false,
"isZWithYEn": false,
"offsetX": "0",
"offsetY": "0",
"offsetZ": "0",
"dataSourceName": "Custom Pos",
"dataSourceID": "custompoint[0]",
"runSeq": 3,
"holdSel": 0,
"armSel": -1,
"coordinate": -1,
"tool": -1
},
"type": 7,
"descr": "scuko",
"dsName": "custompoint[0]",
"dsHostID": 0,
"posData": [
{
"pointName": 0,
"pointPos": {
"m0": 150,
"m1": "0.000",
"m2": "100.000",
"m3": 0,
"m4": 0,
"m5": 0
}
}
]
},
"1": {
"si0": {
"m0pos": "0",
"m1pos": "0",
"m2pos": "0",
"m3pos": "0",
"m4pos": "0",
"m5pos": "0",
"space0": "0",
"space1": "0",
"space2": "0",
"count0": "0",
"count1": "0",
"count2": "0",
"sequence": 0,
"dir0": 0,
"dir1": 0,
"dir2": 0,
"doesBindingCounter": true,
"counterID": 0,
"isOffsetEn": false,
"isZWithYEn": false,
"offsetX": "0",
"offsetY": "0",
"offsetZ": "0",
"dataSourceName": "Custom Pos",
"dataSourceID": "custompoint[1]",
"runSeq": 3,
"holdSel": 0,
"armSel": 0,
"coordinate": 1,
"tool": 0
},
"si1": {
"m0pos": "0",
"m1pos": "0",
"m2pos": "0",
"m3pos": "0",
"m4pos": "0",
"m5pos": "0",
"space0": "0",
"space1": "0",
"space2": "0",
"count0": "0",
"count1": "0",
"count2": "0",
"sequence": 0,
"dir0": 0,
"dir1": 0,
"dir2": 0,
"doesBindingCounter": true,
"counterID": 0,
"isOffsetEn": false,
"isZWithYEn": false,
"offsetX": "0",
"offsetY": "0",
"offsetZ": "0",
"dataSourceName": "Custom Pos",
"dataSourceID": "custompoint[1]",
"runSeq": 3,
"holdSel": 0,
"armSel": -1,
"coordinate": -1,
"tool": -1
},
"type": 7,
"descr": "padla",
"dsName": "custompoint[1]",
"dsHostID": 1,
"posData": [
{
"pointName": 0,
"pointPos": {
"m0": 170,
"m1": "0.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
},
{
"pointName": 1,
"pointPos": {
"m0": 170,
"m1": "200.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
},
{
"pointName": 2,
"pointPos": {
"m0": 170,
"m1": "200.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
},
{
"pointName": 3,
"pointPos": {
"m0": 170,
"m1": "200.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
},
{
"pointName": 4,
"pointPos": {
"m0": 170,
"m1": "200.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
},
{
"pointName": 5,
"pointPos": {
"m0": 170,
"m1": "200.000",
"m2": "200.000",
"m3": 0,
"m4": 0,
"m5": 0
}
}
]
}
}[][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
][
{
"action": 60000,
"insertedIndex": 0
}
]

682
poetry.lock generated
View File

@ -1,361 +1,258 @@
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "numpy"
version = "1.26.4"
description = "Fundamental package for array computing in Python"
name = "attrs"
version = "24.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.9"
python-versions = ">=3.7"
files = [
{file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"},
{file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"},
{file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"},
{file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"},
{file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"},
{file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"},
{file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"},
{file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"},
{file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"},
{file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"},
{file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"},
{file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"},
{file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"},
{file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"},
{file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"},
{file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"},
{file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"},
{file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"},
{file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"},
{file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"},
{file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"},
{file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"},
{file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"},
{file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"},
{file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"},
{file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"},
{file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"},
{file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"},
{file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"},
{file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"},
{file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"},
{file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"},
{file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"},
{file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"},
{file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"},
{file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"},
]
[[package]]
name = "pillow"
version = "11.0.0"
description = "Python Imaging Library (Fork)"
optional = false
python-versions = ">=3.9"
files = [
{file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"},
{file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"},
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"},
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"},
{file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"},
{file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"},
{file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"},
{file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"},
{file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"},
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"},
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"},
{file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"},
{file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"},
{file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"},
{file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"},
{file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"},
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"},
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"},
{file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"},
{file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"},
{file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"},
{file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"},
{file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"},
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"},
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"},
{file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"},
{file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"},
{file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"},
{file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"},
{file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"},
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"},
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"},
{file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"},
{file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"},
{file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"},
{file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"},
{file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"},
{file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"},
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"},
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"},
{file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"},
{file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"},
{file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"},
{file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"},
{file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"},
{file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
fpx = ["olefile"]
mic = ["olefile"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
typing = ["typing-extensions"]
xmp = ["defusedxml"]
benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
[[package]]
name = "popsicle"
version = "0.9.6"
description = "popsicle: Python integration for JUCE with pybind11."
name = "automat"
version = "22.10.0"
description = "Self-service finite-state machines for the programmer on the go."
optional = false
python-versions = ">=3.10"
python-versions = "*"
files = [
{file = "popsicle-0.9.6-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:0abedd3790cfe63b14ac3aa46263993e8d859b2c1f769dad8e8685d9995e8e2e"},
{file = "popsicle-0.9.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10ef070c120e782d852eb47a55a187cf7276e8a759110bbbec713e5bbd0faf6a"},
{file = "popsicle-0.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2d51bd173da55f84aec6c2a3b5c4b8c0ac3742491a20110531fcc3a3f308bc"},
{file = "popsicle-0.9.6-cp310-cp310-win_amd64.whl", hash = "sha256:c55c6f840269a49b395626ce600c65078aeeda8c727d305d1dca7bded5cf587b"},
{file = "popsicle-0.9.6-cp310-cp310-win_arm64.whl", hash = "sha256:1e22ffb9aca2b468915d7c4b5bd7ce82cdf52ce86e1f4d54eacf6a033dd13c98"},
{file = "popsicle-0.9.6-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d013f08cfd2c491d3f4a35b6477592bd58ece3d59c37a513b6d1e620f50145f1"},
{file = "popsicle-0.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cafbace5fb0df51aac0336cce47fc5208335c43670a103d1a7f8ee0f3094f118"},
{file = "popsicle-0.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95063399a42258b56b469ae31a380d6c2ddb4ab01d729a52300ee3e55ecececb"},
{file = "popsicle-0.9.6-cp311-cp311-win_amd64.whl", hash = "sha256:f30b6309b015f3a26a461223c19d7c8f962f42868575af076f15f71f53b58496"},
{file = "popsicle-0.9.6-cp311-cp311-win_arm64.whl", hash = "sha256:0d0eafff83b08b6ada954e897a0e07b17f6994398c1860a5a9560af402c8f6e9"},
{file = "popsicle-0.9.6-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:a42d53580ddbaca15e64e34c4971f83a862a95c5e50d3e1be5b127c4ff056e48"},
{file = "popsicle-0.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4429eeee549cf340b3bcc60e7244881b08b8357aeafc88a2a9aee9dd1e3b9fc1"},
{file = "popsicle-0.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11de3ccfb5a8f422f1532aaca835ab6907affcbf91ff45312ebcb1d424b4723f"},
{file = "popsicle-0.9.6-cp312-cp312-win_amd64.whl", hash = "sha256:ce7f79069151860a1bd43ba50e786d57c8db3e2f6e8538db45bb0ac67adba7f6"},
{file = "popsicle-0.9.6-cp312-cp312-win_arm64.whl", hash = "sha256:c40d8301b08690b041ed5710f0e9a63bf83c48ab51f5cf015b6fb7cf95921744"},
{file = "Automat-22.10.0-py2.py3-none-any.whl", hash = "sha256:c3164f8742b9dc440f3682482d32aaff7bb53f71740dd018533f9de286b64180"},
{file = "Automat-22.10.0.tar.gz", hash = "sha256:e56beb84edad19dcc11d30e8d9b895f75deeb5ef5e96b84a467066b3b84bb04e"},
]
[[package]]
name = "psutil"
version = "6.1.0"
description = "Cross-platform lib for process and system monitoring in Python."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
{file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"},
{file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"},
{file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"},
{file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"},
{file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"},
{file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"},
{file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"},
{file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"},
{file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"},
{file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"},
{file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"},
{file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"},
{file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"},
{file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"},
{file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"},
{file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"},
{file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"},
]
[package.dependencies]
attrs = ">=19.2.0"
six = "*"
[package.extras]
dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"]
test = ["pytest", "pytest-xdist", "setuptools"]
visualize = ["Twisted (>=16.1.1)", "graphviz (>0.5.1)"]
[[package]]
name = "py3dbp"
version = "1.1.2"
description = "3D Bin Packing"
name = "constantly"
version = "23.10.4"
description = "Symbolic constants in Python"
optional = false
python-versions = "*"
python-versions = ">=3.8"
files = [
{file = "py3dbp-1.1.2.tar.gz", hash = "sha256:d8c92c120eecfbee600a4dfd8b0a42d63459c97de67a26ff8ad39529a5125e07"},
{file = "constantly-23.10.4-py3-none-any.whl", hash = "sha256:3fd9b4d1c3dc1ec9757f3c52aef7e53ad9323dbe39f51dfd4c43853b68dfa3f9"},
{file = "constantly-23.10.4.tar.gz", hash = "sha256:aa92b70a33e2ac0bb33cd745eb61776594dc48764b06c35e0efd050b7f1c7cbd"},
]
[[package]]
name = "pybullet"
version = "3.2.6"
description = "Official Python Interface for the Bullet Physics SDK specialized for Robotics Simulation and Reinforcement Learning"
name = "hyperlink"
version = "21.0.0"
description = "A featureful, immutable, and correct URL for Python."
optional = false
python-versions = "*"
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pybullet-3.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f71d0bed6824875b521066571d612274f1d2dead3ede50f8fbdde1946ec0c40"},
{file = "pybullet-3.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a476d51726efa7aabe1dc8c4ee676b78bcd9fc19d4a2ce9776f2c9a9dacd9e8b"},
{file = "pybullet-3.2.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8af791050e927f407a85fa9de15754fbe0973f8c798fd2893773b52fa1fc70e0"},
{file = "pybullet-3.2.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72be1e68c61bbe49af5b7c609d59ede92d3fbbfca072e9b31d4819575c8f332b"},
{file = "pybullet-3.2.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba46f9d8ae76d2bcae4bf4b5768b1dccc0b3b15110b69ba3d78cd0b11f8f21cf"},
{file = "pybullet-3.2.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f928444471186c5d6092d71371b03436e23ec96acd7800dfefcd8e96572c6581"},
{file = "pybullet-3.2.6.tar.gz", hash = "sha256:da27525433c88698dc9fd8bc20fa4ae4d07738b4656633659ebd82c2d2884e08"},
{file = "hyperlink-21.0.0-py2.py3-none-any.whl", hash = "sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4"},
{file = "hyperlink-21.0.0.tar.gz", hash = "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b"},
]
[package.dependencies]
idna = ">=2.5"
[[package]]
name = "idna"
version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
name = "pybullet-industrial"
version = "1.0.3"
description = "Pybullet_industrial is a process-aware robot simulation framework for pybullet."
name = "incremental"
version = "24.7.2"
description = "A small library that versions your Python projects."
optional = false
python-versions = ">=3.8"
files = [
{file = "incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe"},
{file = "incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9"},
]
[package.dependencies]
setuptools = ">=61.0"
tomli = {version = "*", markers = "python_version < \"3.11\""}
[package.extras]
scripts = ["click (>=6.0)"]
[[package]]
name = "modbus"
version = "3.2"
description = "Modbus TCP Server and Client Programs"
optional = false
python-versions = "*"
files = [
{file = "pybullet_industrial-1.0.3-py3-none-any.whl", hash = "sha256:826db59d9451e360aa92470e4df7afceb09500bca391cfb136753cfc87beed53"},
{file = "pybullet_industrial-1.0.3.tar.gz", hash = "sha256:b7a3f263e305ce269ec3bd464106f03886a13c29da5eb5de35e0980c7d9ac8da"},
{file = "modbus-3.2.tar.gz", hash = "sha256:f4cd6efa24e7e2c5295672467722c2ed32faec7f43bbc1cabafe8a9f521439f2"},
]
[package.dependencies]
numpy = "*"
pybullet = "*"
scipy = "*"
[[package]]
name = "numpy"
version = "2.0.1"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [
{file = "numpy-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fbb536eac80e27a2793ffd787895242b7f18ef792563d742c2d673bfcb75134"},
{file = "numpy-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:69ff563d43c69b1baba77af455dd0a839df8d25e8590e79c90fcbe1499ebde42"},
{file = "numpy-2.0.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:1b902ce0e0a5bb7704556a217c4f63a7974f8f43e090aff03fcf262e0b135e02"},
{file = "numpy-2.0.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:f1659887361a7151f89e79b276ed8dff3d75877df906328f14d8bb40bb4f5101"},
{file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4658c398d65d1b25e1760de3157011a80375da861709abd7cef3bad65d6543f9"},
{file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4127d4303b9ac9f94ca0441138acead39928938660ca58329fe156f84b9f3015"},
{file = "numpy-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e5eeca8067ad04bc8a2a8731183d51d7cbaac66d86085d5f4766ee6bf19c7f87"},
{file = "numpy-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9adbd9bb520c866e1bfd7e10e1880a1f7749f1f6e5017686a5fbb9b72cf69f82"},
{file = "numpy-2.0.1-cp310-cp310-win32.whl", hash = "sha256:7b9853803278db3bdcc6cd5beca37815b133e9e77ff3d4733c247414e78eb8d1"},
{file = "numpy-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81b0893a39bc5b865b8bf89e9ad7807e16717f19868e9d234bdaf9b1f1393868"},
{file = "numpy-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75b4e316c5902d8163ef9d423b1c3f2f6252226d1aa5cd8a0a03a7d01ffc6268"},
{file = "numpy-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6e4eeb6eb2fced786e32e6d8df9e755ce5be920d17f7ce00bc38fcde8ccdbf9e"},
{file = "numpy-2.0.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a1e01dcaab205fbece13c1410253a9eea1b1c9b61d237b6fa59bcc46e8e89343"},
{file = "numpy-2.0.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8fc2de81ad835d999113ddf87d1ea2b0f4704cbd947c948d2f5513deafe5a7b"},
{file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a3d94942c331dd4e0e1147f7a8699a4aa47dffc11bf8a1523c12af8b2e91bbe"},
{file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15eb4eca47d36ec3f78cde0a3a2ee24cf05ca7396ef808dda2c0ddad7c2bde67"},
{file = "numpy-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b83e16a5511d1b1f8a88cbabb1a6f6a499f82c062a4251892d9ad5d609863fb7"},
{file = "numpy-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f87fec1f9bc1efd23f4227becff04bd0e979e23ca50cc92ec88b38489db3b55"},
{file = "numpy-2.0.1-cp311-cp311-win32.whl", hash = "sha256:36d3a9405fd7c511804dc56fc32974fa5533bdeb3cd1604d6b8ff1d292b819c4"},
{file = "numpy-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8"},
{file = "numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac"},
{file = "numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4"},
{file = "numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1"},
{file = "numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587"},
{file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8"},
{file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a"},
{file = "numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7"},
{file = "numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b"},
{file = "numpy-2.0.1-cp312-cp312-win32.whl", hash = "sha256:173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf"},
{file = "numpy-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171"},
{file = "numpy-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfc085b28d62ff4009364e7ca34b80a9a080cbd97c2c0630bb5f7f770dae9414"},
{file = "numpy-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fae4ebbf95a179c1156fab0b142b74e4ba4204c87bde8d3d8b6f9c34c5825ef"},
{file = "numpy-2.0.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:72dc22e9ec8f6eaa206deb1b1355eb2e253899d7347f5e2fae5f0af613741d06"},
{file = "numpy-2.0.1-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:ec87f5f8aca726117a1c9b7083e7656a9d0d606eec7299cc067bb83d26f16e0c"},
{file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f682ea61a88479d9498bf2091fdcd722b090724b08b31d63e022adc063bad59"},
{file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8efc84f01c1cd7e34b3fb310183e72fcdf55293ee736d679b6d35b35d80bba26"},
{file = "numpy-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3fdabe3e2a52bc4eff8dc7a5044342f8bd9f11ef0934fcd3289a788c0eb10018"},
{file = "numpy-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:24a0e1befbfa14615b49ba9659d3d8818a0f4d8a1c5822af8696706fbda7310c"},
{file = "numpy-2.0.1-cp39-cp39-win32.whl", hash = "sha256:f9cf5ea551aec449206954b075db819f52adc1638d46a6738253a712d553c7b4"},
{file = "numpy-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:e9e81fa9017eaa416c056e5d9e71be93d05e2c3c2ab308d23307a8bc4443c368"},
{file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61728fba1e464f789b11deb78a57805c70b2ed02343560456190d0501ba37b0f"},
{file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:12f5d865d60fb9734e60a60f1d5afa6d962d8d4467c120a1c0cda6eb2964437d"},
{file = "numpy-2.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eacf3291e263d5a67d8c1a581a8ebbcfd6447204ef58828caf69a5e3e8c75990"},
{file = "numpy-2.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2c3a346ae20cfd80b6cfd3e60dc179963ef2ea58da5ec074fd3d9e7a1e7ba97f"},
{file = "numpy-2.0.1.tar.gz", hash = "sha256:485b87235796410c3519a699cfe1faab097e509e90ebb05dcd098db2ae87e7b3"},
]
[[package]]
name = "pymodbus"
version = "3.7.4"
version = "3.7.0"
description = "A fully featured modbus protocol stack in python"
optional = false
python-versions = ">=3.9.0"
files = [
{file = "pymodbus-3.7.4-py3-none-any.whl", hash = "sha256:dfb45ef9a2c1663875ad32378f780b5824628cd3c0a486851e64b8a3341a3e82"},
{file = "pymodbus-3.7.4.tar.gz", hash = "sha256:573c370aea04523403eea1e159616a583cd7b93cfc5c81b07340d3cccd52c99f"},
{file = "pymodbus-3.7.0-py3-none-any.whl", hash = "sha256:4d4caedea604e294d9a39248dcac05e903e6143e5adfe49aa7edb79d461527e1"},
{file = "pymodbus-3.7.0.tar.gz", hash = "sha256:5c772babaa61a65ff908293faa668aedcd9d9e10f4bcf5c77a8fe51a6fd9ed47"},
]
[package.extras]
all = ["pymodbus[development,documentation,repl,serial,simulator]"]
development = ["build (>=1.2.2)", "codespell (>=2.3.0)", "coverage (>=7.6.1)", "mypy (>=1.11.2)", "pylint (>=3.3.0)", "pytest (>=8.3.3)", "pytest-aiohttp (>=1.0.5)", "pytest-asyncio (>=0.24.0)", "pytest-cov (>=5.0.0)", "pytest-profiling (>=1.7.0)", "pytest-timeout (>=2.3.1)", "pytest-xdist (>=3.6.1)", "ruff (>=0.5.3)", "twine (>=5.1.1)", "types-Pygments", "types-pyserial"]
development = ["build (>=1.2.1)", "codespell (>=2.3.0)", "coverage (>=7.6.0)", "mypy (>=1.10.1)", "pylint (>=3.2.5)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.8)", "pytest-cov (>=5.0.0)", "pytest-profiling (>=1.7.0)", "pytest-timeout (>=2.3.1)", "pytest-xdist (>=3.6.1)", "ruff (>=0.5.3)", "twine (>=5.1.1)", "types-Pygments", "types-pyserial"]
documentation = ["Sphinx (>=7.3.7)", "recommonmark (>=0.7.1)", "sphinx-rtd-theme (>=2.0.0)"]
repl = ["pymodbus-repl (>=2.0.4)"]
repl = ["pymodbus-repl (>=2.0.3)"]
serial = ["pyserial (>=3.5)"]
simulator = ["aiohttp (>=3.10.5)", "aiohttp (>=3.8.6)"]
simulator = ["aiohttp (>=3.8.6)", "aiohttp (>=3.9.5)"]
[[package]]
name = "pyqt6"
version = "6.7.1"
description = "Python bindings for the Qt cross platform application toolkit"
optional = false
python-versions = ">=3.8"
files = [
{file = "PyQt6-6.7.1-1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7f397f4b38b23b5588eb2c0933510deb953d96b1f0323a916c4839c2a66ccccc"},
{file = "PyQt6-6.7.1-1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2f202b7941aa74e5c7e1463a6f27d9131dbc1e6cabe85571d7364f5b3de7397"},
{file = "PyQt6-6.7.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:f053378e3aef6248fa612c8afddda17f942fb63f9fe8a9aeb2a6b6b4cbb0eba9"},
{file = "PyQt6-6.7.1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0adb7914c732ad1dee46d9cec838a98cb2b11bc38cc3b7b36fbd8701ae64bf47"},
{file = "PyQt6-6.7.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2d771fa0981514cb1ee937633dfa64f14caa902707d9afffab66677f3a73e3da"},
{file = "PyQt6-6.7.1-cp38-abi3-win_amd64.whl", hash = "sha256:fa3954698233fe286a8afc477b84d8517f0788eb46b74da69d3ccc0170d3714c"},
{file = "PyQt6-6.7.1.tar.gz", hash = "sha256:3672a82ccd3a62e99ab200a13903421e2928e399fda25ced98d140313ad59cb9"},
]
[package.dependencies]
PyQt6-Qt6 = ">=6.7.0,<6.8.0"
PyQt6-sip = ">=13.8,<14"
[[package]]
name = "pyqt6-qt6"
version = "6.7.3"
description = "The subset of a Qt installation needed by PyQt6."
name = "pymodbus3"
version = "1.0.0"
description = "A fully featured modbus protocol stack in python"
optional = false
python-versions = "*"
files = [
{file = "PyQt6_Qt6-6.7.3-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:f517a93b6b1a814d4aa6587adc312e812ebaf4d70415bb15cfb44268c5ad3f5f"},
{file = "PyQt6_Qt6-6.7.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8551732984fb36a5f4f3db51eafc4e8e6caf18617365830285306f2db17a94c2"},
{file = "PyQt6_Qt6-6.7.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:50c7482bcdcf2bb78af257fb10ed8b582f8daf91d829782393bc50ac5a0a900c"},
{file = "PyQt6_Qt6-6.7.3-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:cb525fdd393332de60887953029276a44de480fce1d785251ae639580f5e7246"},
{file = "PyQt6_Qt6-6.7.3-py3-none-win_amd64.whl", hash = "sha256:36ea0892b8caeb983af3f285f45fb8dfbb93cfd972439f4e01b7efb2868f6230"},
{file = "pymodbus3-1.0.0.tar.gz", hash = "sha256:4a340660a5e56a8f2f945e650b00b78c0bfce05911140338101b37d3b9ed3f8c"},
]
[package.dependencies]
pyserial = ">=2.6"
twisted = ">=12.2.0"
[package.extras]
documents = ["sphinx (>=1.1.3)"]
quality = ["coverage (>=3.5.3)", "mock (>=1.0.0)", "nose (>=1.2.1)", "pep8 (>=1.3.3)"]
twisted = ["pyasn1 (>=0.1.4)", "pycrypto (>=2.6)"]
[[package]]
name = "pymodbustcp"
version = "0.2.2"
description = "A simple Modbus/TCP library for Python"
optional = false
python-versions = "*"
files = [
{file = "pyModbusTCP-0.2.2-py3-none-any.whl", hash = "sha256:6f018792c891b725da99d978c7d156c71340fa26d389d22310f99bf5829ce773"},
{file = "pyModbusTCP-0.2.2.tar.gz", hash = "sha256:30ed8bdba98ef8c423aa8421be454d5079fd5952ef78557f287ec263c57b5ba6"},
]
[[package]]
name = "pyqt6-sip"
version = "13.8.0"
description = "The sip module support for PyQt6"
name = "pyserial"
version = "3.5"
description = "Python Serial Port Extension"
optional = false
python-versions = ">=3.8"
python-versions = "*"
files = [
{file = "PyQt6_sip-13.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cedd554c643e54c4c2e12b5874781a87441a1b405acf3650a4a2e1df42aae231"},
{file = "PyQt6_sip-13.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f57275b5af774529f9838adcfb58869ba3ebdaf805daea113bb0697a96a3f3cb"},
{file = "PyQt6_sip-13.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:835ed22eab977f75fd77e60d4ff308a1fa794b1d0c04849311f36d2a080cdf3b"},
{file = "PyQt6_sip-13.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d8b22a6850917c68ce83fc152a8b606ecb2efaaeed35be53110468885d6cdd9d"},
{file = "PyQt6_sip-13.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b203b6fbae4a8f2d27f35b7df46200057033d9ecd9134bcf30e3eab66d43572c"},
{file = "PyQt6_sip-13.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:beaddc1ec96b342f4e239702f91802706a80cb403166c2da318cec4ad8b790cb"},
{file = "PyQt6_sip-13.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5c086b7c9c7996ea9b7522646cc24eebbf3591ec9dd38f65c0a3fdb0dbeaac7"},
{file = "PyQt6_sip-13.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:dd168667addf01f8a4b0fa7755323e43e4cd12ca4bade558c61f713a5d48ba1a"},
{file = "PyQt6_sip-13.8.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:33d9b399fc9c9dc99496266842b0fb2735d924604774e97cf9b555667cc0fc59"},
{file = "PyQt6_sip-13.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:056af69d1d8d28d5968066ec5da908afd82fc0be07b67cf2b84b9f02228416ce"},
{file = "PyQt6_sip-13.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:08dd81037a2864982ece2bf9891f3bf4558e247034e112993ea1a3fe239458cb"},
{file = "PyQt6_sip-13.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:fbb249b82c53180f1420571ece5dc24fea1188ba435923edd055599dffe7abfb"},
{file = "PyQt6_sip-13.8.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:6bce6bc5870d9e87efe5338b1ee4a7b9d7d26cdd16a79a5757d80b6f25e71edc"},
{file = "PyQt6_sip-13.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd81144b0770084e8005d3a121c9382e6f9bc8d0bb320dd618718ffe5090e0e6"},
{file = "PyQt6_sip-13.8.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:755beb5d271d081e56618fb30342cdd901464f721450495cb7cb0212764da89e"},
{file = "PyQt6_sip-13.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a0bbc0918eab5b6351735d40cf22cbfa5aa2476b55e0d5fe881aeed7d871c29"},
{file = "PyQt6_sip-13.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7f84c472afdc7d316ff683f63129350d645ef82d9b3fd75a609b08472d1f7291"},
{file = "PyQt6_sip-13.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1bf29e95f10a8a00819dac804ca7e5eba5fc1769adcd74c837c11477bf81954"},
{file = "PyQt6_sip-13.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9ea9223c94906efd68148f12ae45b51a21d67e86704225ddc92bce9c54e4d93c"},
{file = "PyQt6_sip-13.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:2559afa68825d08de09d71c42f3b6ad839dcc30f91e7c6d0785e07830d5541a5"},
{file = "PyQt6_sip-13.8.0.tar.gz", hash = "sha256:2f74cf3d6d9cab5152bd9f49d570b2dfb87553ebb5c4919abfde27f5b9fd69d4"},
{file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"},
{file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"},
]
[package.extras]
cp2110 = ["hidapi"]
[[package]]
name = "scipy"
version = "1.14.1"
version = "1.14.0"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.10"
files = [
{file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"},
{file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"},
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"},
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"},
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"},
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"},
{file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"},
{file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"},
{file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"},
{file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"},
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"},
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"},
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"},
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"},
{file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"},
{file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"},
{file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"},
{file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"},
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"},
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"},
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"},
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"},
{file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"},
{file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"},
{file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"},
{file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"},
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"},
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"},
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"},
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"},
{file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"},
{file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"},
{file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"},
{file = "scipy-1.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7e911933d54ead4d557c02402710c2396529540b81dd554fc1ba270eb7308484"},
{file = "scipy-1.14.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:687af0a35462402dd851726295c1a5ae5f987bd6e9026f52e9505994e2f84ef6"},
{file = "scipy-1.14.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:07e179dc0205a50721022344fb85074f772eadbda1e1b3eecdc483f8033709b7"},
{file = "scipy-1.14.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:6a9c9a9b226d9a21e0a208bdb024c3982932e43811b62d202aaf1bb59af264b1"},
{file = "scipy-1.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076c27284c768b84a45dcf2e914d4000aac537da74236a0d45d82c6fa4b7b3c0"},
{file = "scipy-1.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42470ea0195336df319741e230626b6225a740fd9dce9642ca13e98f667047c0"},
{file = "scipy-1.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:176c6f0d0470a32f1b2efaf40c3d37a24876cebf447498a4cefb947a79c21e9d"},
{file = "scipy-1.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:ad36af9626d27a4326c8e884917b7ec321d8a1841cd6dacc67d2a9e90c2f0359"},
{file = "scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e"},
{file = "scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb"},
{file = "scipy-1.14.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:94c164a9e2498e68308e6e148646e486d979f7fcdb8b4cf34b5441894bdb9caf"},
{file = "scipy-1.14.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a7d46c3e0aea5c064e734c3eac5cf9eb1f8c4ceee756262f2c7327c4c2691c86"},
{file = "scipy-1.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eee2989868e274aae26125345584254d97c56194c072ed96cb433f32f692ed8"},
{file = "scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74"},
{file = "scipy-1.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c40003d880f39c11c1edbae8144e3813904b10514cd3d3d00c277ae996488cdb"},
{file = "scipy-1.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc"},
{file = "scipy-1.14.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff2438ea1330e06e53c424893ec0072640dac00f29c6a43a575cbae4c99b2b9"},
{file = "scipy-1.14.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bbc0471b5f22c11c389075d091d3885693fd3f5e9a54ce051b46308bc787e5d4"},
{file = "scipy-1.14.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:64b2ff514a98cf2bb734a9f90d32dc89dc6ad4a4a36a312cd0d6327170339eb0"},
{file = "scipy-1.14.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:7d3da42fbbbb860211a811782504f38ae7aaec9de8764a9bef6b262de7a2b50f"},
{file = "scipy-1.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d91db2c41dd6c20646af280355d41dfa1ec7eead235642178bd57635a3f82209"},
{file = "scipy-1.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a01cc03bcdc777c9da3cfdcc74b5a75caffb48a6c39c8450a9a05f82c4250a14"},
{file = "scipy-1.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:65df4da3c12a2bb9ad52b86b4dcf46813e869afb006e58be0f516bc370165159"},
{file = "scipy-1.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:4c4161597c75043f7154238ef419c29a64ac4a7c889d588ea77690ac4d0d9b20"},
{file = "scipy-1.14.0.tar.gz", hash = "sha256:b5923f48cb840380f9854339176ef21763118a7300a88203ccd0bdd26e58527b"},
]
[package.dependencies]
@ -363,28 +260,62 @@ numpy = ">=1.23.5,<2.3"
[package.extras]
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"]
test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"]
test = ["Cython", "array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
[[package]]
name = "setuptools"
version = "75.4.0"
version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.9"
python-versions = ">=3.8"
files = [
{file = "setuptools-75.4.0-py3-none-any.whl", hash = "sha256:b3c5d862f98500b06ffdf7cc4499b48c46c317d8d56cb30b5c8bce4d88f5c216"},
{file = "setuptools-75.4.0.tar.gz", hash = "sha256:1dc484f5cf56fd3fe7216d7b8df820802e7246cfb534a1db2aa64f14fcb9cdcb"},
{file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
{file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
enabler = ["pytest-enabler (>=2.2)"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
[[package]]
name = "svgpathtools"
version = "1.6.1"
description = "A collection of tools for manipulating and analyzing SVG Path objects and Bezier curves."
optional = false
python-versions = "*"
files = [
{file = "svgpathtools-1.6.1-py2.py3-none-any.whl", hash = "sha256:39967f9a817b8a12cc6dd1646fc162d522fca6c3fd5f8c94913c15ee4cb3a906"},
{file = "svgpathtools-1.6.1.tar.gz", hash = "sha256:7054e6de1953e295bf565d535d585695453b09f8db4a2f7c4853348732097a3e"},
]
[package.dependencies]
numpy = "*"
scipy = "*"
svgwrite = "*"
[[package]]
name = "svgwrite"
version = "1.4.3"
description = "A Python library to create SVG drawings."
optional = false
python-versions = ">=3.6"
files = [
{file = "svgwrite-1.4.3-py3-none-any.whl", hash = "sha256:bb6b2b5450f1edbfa597d924f9ac2dd099e625562e492021d7dd614f65f8a22d"},
{file = "svgwrite-1.4.3.zip", hash = "sha256:a8fbdfd4443302a6619a7f76bc937fc683daf2628d9b737c891ec08b8ce524c3"},
]
[[package]]
name = "tk"
@ -397,7 +328,144 @@ files = [
{file = "tk-0.1.0.tar.gz", hash = "sha256:60bc8923d5d35f67f5c6bd93d4f0c49d2048114ec077768f959aef36d4ed97f8"},
]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]]
name = "twisted"
version = "24.3.0"
description = "An asynchronous networking framework written in Python"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "twisted-24.3.0-py3-none-any.whl", hash = "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63"},
{file = "twisted-24.3.0.tar.gz", hash = "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae"},
]
[package.dependencies]
attrs = ">=21.3.0"
automat = ">=0.8.0"
constantly = ">=15.1"
hyperlink = ">=17.1.1"
incremental = ">=22.10.0"
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
typing-extensions = ">=4.2.0"
zope-interface = ">=5"
[package.extras]
all-non-platform = ["twisted[conch,http2,serial,test,tls]", "twisted[conch,http2,serial,test,tls]"]
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
mypy = ["mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
windows-platform = ["pywin32 (!=226)", "pywin32 (!=226)", "twisted[all-non-platform]", "twisted[all-non-platform]"]
[[package]]
name = "twisted-iocpsupport"
version = "1.0.4"
description = "An extension for use in the twisted I/O Completion Ports reactor."
optional = false
python-versions = "*"
files = [
{file = "twisted-iocpsupport-1.0.4.tar.gz", hash = "sha256:858096c0d15e33f15ac157f455d8f86f2f2cdd223963e58c0f682a3af8362d89"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win32.whl", hash = "sha256:afa2b630797f9ed2f27f3d9f55e3f72b4244911e45a8c82756f44babbf0b243e"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:0058c963c8957bcd3deda62122e89953c9de1e867a274facc9b15dde1a9f31e8"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win32.whl", hash = "sha256:196f7c7ccad4ba4d1783b1c4e1d1b22d93c04275cd780bf7498d16c77319ad6e"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:4e5f97bcbabdd79cbaa969b63439b89801ea560f11d42b0a387634275c633623"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win32.whl", hash = "sha256:6081bd7c2f4fcf9b383dcdb3b3385d75a26a7c9d2be25b6950c3d8ea652d2d2d"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:76f7e67cec1f1d097d1f4ed7de41be3d74546e1a4ede0c7d56e775c4dce5dfb0"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:3d306fc4d88a6bcf61ce9d572c738b918578121bfd72891625fab314549024b5"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:391ac4d6002a80e15f35adc4ad6056f4fe1c17ceb0d1f98ba01b0f4f917adfd7"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:0c1b5cf37f0b2d96cc3c9bc86fff16613b9f5d0ca565c96cf1f1fb8cfca4b81c"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:3c5dc11d72519e55f727320e3cee535feedfaee09c0f0765ed1ca7badff1ab3c"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win32.whl", hash = "sha256:cc86c2ef598c15d824a243c2541c29459881c67fc3c0adb6efe2242f8f0ec3af"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c27985e949b9b1a1fb4c20c71d315c10ea0f93fdf3ccdd4a8c158b5926edd8c8"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win32.whl", hash = "sha256:e311dfcb470696e3c077249615893cada598e62fa7c4e4ca090167bd2b7d331f"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4574eef1f3bb81501fb02f911298af3c02fe8179c31a33b361dd49180c3e644d"},
{file = "twisted_iocpsupport-1.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:872747a3b64e2909aee59c803ccd0bceb9b75bf27915520ebd32d69687040fa2"},
{file = "twisted_iocpsupport-1.0.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c2712b778bacf1db434e3e065adfed3db300754186a29aecac1efae9ef4bcaff"},
{file = "twisted_iocpsupport-1.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7c66fa0aa4236b27b3c61cb488662d85dae746a6d1c7b0d91cf7aae118445adf"},
{file = "twisted_iocpsupport-1.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:300437af17396a945a58dcfffd77863303a8b6d9e65c6e81f1d2eed55b50d444"},
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "zope-interface"
version = "7.0.1"
description = "Interfaces for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "zope.interface-7.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ec4e87e6fdc511a535254daa122c20e11959ce043b4e3425494b237692a34f1c"},
{file = "zope.interface-7.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51d5713e8e38f2d3ec26e0dfdca398ed0c20abda2eb49ffc15a15a23eb8e5f6d"},
{file = "zope.interface-7.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8d51e5eb29e57d34744369cd08267637aa5a0fefc9b5d33775ab7ff2ebf2e3"},
{file = "zope.interface-7.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55bbcc74dc0c7ab489c315c28b61d7a1d03cf938cc99cc58092eb065f120c3a5"},
{file = "zope.interface-7.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10ebac566dd0cec66f942dc759d46a994a2b3ba7179420f0e2130f88f8a5f400"},
{file = "zope.interface-7.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:7039e624bcb820f77cc2ff3d1adcce531932990eee16121077eb51d9c76b6c14"},
{file = "zope.interface-7.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03bd5c0db82237bbc47833a8b25f1cc090646e212f86b601903d79d7e6b37031"},
{file = "zope.interface-7.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3f52050c6a10d4a039ec6f2c58e5b3ade5cc570d16cf9d102711e6b8413c90e6"},
{file = "zope.interface-7.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af0b33f04677b57843d529b9257a475d2865403300b48c67654c40abac2f9f24"},
{file = "zope.interface-7.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:696c2a381fc7876b3056711717dba5eddd07c2c9e5ccd50da54029a1293b6e43"},
{file = "zope.interface-7.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f89a420cf5a6f2aa7849dd59e1ff0e477f562d97cf8d6a1ee03461e1eec39887"},
{file = "zope.interface-7.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b59deb0ddc7b431e41d720c00f99d68b52cb9bd1d5605a085dc18f502fe9c47f"},
{file = "zope.interface-7.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52f5253cca1b35eaeefa51abd366b87f48f8714097c99b131ba61f3fdbbb58e7"},
{file = "zope.interface-7.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88d108d004e0df25224de77ce349a7e73494ea2cb194031f7c9687e68a88ec9b"},
{file = "zope.interface-7.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c203d82069ba31e1f3bc7ba530b2461ec86366cd4bfc9b95ec6ce58b1b559c34"},
{file = "zope.interface-7.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f3495462bc0438b76536a0e10d765b168ae636092082531b88340dc40dcd118"},
{file = "zope.interface-7.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192b7a792e3145ed880ff6b1a206fdb783697cfdb4915083bfca7065ec845e60"},
{file = "zope.interface-7.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:400d06c9ec8dbcc96f56e79376297e7be07a315605c9a2208720da263d44d76f"},
{file = "zope.interface-7.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c1dff87b30fd150c61367d0e2cdc49bb55f8b9fd2a303560bbc24b951573ae1"},
{file = "zope.interface-7.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f749ca804648d00eda62fe1098f229b082dfca930d8bad8386e572a6eafa7525"},
{file = "zope.interface-7.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ec212037becf6d2f705b7ed4538d56980b1e7bba237df0d8995cbbed29961dc"},
{file = "zope.interface-7.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d33cb526efdc235a2531433fc1287fcb80d807d5b401f9b801b78bf22df560dd"},
{file = "zope.interface-7.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b419f2144e1762ab845f20316f1df36b15431f2622ebae8a6d5f7e8e712b413c"},
{file = "zope.interface-7.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03f1452d5d1f279184d5bdb663a3dc39902d9320eceb63276240791e849054b6"},
{file = "zope.interface-7.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ba4b3638d014918b918aa90a9c8370bd74a03abf8fcf9deb353b3a461a59a84"},
{file = "zope.interface-7.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc0615351221926a36a0fbcb2520fb52e0b23e8c22a43754d9cb8f21358c33c0"},
{file = "zope.interface-7.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:ce6cbb852fb8f2f9bb7b9cdca44e2e37bce783b5f4c167ff82cb5f5128163c8f"},
{file = "zope.interface-7.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5566fd9271c89ad03d81b0831c37d46ae5e2ed211122c998637130159a120cf1"},
{file = "zope.interface-7.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da0cef4d7e3f19c3bd1d71658d6900321af0492fee36ec01b550a10924cffb9c"},
{file = "zope.interface-7.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f32ca483e6ade23c7caaee9d5ee5d550cf4146e9b68d2fb6c68bac183aa41c37"},
{file = "zope.interface-7.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da21e7eec49252df34d426c2ee9cf0361c923026d37c24728b0fa4cc0599fd03"},
{file = "zope.interface-7.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a8195b99e650e6f329ce4e5eb22d448bdfef0406404080812bc96e2a05674cb"},
{file = "zope.interface-7.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:19c829d52e921b9fe0b2c0c6a8f9a2508c49678ee1be598f87d143335b6a35dc"},
{file = "zope.interface-7.0.1.tar.gz", hash = "sha256:f0f5fda7cbf890371a59ab1d06512da4f2c89a6ea194e595808123c863c38eff"},
]
[package.dependencies]
setuptools = "*"
[package.extras]
docs = ["Sphinx", "repoze.sphinx.autointerface", "sphinx-rtd-theme"]
test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10.11"
content-hash = "6d16510fd35519dee80acbeb09936403172391cc840df3b5be874e6eab27f242"
python-versions = "3.10.12"
content-hash = "a224728a18ef19c1f754e77db7d8cba413724a9a4257af5704b0fad93f833c58"

View File

@ -1,39 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['utils/pybullet_server.py'],
pathex=['.', './.venv', './.venv/Lib', './.venv/Lib/site-packages'],
binaries=[],
datas=[('pyproject.toml', '.'), ('robots.json', '.'), ('urdf', 'urdf'), ('data', 'data')],
hiddenimports=['libpython3.10', 'numpy'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='pybullet_server',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
contents_directory='test',
)

View File

@ -4,21 +4,16 @@ version = "0.1.0"
description = ""
authors = ["aarizona <ar.ariz.arizona@gmail.com>"]
readme = "README.md"
package-mode = false
[tool.poetry.dependencies]
python = "^3.10.11"
python = "3.10.12"
modbus = "^3.2"
pymodbustcp = "^0.2.2"
pymodbus = "^3.7.0"
pymodbus3 = "^1.0.0"
svgpathtools = "^1.6.1"
tk = "^0.1.0"
pybullet = "^3.2.5"
numpy = "^1.23.3"
popsicle = "^0.9.6"
pillow = "^11.0.0"
pyqt6 = "^6.7.1"
setuptools = "^75.3.0"
psutil = "^6.1.0"
pybullet-industrial = "^1.0.3"
py3dbp = "^1.1.2"
[build-system]
requires = ["poetry-core"]

View File

@ -1 +0,0 @@
from .client_socket import SocketRobotArm

View File

@ -1,456 +0,0 @@
import socket
import json
import os
import math
import numpy as np
from typing import Literal
from pprint import pprint
import threading
import pybullet as p
import pybullet_industrial as pi
from logger import logger
from robot.func import *
from robot.prepare_data import PrepareRobotData
from robot.urdf_manager import UrdfManager
from robot.socket_manager import SocketManager
# os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1"
class SocketRobotArm:
global_speed = 10
physical_speed = 10
# laser_id = 15
laser_id = 14
filename = "axis"
urdf_filename = "sample"
pass_size = 4
connected_status = Literal["connected", "not_connected", "error"]
_axis_coordinates = []
_world_coordinates = []
_command_count = []
command_type = "base"
command_data = None
motion_type = "reset"
motion_type = "normal"
def __init__(self, application_path, *args, **kwargs):
self.socket = None
self.host = None
self.port = 9760
self.slave_id = None
self.status: SocketRobotArm.connected_status = "not_connected"
self.q_app = None
self.imitate_point = None
robot_start_position = [0, 0, 0]
self.prepare_data = PrepareRobotData()
self.socket_manager = SocketManager()
self.urdf_manager = UrdfManager(
robot_start_position,
application_path,
self.palletizing,
)
self.constraint_id = None
def __exit__(self, exc_type, exc_value, traceback):
logger.info("exiting")
self.socket.close()
def start(self, type="DIRECT"):
self.urdf_manager.run_pybullet(type)
def start_loop(self, urdf):
self.urdf_manager.start_loop(urdf)
self.body_id = self.urdf_manager.body_id
self.num_joints = p.getNumJoints(self.body_id)
def load_palletizing(self):
self.urdf_manager.load_palletizing()
def start_moving(self):
self.urdf_manager.conveyor.moving = True
def get_pybullet_image(self):
return self.urdf_manager.get_pybullet_image()
def close(self):
self.socket_manager.close()
def connect(self, host, slave_id):
self.socket_manager.connect(host)
with open("delta.json", "w") as f:
pass
def get_status(self):
return self.socket_manager.status
def motionFund(self, radians):
if self.motion_type == "reset":
for index, r in enumerate(radians):
p.resetJointState(self.urdf_manager.body_id, index, r)
time.sleep(0.3)
else:
p.setJointMotorControlArray(
self.urdf_manager.body_id,
[i for i in range(len(radians))],
p.POSITION_CONTROL,
radians,
)
time.sleep(1)
def upd_model(self):
threading.Thread(target=self.upd_model_func, daemon=True).start()
def upd_model_func(self):
self.get_coordinates("axis")
self.set_text(text=f"Координаты осей {self.axis_coordinates}")
time.sleep(0.5)
self.get_coordinates("world")
self.set_text(text=f"Мировые координаты {self.world_coordinates}")
time.sleep(0.5)
self._fetch_command_count()
time.sleep(0.5)
axisJointPoses = self.axis_coordinates
self.motionFund(np.radians(axisJointPoses))
time.sleep(0.5)
if False:
coordinates = [float(p) * 0.001 for p in self.world_coordinates[:3]]
angles = [math.radians(p) for p in self.world_coordinates[3:6]]
worldJointPoses = self.convert_to_joint_base(coordinates, angles)
for i in range(self.num_joints):
v = worldJointPoses[i] if i < len(worldJointPoses) else 0
self.motionFund(worldJointPoses)
time.sleep(0.5)
calcWorldPosition = p.getLinkState(
self.urdf_manager.body_id,
self.num_joints - 1,
computeForwardKinematics=True,
)
calcWorldPosition = list(
[p * 1000 for p in calcWorldPosition[0]]
+ [
np.degrees(p)
for p in p.getEulerFromQuaternion(calcWorldPosition[1])
]
)
time.sleep(0.5)
position_diff = np.linalg.norm(
self.world_coordinates[:3] - np.array(calcWorldPosition[:3])
)
# print(*[f"world delta {i} {self.world_coordinates[i] - calcWorldPosition[i]}" for i in range(6)])
# print(*[f"axis delta {i} {self.axis_coordinates[i] - np.rad2deg(worldJointPoses[i])}" for i in range(6)])
# print(self.axis_coordinates[4] - np.rad2deg(worldJointPoses[4]))
print(
"Разница между расчетом по модели и мировыми координатами:",
position_diff,
)
self.set_text(text=f"Команд в очереди {self.command_count}")
time.sleep(0.5)
def cycle_base(self):
self.upd_model()
self.send_data(self.set_global_speed())
self.set_text(text=f"Установили глобальную скорость {self.global_speed}")
time.sleep(0.5)
def cycle_start(self):
self.send_data(self.start_cycle())
self.set_text(text=f"Старт одиночного цикла")
time.sleep(0.5)
if self.command_type == "base":
commands = self.steps_from_file()
if self.command_type == "calc":
commands = self.convert_point_to_free()
if self.command_type == "pallette":
commands = self.get_palletizing_json()
with open(f"log/{self.command_type}.json", "w") as myfile:
myfile.write(json.dumps(commands))
self.add_rcc_list = (
[self.set_physical_speed(True), self.set_output_laser(True)]
+ commands
+ [self.set_physical_speed(False), self.set_output_laser(False)]
)
step = 4
empty = 1
for i in range(0, len(self.add_rcc_list), step):
self.command_data = f"Отправка данных {i}...{i+step-1}"
self.send_data(make_addrcc_data(self.add_rcc_list[i : i + step], empty))
empty = 0
time.sleep(0.05)
def imitate(self):
threading.Thread(target=self.imitate_func, daemon=True).start()
def palletizing(self, position, box_id, counter):
dir_wall = (self.urdf_manager.conv_direction + 1) % 2
near_position = position[:]
near_position[dir_wall] -= 0.4
object_position = position[:]
object_position[dir_wall] -= 0.02
pallet_position = self.urdf_manager.packing[
counter % len(self.urdf_manager.packing)
]
logger.info(f"pallete {pallet_position}")
base1_position = pallet_position[:]
base1_position[0] -= 0.2
base1_position[2] += 0.2
base_position = pallet_position[:]
base_position[0] -= 0.2
drop_position = pallet_position[:]
drop_position[0] -= 0.4
drop_position[2] += 0.4
json_res = []
tool_pos = [0, 0, 0]
steps = [
{"type": "move", "coordinates": near_position},
{"type": "move", "coordinates": object_position},
{"type": "create_constraint"},
{"type": "move", "coordinates": base1_position},
{"type": "move", "coordinates": base_position},
{"type": "move", "coordinates": pallet_position},
{"type": "remove_constraint"},
{"type": "move", "coordinates": base_position},
{"type": "move", "coordinates": base1_position},
{"type": "move", "coordinates": drop_position},
]
constraint_id = None
for step in steps:
if step["type"] == "move":
# logger.info(step["coordinates"])
jointPoses = self.convert_to_joint_base(
step["coordinates"],
np.radians(tool_pos),
)
json_res.append(
self.prepare_data.make_step(
"free", np.degrees(jointPoses), [0, 0, 0, 0, 0, 0]
)
)
self.motionFund(jointPoses)
# time.sleep(2)
if step["type"] == "create_constraint":
link_state = p.getLinkState(self.body_id, self.num_joints - 1)
orientation = link_state[1]
constraint_id = p.createConstraint(
parentBodyUniqueId=self.body_id,
parentLinkIndex=self.num_joints - 1,
childBodyUniqueId=box_id,
childLinkIndex=-1,
jointType=p.JOINT_FIXED,
jointAxis=[0, 0, 0],
parentFramePosition=[0, 0, 0],
childFramePosition=[0, 0.2, 0],
parentFrameOrientation=p.getQuaternionFromEuler(
np.radians([0, 0, 90])
),
childFrameOrientation=orientation,
)
if step["type"] == "remove_constraint":
time.sleep(0.5)
p.removeConstraint(constraint_id)
# time.sleep(0.5)
# p.resetBasePositionAndOrientation(
# box_id,
# pallet_position,
# p.getQuaternionFromEuler(np.radians([0, 0, 0])),
# )
with open(f"data/palletizing.json", "w") as myfile:
myfile.write(json.dumps(json_res))
self.urdf_manager.conveyor.conveyor_stopped = False
def set_text(self, text):
logger.info(text)
def send_data(self, data):
return self.socket_manager.send_data(data)
def get_coordinates(self, coord_type: Literal["axis", "world"] = "axis"):
request = make_query_data([f"{coord_type}-{i}" for i in range(6)])
result = self.send_data(request)
if not result:
return
data = [float(i) for i in result]
if coord_type == "axis":
self._axis_coordinates = data
elif coord_type == "world":
self._world_coordinates = data
@property
def axis_coordinates(self):
return self._axis_coordinates
@property
def world_coordinates(self):
return self._world_coordinates
def _fetch_command_count(self):
request = make_query_data(["RemoteCmdLen"])
result = self.send_data(request)
self._command_count = result
@property
def command_count(self):
return self._command_count
def set_command_type(self, data):
self.command_type = data
def get_command_type(self):
return self.command_type
def get_command_data(self):
return self.command_data
def get_imitate_point(self):
return self.imitate_point
def set_global_speed(self):
return make_command_data(["modifyGSPD", str(self.global_speed * 10)])
def start_cycle(self):
return make_command_data(["actionSingleCycle"])
def set_physical_speed(self, status: bool = False):
return (
{
"oneshot": "0",
"action": "51",
"isUse": str(int(status)),
"speed": str(self.physical_speed * 1000),
},
)
def set_output_laser(self, status: bool = False):
return (
{
"oneshot": "0",
"action": "200",
"type": "0",
"io_status": str(int(status)),
"point": str(self.laser_id),
},
)
def imitate_func(self):
points = self.convert_point_to_free()
for point in points:
jointPoses = [np.radians(float(point[f"m{i}"])) for i in range(6)]
self.motionFund(jointPoses)
def get_palletizing_json(self):
with open(f"data/palletizing.json", "r") as fp:
data = json.load(fp)
return data
def convert_point_to_free(self):
points = self.steps_from_file()
res = []
for i, point in enumerate(points):
if point["action"] == "10":
self.imitate_point = i
points = [
point["m0"],
point["m1"],
point["m2"],
]
angles = [
point["m3"],
point["m4"],
point["m5"],
]
jointPoses = self.convert_to_joint_base(
[float(p) * 0.001 for p in points],
np.radians([float(x) for x in angles]),
)
res.append(
self.prepare_data.make_step(
"free", np.degrees(jointPoses), [0, 0, 0, 0, 0, 0]
)
)
return res
def convert_to_joint_base(self, coordinates, angles):
lower_limits = []
upper_limits = []
for i in range(self.num_joints):
limit = p.getJointInfo(self.body_id, i)
lower_limits.append(limit[8])
upper_limits.append(limit[9])
joint_angles = p.calculateInverseKinematics(
self.body_id,
endEffectorLinkIndex=self.num_joints - 1,
targetPosition=[float(c) for c in coordinates],
targetOrientation=p.getQuaternionFromEuler(angles),
lowerLimits=lower_limits,
upperLimits=upper_limits,
)
return joint_angles
def steps_from_file(self):
if not self.world_coordinates:
return []
result = []
with open(f"data/{self.filename}.nc.result", "r") as fp:
for line in fp:
data = line.strip().split(" ")
prep = {}
axis = ["X", "Y", "Z", "U", "V", "W"]
for item in data:
if item and item[0] and item[0] in axis:
prep[item[:1]] = float(item[1:])
if len(prep) > 0:
r = self.prepare_data.make_step(
"line",
(
prep.get("X", 0),
prep.get("Y", 0),
prep.get("Z", 0),
prep.get("U", 0),
prep.get("V", 0),
prep.get("W", 0),
),
self.world_coordinates,
)
# print(r)
result.append(r)
return result

View File

@ -1,141 +0,0 @@
import pybullet as p
import time
import threading
from logger import logger
class ConveyorBelt:
moving = False
def __init__(
self,
size,
position,
direction,
box_size,
box_spacing,
box_speed,
palletizinFunc,
):
self.direction = direction
self.conveyor_size = size
self.conveyor_position = position
self.conveyor_id = self.create_conveyor(size, position)
self.conveyor_stopped = False
self.box_size = box_size
self.box_spacing = box_spacing
self.box_speed = box_speed
self.boxes = []
self.box_counter = 0
self.create_boxes()
self.stop_thread = False
self.thread = threading.Thread(target=self.run)
self.thread.start()
self.palletizingFunc = palletizinFunc
def create_conveyor(self, size, position):
collision_shape_id = p.createCollisionShape(
shapeType=p.GEOM_BOX,
halfExtents=[size[i] / 2.0 for i in range(3)],
)
visual_shape_id = p.createVisualShape(
shapeType=p.GEOM_BOX,
halfExtents=[size[i] / 2.0 for i in range(3)],
rgbaColor=[0.5, 0.5, 0.5, 1],
)
conveyor_id = p.createMultiBody(
baseMass=0.0,
baseCollisionShapeIndex=collision_shape_id,
baseVisualShapeIndex=visual_shape_id,
basePosition=position,
)
return conveyor_id
def box_position(self, i=0):
position = self.conveyor_position[:]
position[self.direction] = (
self.conveyor_position[self.direction]
- self.conveyor_size[self.direction] * 0.5
+ i * (self.box_size[self.direction] + self.box_spacing)
+ self.box_size[0] * 0.5
)
return position
def create_boxes(self):
num_boxes = int(
self.conveyor_size[self.direction] / (self.box_size[0] + self.box_spacing)
)
for i in range(num_boxes):
position = self.box_position(i)
self.boxes.append(self.create_box(position))
def create_box(self, position):
collision_shape_id = p.createCollisionShape(
shapeType=p.GEOM_BOX,
halfExtents=[self.box_size[i] / 2.0 for i in range(3)],
)
visual_shape_id = p.createVisualShape(
shapeType=p.GEOM_BOX,
halfExtents=[self.box_size[i] / 2.0 for i in range(3)],
rgbaColor=[1, 0, 0, 1],
)
box_id = p.createMultiBody(
baseMass=10.0,
baseCollisionShapeIndex=collision_shape_id,
baseVisualShapeIndex=visual_shape_id,
basePosition=position,
baseOrientation=p.getQuaternionFromEuler([0, 0, 0]),
)
return box_id
def move_boxes(self):
if self.moving and not self.conveyor_stopped:
for box_id in self.boxes[:]:
pos, orn = p.getBasePositionAndOrientation(box_id)
if (
pos[self.direction] + self.box_size[0] * 0.5
> self.conveyor_position[self.direction]
+ self.conveyor_size[self.direction] * 0.5
):
# Если коробка выходит за конец конвейера, она падает вниз (физика продолжает действовать)
# Удаляем коробку с конвейера
self.boxes.remove(box_id)
self.conveyor_stopped = True
wall_position = list(pos)
dir_wall = (self.direction + 1) % (3 - 1)
wall_position[dir_wall] -= self.box_size[dir_wall] * 0.5
self.call_robot(wall_position, box_id, self.box_counter)
self.box_counter += 1
else:
new_pos = list(pos[:])
new_pos[self.direction] += self.box_speed
p.resetBasePositionAndOrientation(box_id, new_pos, orn)
# Добавляем новые коробки, если на конвейере меньше, чем максимально возможное количество
num_boxes = int(
self.conveyor_size[self.direction] / (self.box_size[0] + self.box_spacing)
)
if len(self.boxes) < num_boxes:
new_box = self.create_box(self.box_position())
self.boxes.append(new_box)
def call_robot(self, position, box_id, counter):
# Здесь можно вызвать робота для выполнения операции, например:
logger.info("Конвейер остановлен, вызываем робота для работы с коробкой.")
self.palletizingFunc(position, box_id, counter)
# time.sleep(5)
# self.conveyor_stopped = False
def run(self):
while not self.stop_thread:
self.move_boxes()
time.sleep(1)
def stop(self):
self.stop_thread = True
self.thread.join()

View File

@ -1,34 +0,0 @@
import pybullet as p
class Pallet:
def __init__(
self, position=[1, 1, 0], size=[0.8, 1.2, 0.144], color=[0.6, 0.3, 0.1, 0.5]
):
self.size = size
self.position = position
self.color = color
self.create_pallet()
def create_pallet(self):
half_size = [s * 0.5 for s in self.size]
# Создаем collision shape для паллеты
collision_shape = p.createCollisionShape(p.GEOM_BOX, halfExtents=half_size)
# Создаем визуальное отображение (shape) для паллеты
visual_shape = p.createVisualShape(
p.GEOM_BOX, halfExtents=half_size, rgbaColor=self.color
)
# Создаем объект паллеты в физическом мире
self.pallet_id = p.createMultiBody(
baseMass=0, # Масса 0, чтобы паллета не взаимодействовала с физикой
baseCollisionShapeIndex=collision_shape,
baseVisualShapeIndex=visual_shape,
basePosition=self.position,
)
# Устанавливаем позицию объекта паллеты в физическом мире
p.resetBasePositionAndOrientation(self.pallet_id, self.position, [0, 0, 0, 1])

View File

@ -1,60 +0,0 @@
from robot.func import *
# os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1"
class PrepareRobotData:
line_speed = 100.0
line_smooth = 0
line_tool = 0
def make_step(self, type, point, start_coordinates):
step = {
"oneshot": "1",
"delay": "0.0",
"speed": str(self.line_speed),
"smooth": str(self.line_smooth),
"coord": "0",
"tool": str(self.line_tool),
"ckStatus": "0x3F",
}
if type == "line" or type == "free":
pairs = zip(start_coordinates, point)
data = []
for pair in pairs:
data.append(round(sum(pair), 3))
m0, m1, m2, m3, m4, m5 = data
if type == "line":
step.update({"action": "10"})
if type == "free":
step.update({"action": "4"})
# m3 = 0
# m4 = 0
# m5 = 0
step.update({"m0": m0, "m1": m1, "m2": m2, "m3": m3, "m4": m4, "m5": m5})
step.update({"m6": 0, "m7": 0})
elif type == "curve":
pairs = zip(self.world_coordinates, point[:5])
m0, m1, m2, m3, m4, m5 = [round(sum(i), 3) for i in pairs]
pairs_p = zip(self.world_coordinates, point[6:])
m0_p, m1_p, m2_p, m3_p, m4_p, m5_p = [round(sum(i), 3) for i in pairs_p]
step.update({"action": "17"})
step.update({"m0": m0, "m1": m1, "m2": m2, "m3": m3, "m4": m4, "m5": m5})
step.update({"m6": 0, "m7": 0})
step.update(
{
"m0_p": m0_p,
"m1_p": m1_p,
"m2_p": m2_p,
"m3_p": m3_p,
"m4_p": m4_p,
"m5_p": m5_p,
}
)
step.update({"m6_p": 0, "m7_p": 0})
for s in step:
step[s] = str(step[s])
return step

View File

@ -1,58 +0,0 @@
import socket
import json
import os
import math
import numpy as np
from typing import Literal
from pprint import pprint
import threading
import pybullet as p
import pybullet_industrial as pi
from logger import logger
class SocketManager:
def __init__(self):
self.host = None
self.port = 9760
self.socket = None
self.status: Literal["connected", "not_connected", "error"] = "not_connected"
def connect(self, host):
self.host = host
if self.socket is None:
self.socket = socket.socket()
logger.info(f"trying connect to {(self.host, self.port)}")
self.socket.connect((self.host, self.port))
self.status = "connected"
def close(self):
if self.socket:
self.socket.close()
self.socket = None
self.status = "not_connected"
def send_data(self, data):
if not self.socket:
return
try:
self.socket.send(str.encode(json.dumps(data)))
response_data = self.socket.recv(1024)
response = json.loads(response_data)
if data["reqType"] == "query":
return response["queryData"]
elif data["reqType"] == "command":
return response["cmdReply"]
elif data["reqType"] == "AddRCC" and "cmdReply" in response.keys():
return response["cmdReply"]
else:
pprint(response_data)
return json.loads(response_data)
except Exception as e:
logger.error(f"Error sending data: {e}")
return None

View File

@ -1,139 +0,0 @@
import os
import numpy as np
import time
import pybullet as p
from logger import logger
from robot.conveyor import ConveyorBelt
from robot.pallet import Pallet
from packer.packer import PalletPacker
class UrdfManager:
urdf_filename = None
urdf_filename_tool = "welding_gun"
physics_client = None
body_id = None
def __init__(self, robot_start_position, application_path, palletizing):
self.robot_start_position = robot_start_position
self.application_path = application_path
self.palletizing = palletizing
self.conveyor = None
self.pallet = None
def start_loop(self, urdf):
self.urdf_filename = urdf
p.resetSimulation()
self.load_models()
p.setGravity(0, 0, -9.81, physicsClientId=self.physics_client)
self.state_id = p.saveState()
def run_pybullet(self, type="DIRECT"):
self.physics_client = p.connect(getattr(p, type))
logger.info(f"Connect to {self.physics_client} by {type}")
def load_models(self):
p.loadURDF(
os.path.join(self.application_path, "urdf", "plane.urdf"),
[0,0,-1],
physicsClientId=self.physics_client,
)
urdf_path = os.path.join(
self.application_path, "urdf", f"{self.urdf_filename}.urdf"
)
self.body_id = p.loadURDF(
urdf_path,
self.robot_start_position,
useFixedBase=True,
)
def load_palletizing(self):
if self.conveyor:
self.conveyor = None
if self.pallet:
self.pallet = None
self.start_loop(self.urdf_filename)
k = 0.2
self.pallet_target = [1.366773, 0.59591, -0.624086]
self.pallet_size = [0.8, 1.2, 0.144]
self.pallet_position = [
(self.pallet_target[i] - self.pallet_size[i] * 0.5)
for i in range(len(self.pallet_target))
]
self.pallet = Pallet(self.pallet_position)
self.box_size = [0.2, 0.2, 0.2]
# положение дальнего угла
self.conv_target = [1.045, -0.989, -0.094]
self.conv_size = [0.5, 3.0, 0.1]
self.conv_direction = self.conv_size.index(max(self.conv_size))
self.conv_pos = [
(self.conv_target[i] - self.conv_size[i] * 0.5)
for i in range(len(self.conv_target))
]
self.conveyor = ConveyorBelt(
self.conv_size,
self.conv_pos,
self.conv_direction,
self.box_size,
0.2,
0.1,
self.palletizing,
)
self.packing = PalletPacker(
{
"x": self.pallet_size[0],
"y": self.pallet_size[1],
"z": self.box_size[2], # высота паллеты в один слой
},
{
"x": self.box_size[0],
"y": self.box_size[1],
"z": self.box_size[2],
},
).pack()
self.packing = sorted(self.packing, key=lambda x: (x[0], x[1]))
for p in self.packing:
# logger.info(p)
for i in range(len(self.box_size)):
p[i] = self.pallet_target[i] - p[i] - self.box_size[i] * 0.5
dir_wall = (self.conv_direction + 1) % (3 - 1)
p[dir_wall] -= self.box_size[dir_wall]
p[self.conv_direction] -= self.box_size[self.conv_direction] * 0.5
p[2] += self.pallet_size[2]
# logger.info(f"{self.packing[0]} {self.pallet_target}")
time.sleep(1)
def get_pybullet_image(self):
if self.physics_client is None:
return
width, height, rgb, _, _ = p.getCameraImage(
width=500,
height=500,
viewMatrix=p.computeViewMatrix(
cameraEyePosition=[4, -4, 1.5],
# cameraEyePosition=[4,-4,4],
cameraTargetPosition=[0, 0, 0], # Центр фокусировки камеры
cameraUpVector=[0, 0, 1], # Направление вверх
),
projectionMatrix=p.computeProjectionMatrixFOV(
fov=60.0, aspect=1.0, nearVal=0.1, farVal=10.0
),
# renderer=p.ER_TINY_RENDERER,
physicsClientId=self.physics_client,
)
return (rgb, width, height)

View File

@ -1,33 +0,0 @@
[
{
"name": "big",
"host": "192.168.70.55",
"slave_id": 11,
"urdf": "sample"
},
{
"name": "big WITHOUT",
"host": "192.168.70.55",
"slave_id": 11,
"urdf": "sample_without"
},
{
"name": "test",
"host": "127.0.0.1",
"slave_id": 11,
"urdf": "sample"
},
{
"name": "test WITHOUT",
"host": "127.0.0.1",
"slave_id": 11,
"urdf": "sample_without"
},
{
"name": "test small WITHOUT",
"host": "127.0.0.1",
"slave_id": 11,
"urdf": "small_without"
}
]

125
run.py
View File

@ -1,125 +0,0 @@
import subprocess
import argparse
import sys
import signal
import psutil
# Параметры для процессов
server_process = None
test_server_process = None
command_type = 'exe'
def usage():
"""Функция для отображения помощи"""
print("Usage: run_all.py [--test]")
sys.exit(1)
def terminate_process(process):
"""Функция для корректного завершения процесса и всех его дочерних процессов"""
if process:
proc = psutil.Process(process.pid)
for child in proc.children(recursive=True):
child.terminate()
proc.terminate()
proc.wait()
# Обработчик для сигналов выхода
def cleanup(*args):
"""Функция для остановки серверов при выходе"""
global server_process, test_server_process
print("Остановка серверов...")
terminate_process(server_process)
terminate_process(test_server_process)
print("Серверы остановлены.")
sys.exit(0) # Завершение работы после очистки
# Назначаем функции очистки для сигналов
signal.signal(signal.SIGINT, lambda *_: cleanup())
signal.signal(signal.SIGTERM, lambda *_: cleanup())
# Парсер аргументов командной строки
parser = argparse.ArgumentParser(description="Python launcher script.")
parser.add_argument(
"--test-socket", action="store_true", help="Запуск в режиме тестирования"
)
parser.add_argument(
"--bullet-gui", action="store_true", help="Вывод визуального pybullet"
)
parser.add_argument(
"--start-py", action="store_true", help="Запуск EXE или PY"
)
args = parser.parse_args()
if args.start_py:
command_type = 'local'
poetry_path = "poetry"
# Установка команды для pybullet_server
pybullet_command = [
poetry_path,
"run",
"python",
"utils/pybullet_server.py",
] if command_type == 'local' else ['pybullet_server.exe']
# Если включен режим тестирования, добавляем флаг --test
if args.bullet_gui:
# if type(pybullet_command) is str:
# pybullet_command += '--test'
# else:
pybullet_command.append("--test")
# Запуск pybullet_server.exe
print("Запуск pybullet_server...")
server_process = subprocess.Popen(pybullet_command)
# Проверяем успешный запуск сервера
if server_process.poll() is not None:
print("Ошибка при запуске pybullet_server")
sys.exit(1)
# Если включен режим тестирования, запускаем test_socket_server.exe
if args.test_socket:
print("Запуск test_socket_server...")
test_server_process = subprocess.Popen(
[
poetry_path,
"run",
"python",
"utils/test_socket_server.py",
] if command_type == 'local' else 'test_socket_server.exe'
) # Путь к исполняемому файлу
# Проверка успешного запуска тестового сервера
if test_server_process.poll() is not None:
print("Ошибка при запуске test_socket_server")
sys.exit(1)
# Запуск основного скрипта main.exe в режиме тестирования
subprocess.run(
[
poetry_path,
"run",
"python",
"main.py",
"--mode",
"test",
] if command_type == 'local' else 'main.exe --mode test'
) # Путь к исполняемому файлу
else:
# Запуск основного скрипта main.exe
subprocess.run(
[
poetry_path,
"run",
"python",
"main.py",
] if command_type == 'local' else 'main.exe'
) # Путь к исполняемому файлу
# Очистка после завершения
cleanup()

View File

@ -1,39 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['run.py'],
pathex=['.', './.venv', './.venv/Lib', './.venv/Lib/site-packages'],
binaries=[],
datas=[('pyproject.toml', '.'), ('robots.json', '.'), ('urdf', 'urdf'), ('data', 'data')],
hiddenimports=['libpython3.10'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='run',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
contents_directory='test',
)

27
test_socket_server.py Normal file
View File

@ -0,0 +1,27 @@
import socket
import json
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
if data:
req = json.loads(data)
res = {"queryData": ["ok"]}
if "queryAddr" in req.keys() and "axis-0" in req["queryAddr"]:
res["queryData"] = [10, 11, 12, 13, 14, 15]
if "queryAddr" in req and "world-0" in req["queryAddr"]:
res["queryData"] = [100, 101, 102, 103, 104, 105]
if req["reqType"] == "command":
res["cmdReply"] = ['ok']
conn.sendall(json.dumps(res).encode())

View File

@ -1,39 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['utils/test_socket_server.py'],
pathex=['.', './.venv', './.venv/Lib', './.venv/Lib/site-packages'],
binaries=[],
datas=[('pyproject.toml', '.'), ('robots.json', '.'), ('urdf', 'urdf'), ('data', 'data')],
hiddenimports=['libpython3.10'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='test_socket_server',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
contents_directory='test',
)

View File

@ -1,24 +0,0 @@
<?xml version="1.0"?>
<robot name="europallet">
<link name="pallet">
<inertial>
<mass value="20.0" /> <!-- Масса палеты, можно изменить -->
<origin xyz="0 0 7.25" rpy="0 0 0" /> <!-- Центр масс (высота 7.25 см) -->
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" /> <!-- Моменты
инерции, можно изменить -->
</inertial>
<visual>
<geometry>
<box size="1.2 0.8 0.145" /> <!-- Размеры (длина, ширина, высота) в метрах -->
</geometry>
<material name="wood">
<color rgba="0.58 0.29 0.19 1.0" /> <!-- Цвет, здесь коричневый -->
</material>
</visual>
<collision>
<geometry>
<box size="1.2 0.8 0.145" /> <!-- Размеры для коллизий также -->
</geometry>
</collision>
</link>
</robot>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" ?>
<robot name="plane">
<link name="planeLink">
<contact>
<lateral_friction value="1"/>
</contact>
<inertial>
<origin rpy="0 0 0" xyz="0 0 0"/>
<mass value=".0"/>
<inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0"/>
<geometry>
<mesh filename="../urdf_support/plane.obj" scale="1 1 1"/>
</geometry>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 -5"/>
<geometry>
<box size="30 30 10"/>
</geometry>
</collision>
</link>
</robot>

View File

@ -1,218 +0,0 @@
<?xml version="1.0"?>
<robot name="sample_robot">
<!-- Materials -->
<material name="grey">
<color rgba="0.0 0 0 1.0" />
</material>
<material name="red">
<color rgba="1.0 0.0 0.0 1.0" />
</material>
<material name="blue">
<color rgba="0 0.0 1.0 1.0" />
</material>
<material name="lightblue">
<color rgba="0.0 0.22 1.0 1.0" />
</material>
<material name="yellow">
<color rgba="0.96 0.76 0.13 1.0" />
</material>
<material name="orange">
<color rgba="1.0 0.5 0.0 1.0" />
</material>
<material name="black">
<color rgba="0.15 0.15 0.15 1.0" />
</material>
<!-- Links: main serial chain -->
<link name="base_link">
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/1.stl" />
</geometry>
<material name="grey" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/1.stl" />
</geometry>
</collision>
</link>
<link name="link_1">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/sample/2.stl" />
</geometry>
<material name="red" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/sample/2.stl" />
</geometry>
</collision>
</link>
<link name="link_2">
<visual>
<origin rpy="0 0 0" xyz="0.0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/3.stl" />
</geometry>
<material name="blue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/3.stl" />
</geometry>
</collision>
</link>
<link name="link_3">
<visual>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/4.stl" />
</geometry>
<material name="lightblue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/4.stl" />
</geometry>
</collision>
</link>
<link name="link_4">
<visual>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/5.stl" />
</geometry>
<material name="yellow" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/5.stl" />
</geometry>
</collision>
</link>
<link name="link_5">
<visual>
<origin rpy="0 0 0" xyz="0.02 0.04 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/6.stl" />
</geometry>
<material name="orange" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.02 0.04 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/6.stl" />
</geometry>
</collision>
</link>
<link name="link_6">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/777.stl" />
</geometry>
<material name="black" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/777.stl" />
</geometry>
</collision>
</link>
<link name="welding_gun_body">
<visual>
<geometry>
<mesh filename="../urdf_support/sample/7.stl" /> <!-- Замените на путь к вашему STL-файлу -->
</geometry>
<material name="metal" />
<origin xyz="0 0 0" rpy="0 0 0" />
</visual>
</link>
<!-- Joints: main serial chain -->
<joint name="joint_1" type="revolute">
<limit lower="-2.705" upper="2.705" effort="0" velocity="0" />
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
</joint>
<joint name="joint_2" type="revolute">
<limit lower="-2.444" upper="1.135" effort="0" velocity="0" />
<parent link="link_1" />
<child link="link_2" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0.17045 0 0.4946" />
</joint>
<joint name="joint_3" type="revolute">
<limit lower="-1.309" upper="1.919" effort="0" velocity="0" />
<parent link="link_2" />
<child link="link_3" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0 -0.001963 0.729921" />
</joint>
<joint name="joint_4" type="revolute">
<limit lower="-3.142" upper="3.142" effort="0" velocity="0" />
<parent link="link_3" />
<child link="link_4" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0 0 0.098277" />
</joint>
<joint name="joint_5" type="revolute">
<limit lower="-2.007" upper="2.007" effort="0" velocity="0" />
<parent link="link_4" />
<child link="link_5" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="1.109039 0 0" />
</joint>
<joint name="joint_6" type="revolute">
<limit lower="-6.283" upper="6.283" effort="0" velocity="0" />
<parent link="link_5" />
<child link="link_6" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0.117 0 0" />
</joint>
<joint name="welding_gun_fixed_joint" type="fixed">
<parent link="link_6" />
<child link="welding_gun_body" />
<origin xyz="0 0 0" rpy="0 0 0" />
</joint>
<link name="tcp">
<visual>
<geometry>
<box size="0.05 0.05 0.05" />
</geometry>
<material name="red" />
</visual>
</link>
<joint name="tcp_joint" type="fixed">
<parent link="welding_gun_body" />
<child link="tcp" />
<origin xyz="0.353774 0.009203 -0.033794" rpy="110.766 1.620 -89.636" />
</joint>
</robot>

View File

@ -1,204 +0,0 @@
<?xml version="1.0"?>
<robot name="sample_robot">
<!-- Materials -->
<material name="grey">
<color rgba="0.0 0 0 1.0" />
</material>
<material name="red">
<color rgba="1.0 0.0 0.0 1.0" />
</material>
<material name="blue">
<color rgba="0 0.0 1.0 1.0" />
</material>
<material name="lightblue">
<color rgba="0.0 0.22 1.0 1.0" />
</material>
<material name="yellow">
<color rgba="0.96 0.76 0.13 1.0" />
</material>
<material name="orange">
<color rgba="1.0 0.5 0.0 1.0" />
</material>
<material name="black">
<color rgba="0.15 0.15 0.15 1.0" />
</material>
<!-- Links: main serial chain -->
<link name="base_link">
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/1.stl" />
</geometry>
<material name="grey" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/1.stl" />
</geometry>
</collision>
</link>
<link name="link_1">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/sample/2.stl" />
</geometry>
<material name="red" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/sample/2.stl" />
</geometry>
</collision>
</link>
<link name="link_2">
<visual>
<origin rpy="0 0 0" xyz="0.0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/3.stl" />
</geometry>
<material name="blue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/3.stl" />
</geometry>
</collision>
</link>
<link name="link_3">
<visual>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/4.stl" />
</geometry>
<material name="lightblue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/4.stl" />
</geometry>
</collision>
</link>
<link name="link_4">
<visual>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/5.stl" />
</geometry>
<material name="yellow" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/5.stl" />
</geometry>
</collision>
</link>
<link name="link_5">
<visual>
<origin rpy="0 0 0" xyz="0.02 0.04 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/6.stl" />
</geometry>
<material name="orange" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.02 0.04 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/6.stl" />
</geometry>
</collision>
</link>
<link name="link_6">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/777.stl" />
</geometry>
<material name="black" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0.0" />
<geometry>
<mesh filename="../urdf_support/sample/777.stl" />
</geometry>
</collision>
</link>
<!-- Joints: main serial chain -->
<joint name="joint_1" type="revolute">
<limit lower="-2.705" upper="2.705" effort="0" velocity="0" />
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
</joint>
<joint name="joint_2" type="revolute">
<limit lower="-2.444" upper="1.135" effort="0" velocity="0" />
<parent link="link_1" />
<child link="link_2" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0.17045 0 0.4946" />
</joint>
<joint name="joint_3" type="revolute">
<limit lower="-1.309" upper="1.919" effort="0" velocity="0" />
<parent link="link_2" />
<child link="link_3" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0 -0.001693 0.729921" />
</joint>
<joint name="joint_4" type="revolute">
<limit lower="-3.142" upper="3.142" effort="0" velocity="0" />
<parent link="link_3" />
<child link="link_4" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0 0 0.098277" />
</joint>
<joint name="joint_5" type="revolute">
<limit lower="-2.007" upper="2.007" effort="0" velocity="0" />
<parent link="link_4" />
<child link="link_5" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="1.109039 0 0" />
</joint>
<joint name="joint_6" type="revolute">
<limit lower="-6.283" upper="6.283" effort="0" velocity="0" />
<parent link="link_5" />
<child link="link_6" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0.117 0 0" />
</joint>
<link name="tcp">
<visual>
<origin rpy="0 0 0" xyz="0.04 0 0" />
<geometry>
<box size="0.02 0.02 0.02" />
</geometry>
<material name="red" />
</visual>
</link>
<joint name="tcp_joint" type="fixed">
<parent link="link_6" />
<child link="tcp" />
<origin xyz="0 0 0" rpy="0 0 0" />
</joint>
</robot>

View File

@ -1,192 +0,0 @@
<?xml version="1.0"?>
<robot name="small_robot">
<!-- Materials -->
<material name="grey">
<color rgba="0.0 0 0 1.0" />
</material>
<material name="red">
<color rgba="1.0 0.0 0.0 1.0" />
</material>
<material name="blue">
<color rgba="0 0.0 1.0 1.0" />
</material>
<material name="lightblue">
<color rgba="0.0 0.22 1.0 1.0" />
</material>
<material name="yellow">
<color rgba="0.96 0.76 0.13 1.0" />
</material>
<material name="orange">
<color rgba="1.0 0.5 0.0 1.0" />
</material>
<material name="black">
<color rgba="0.15 0.15 0.15 1.0" />
</material>
<!-- Links: main serial chain -->
<link name="base_link">
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/small/1.stl" />
</geometry>
<material name="grey" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/1.stl" />
</geometry>
</collision>
</link>
<link name="link_1">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/small/2.stl" />
</geometry>
<material name="red" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0.23445" />
<geometry>
<mesh filename="../urdf_support/sample/2.stl" />
</geometry>
</collision>
</link>
<link name="link_2">
<visual>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/small/3.stl" />
</geometry>
<material name="blue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/3.stl" />
</geometry>
</collision>
</link>
<link name="link_3">
<visual>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/small/4.stl" />
</geometry>
<material name="lightblue" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 -0.103 0" />
<geometry>
<mesh filename="../urdf_support/sample/4.stl" />
</geometry>
</collision>
</link>
<link name="link_4">
<visual>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/small/5.stl" />
</geometry>
<material name="yellow" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0.23345 0 0" />
<geometry>
<mesh filename="../urdf_support/sample/5.stl" />
</geometry>
</collision>
</link>
<link name="link_5">
<visual>
<origin rpy="0 0 0" xyz="0 0 0.0" />
<geometry>
<mesh filename="../urdf_support/small/6.stl" />
</geometry>
<material name="orange" />
</visual>
</link>
<link name="link_6">
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="../urdf_support/small/7.stl" />
</geometry>
<material name="black" />
</visual>
</link>
<!-- Joints: main serial chain -->
<joint name="joint_1" type="revolute">
<limit lower="-2.705" upper="2.705" effort="0" velocity="0" />
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
</joint>
<joint name="joint_2" type="revolute">
<limit lower="-2.444" upper="1.135" effort="0" velocity="0" />
<parent link="link_1" />
<child link="link_2" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0.169740 0 0.4946" />
</joint>
<joint name="joint_3" type="revolute">
<limit lower="-1.309" upper="1.919" effort="0" velocity="0" />
<parent link="link_2" />
<child link="link_3" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0 -0.00118 0.730581" />
</joint>
<joint name="joint_4" type="revolute">
<limit lower="-3.142" upper="3.142" effort="0" velocity="0" />
<parent link="link_3" />
<child link="link_4" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0 0 0.099522" />
</joint>
<joint name="joint_5" type="revolute">
<limit lower="-2.007" upper="2.007" effort="0" velocity="0" />
<parent link="link_4" />
<child link="link_5" />
<axis xyz="0 -1 0" />
<origin rpy="0 0 0" xyz="0.826407 0 0" />
</joint>
<joint name="joint_6" type="revolute">
<limit lower="-6.283" upper="6.283" effort="0" velocity="0" />
<parent link="link_5" />
<child link="link_6" />
<axis xyz="1 0 0" />
<origin rpy="0 0 0" xyz="0.164 0 0" />
</joint>
<link name="tcp">
<visual>
<origin rpy="0 0 0" xyz="0.04 0 0" />
<geometry>
<box size="0.02 0.02 0.02" />
</geometry>
<material name="red" />
</visual>
</link>
<joint name="tcp_joint" type="fixed">
<parent link="link_6" />
<child link="tcp" />
<origin xyz="0 0 0" rpy="0 0 0" />
</joint>
</robot>

View File

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<robot name="welding_gun_robot">
<link name="welding_gun_body">
<visual>
<geometry>
<mesh filename="../urdf_support/sample/7.stl" />
</geometry>
<material name="metal" />
<origin xyz="0 0 0" rpy="0 0 0" />
</visual>
</link>
<link name="tcp">
<visual>
<geometry>
<box size="0.05 0.05 0.05" />
</geometry>
<material name="red" />
</visual>
</link>
<joint name="tcp_joint" type="fixed">
<parent link="welding_gun_body" />
<child link="tcp" />
<origin xyz="0.353774 0.009203 -0.033794" rpy="110.766 1.620 -89.636" />
</joint>
</robot>

View File

@ -1,18 +0,0 @@
# Blender v2.66 (sub 1) OBJ File: ''
# www.blender.org
mtllib plane.mtl
o Plane
v 15.000000 -15.000000 0.000000
v 15.000000 15.000000 0.000000
v -15.000000 15.000000 0.000000
v -15.000000 -15.000000 0.000000
vt 15.000000 0.000000
vt 15.000000 15.000000
vt 0.000000 15.000000
vt 0.000000 0.000000
usemtl Material
s off
f 1/1 2/2 3/3
f 1/1 3/3 4/4

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@ -1,42 +0,0 @@
# server.py
import time
import argparse
import pybullet as p
import pybullet_data
# from logger import logger
def main(type="SHARED_MEMORY_SERVER"):
# Подключаемся к графическому серверу в режиме SHARED_MEMORY_SERVER
# physicsClient = p.connect(p.SHARED_MEMORY_SERVER)
physicsClient = p.connect(getattr(p, type))
print(f"start pybullet ph client {physicsClient}")
# Настраиваем среду
p.setAdditionalSearchPath(pybullet_data.getDataPath())
p.setGravity(0, 0, -9.81, physicsClientId=physicsClient)
while True:
# Основной цикл физического движка
# if physicsClient != -1:
try:
p.stepSimulation()
except Exception as e:
print(f"Ошибка в pybullet_server{e}")
time.sleep(1)
time.sleep(1/240)
if __name__ == "__main__":
# Парсер аргументов командной строки
parser = argparse.ArgumentParser(description="Запуск PyBullet сервера.")
parser.add_argument(
"--test", action="store_true", help="Запустить сервер в режиме GUI_SERVER"
)
args = parser.parse_args()
# Если передан аргумент --test, устанавливаем тип подключения SHARED_MEMORY_SERVER
connection_type = "GUI_SERVER" if args.test else "SHARED_MEMORY_SERVER"
# connection_type = "SHARED_MEMORY_SERVER"
main(connection_type)

View File

@ -1,179 +0,0 @@
import socket
import json
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 9760 # Port to listen on (non-privileged ports are > 1023)
c_angles = [
{
"world": [
1131.959351,
-588.689941,
1277.805054,
6.181231,
54.227802,
-100.604988,
],
"axis": [-41.612457, 31.759747, -26.773878, 74.869049, -45.417992, -20.86335],
},
{
"world": [1282.244, -75.427, 1772.476, 84.629, 34.519, 153.999],
"axis": [-8.487, -8.681, 33.058, 88.070, -75.010, -10.566],
},
{
"world": [1630.006, 628.326, 1322.554, 0, 90, 0],
"axis": [22.493, -30.696, 35.997, -77.419, -23.007, 76.362],
},
{
"world": [1052.757, -1028.846, 334.417, 162.374, 20.467, 75.065],
"axis": [-43.742, -30.698, -12.227, -21.884, -23.078, 76.362],
},
{
"world": [1396.525, 1.687, 1322.697, 0, 90, 0],
"axis": [0, -0.002, -0.002, 0.003, -0.001, 0],
},
{
"world": [1396.513, 1.758, 1322.749, -0.002, 90, 0],
"axis": [0.002, -0.001, 0, 0, 0, 0],
},
{
"world": [-1.645, 1396.533, 1322.700, -89.998, 90.000, 0],
"axis": [89.998, -0.002, -0.001, 0.001, -0.001, -0.001],
},
{
"world": [-61.982, 1.689, 1955.771, 0, 25, 0.003],
"axis": [0.003, 65, -0.001, 0.001, 0, -0.001],
},
{
"world": [72.252, 1.696, 2450.564, 0, 0, 0],
"axis": [0.002, -0.001, 89.999, 0.002, 0, -0.001],
},
{
"world": [1396.542, 1.748, 1322.702, 90.004, 0.001, 90.003],
"axis": [0.002, -0.003, 0, 89.999, -0.001, 0],
},
{
"world": [1279.539, 1.716, 1439.725, 0.004, 0.005, 0.001],
"axis": [0.001, -0.002, -0.001, 0.004, 89.998, 0],
},
{
"world": [1396.518, 1.704, 1322.743, 90.002, -0.006, 90],
"axis": [0, -0.001, 0, 0.002, 0, 90.003],
},
]
c_angles = [
{
"world": [
894.159973,
-738.295654,
782.748047,
172.274109,
28.079031,
120.377357,
],
"axis": [-39.428261, 10.391139, -32.562145, 176.81929, 38.895988, -159.779755],
},
{
"world": [
1100.071655,
-347.347412,
782.754578,
172.284241,
28.079557,
142.505508,
],
"axis": [-17.409513, 10.897068, -33.003525, 176.892288, 38.957874, -159.934479],
},
]
c_small = [
{
"world": [549.087, -803.609, 939.418, 125.479, 50.992, 63.257],
"axis": [-55.721, 12.229, -33.657, 35.030, 0.00, -1.621],
},
{
"world": [202.361, 333.995, 1743.859, -33.7, 40.692, 12.951],
"axis": [58.637, 41.540, -2.386, -32.975, -0.052, 0.119],
},
{
"world": [915.212, 352.196, 1110.636, -109.839, 55.517, -85.605],
"axis": [20.987, 14.281, -25.313, -32.976, -0.054, 0.117],
},
{
"world": [915.172, 352.254, 1110.614, 179.937, 78.911, -159.077],
"axis": [20.986, 14.282, -25.313, -0.102, -0.057, 0.115],
},
{
"world": [1165.135, 1.142, 1312.130, 179.258, 89.223, 179.259],
"axis": [0.001, -0.299, -0.416, -0.103, -0.059, 0.113],
},
{
"world": [1410.226, 1.123, 1324.733, 0, 90, 0],
"axis": [0, -20.6, 23.854, -0.001, -3.249, 0.004],
},
{
"world": [943.3, -650.361, 783.806, 103.505, 55.005, 42.234],
"axis": [-31.249, -8.117, -28.424, 43.951, 36.544, 0.001],
},
{
"world": [721.214, 299.284, 1141.345, -133.593, 37.242, -120.067],
"axis": [27.053, 27.798, -28.423, -35.215, -41.446, 0.005],
},
]
c_angles = c_small
coordinates_index = 0
def handle_client(conn, addr):
print(f"Connected by {addr}")
try:
while True:
data = conn.recv(1024 * 2)
if not data:
break
req = json.loads(data)
print(req)
res = {"queryData": ["ok"]}
global coordinates_index
if "queryAddr" in req and "axis-0" in req["queryAddr"]:
print(f"----{coordinates_index}----")
limit = len(c_angles) - 1
# limit = 2
if coordinates_index < limit:
coordinates_index += 1
else:
coordinates_index = 0
c = c_angles[coordinates_index]
if "queryAddr" in req and "axis-0" in req["queryAddr"]:
res["queryData"] = c["axis"]
if "queryAddr" in req and "world-0" in req["queryAddr"]:
res["queryData"] = c["world"]
if "reqType" in req and (
req["reqType"] == "command" or req["reqType"] == "AddRCC"
):
res["cmdReply"] = ["it is local dear"]
# print(res)
conn.sendall(json.dumps(res).encode())
except json.JSONDecodeError as e:
print(f"JSON decode error: {e}")
except socket.error as e:
print(f"Socket error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
finally:
conn.close()
print(f"Connection with {addr} closed")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print(f"Server listening on {HOST}:{PORT}")
while True:
conn, addr = s.accept()
handle_client(conn, addr)

View File

@ -1,4 +0,0 @@
from xacrodoc import XacroDoc
doc = XacroDoc.from_file(path="fanuc_m16ib_support/urdf/fanucM16ib.urdf")
urdf_str = doc.to_urdf_string()
doc.to_urdf_file("urdf/fanucM16ib.urdf")