Update fields
This commit is contained in:
@@ -65,36 +65,39 @@ def _parse_joint_limits_data(data: dict) -> tuple[list[str], list[tuple[float, f
|
||||
|
||||
|
||||
def load_joint_names(
|
||||
path: str | None = None,
|
||||
package: str = "iiwa_config",
|
||||
relative: str = "config/moveit/joint_limits.yaml",
|
||||
) -> list[str]:
|
||||
"""Возвращает упорядоченный список имён суставов из joint_limits.yaml."""
|
||||
path = _resolve_path(package, relative)
|
||||
with open(path) as f:
|
||||
resolved = Path(path) if path else _resolve_path(package, relative)
|
||||
with open(resolved) as f:
|
||||
data = yaml.safe_load(f)
|
||||
names, _ = _parse_joint_limits_data(data)
|
||||
return names
|
||||
|
||||
|
||||
def load_joint_limits(
|
||||
path: str | None = None,
|
||||
package: str = "iiwa_config",
|
||||
relative: str = "config/moveit/joint_limits.yaml",
|
||||
) -> list[tuple[float, float]]:
|
||||
"""Возвращает список (min, max) для каждого сустава по порядку joint1..jointN."""
|
||||
path = _resolve_path(package, relative)
|
||||
with open(path) as f:
|
||||
resolved = Path(path) if path else _resolve_path(package, relative)
|
||||
with open(resolved) as f:
|
||||
data = yaml.safe_load(f)
|
||||
_, limits = _parse_joint_limits_data(data)
|
||||
return limits
|
||||
|
||||
|
||||
def load_api_config(
|
||||
path: str | None = None,
|
||||
package: str = "iiwa_config",
|
||||
relative: str = "config/api_endpoints.yaml",
|
||||
) -> list[EndpointDef]:
|
||||
"""Загружает описания эндпоинтов из YAML и возвращает список EndpointDef."""
|
||||
path = _resolve_path(package, relative)
|
||||
with open(path) as f:
|
||||
resolved = Path(path) if path else _resolve_path(package, relative)
|
||||
with open(resolved) as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
endpoints: list[EndpointDef] = []
|
||||
|
||||
@@ -208,10 +208,13 @@ def _make_tf_handler(ep: EndpointDef):
|
||||
return handler
|
||||
|
||||
|
||||
def build_dynamic_router() -> APIRouter:
|
||||
def build_dynamic_router(
|
||||
endpoints_path: str | None = None,
|
||||
joint_limits_path: str | None = None,
|
||||
) -> APIRouter:
|
||||
"""Читает api_endpoints.yaml и joint_limits.yaml, возвращает готовый APIRouter."""
|
||||
endpoints = load_api_config()
|
||||
joint_limits = load_joint_limits()
|
||||
endpoints = load_api_config(path=endpoints_path)
|
||||
joint_limits = load_joint_limits(path=joint_limits_path)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
import uvicorn
|
||||
import threading
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import rclpy
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from sensor_msgs.msg import JointState
|
||||
from .ros_node import init_ros_node, get_bridge
|
||||
|
||||
from .dynamic_router import build_dynamic_router
|
||||
from .ros_node import CobotWebNode, get_bridge, set_bridge
|
||||
from . import runner, trajectory
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
init_ros_node()
|
||||
get_bridge().subscribe("/joint_states", JointState)
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
app.include_router(build_dynamic_router())
|
||||
app.include_router(runner.router)
|
||||
app.include_router(trajectory.router)
|
||||
|
||||
|
||||
def main():
|
||||
uvicorn.run(app, host="localhost", port=8007)
|
||||
rclpy.init()
|
||||
node = CobotWebNode()
|
||||
set_bridge(node)
|
||||
threading.Thread(target=rclpy.spin, args=(node,), daemon=True).start()
|
||||
|
||||
host = node.get_parameter('host').value
|
||||
port = node.get_parameter('port').value
|
||||
endpoints_path = node.get_parameter('endpoints_path').value or None
|
||||
joint_limits_path = node.get_parameter('joint_limits_path').value or None
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
get_bridge().subscribe("/joint_states", JointState)
|
||||
yield
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
app.include_router(build_dynamic_router(endpoints_path, joint_limits_path))
|
||||
app.include_router(runner.router)
|
||||
app.include_router(trajectory.router)
|
||||
|
||||
uvicorn.run(app, host=host, port=port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -11,6 +11,11 @@ class CobotWebNode(Node):
|
||||
def __init__(self):
|
||||
super().__init__('cobot_web_node')
|
||||
|
||||
self.declare_parameter('host', '0.0.0.0')
|
||||
self.declare_parameter('port', 8007)
|
||||
self.declare_parameter('endpoints_path', '')
|
||||
self.declare_parameter('joint_limits_path', '')
|
||||
|
||||
self._topic_cache: dict = {}
|
||||
self._pub_registry: dict = {}
|
||||
self._service_clients: dict = {}
|
||||
@@ -106,11 +111,16 @@ class CobotWebNode(Node):
|
||||
|
||||
_bridge: CobotWebNode = None
|
||||
|
||||
|
||||
def set_bridge(node: CobotWebNode) -> None:
|
||||
global _bridge
|
||||
_bridge = node
|
||||
|
||||
|
||||
def init_ros_node() -> None:
|
||||
global _bridge
|
||||
rclpy.init()
|
||||
_bridge = CobotWebNode()
|
||||
|
||||
thread = threading.Thread(target=rclpy.spin, args=(_bridge,), daemon=True)
|
||||
thread.start()
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<exec_depend>python3-fastapi</exec_depend>
|
||||
<exec_depend>python3-uvicorn</exec_depend>
|
||||
<exec_depend>python3-multipart</exec_depend>
|
||||
<exec_depend>tf2_ros</exec_depend>
|
||||
<exec_depend>tf2_py</exec_depend>
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ setup(
|
||||
install_requires=[
|
||||
'setuptools',
|
||||
'fastapi',
|
||||
'uvicorn[standard]'
|
||||
'uvicorn[standard]',
|
||||
'python-multipart',
|
||||
],
|
||||
zip_safe=True,
|
||||
maintainer='daniel',
|
||||
|
||||
Reference in New Issue
Block a user