118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
import asyncio
|
||
import os
|
||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
||
from fastapi.staticfiles import StaticFiles
|
||
import logging
|
||
# import threading # ROS2相关,已注释
|
||
# import rclpy # ROS2相关,已注释
|
||
|
||
from .models import GeneratePlanRequest, ExecuteMissionRequest, DebugStageRequest
|
||
from .websocket_manager import websocket_manager
|
||
from .py_tree_generator import py_tree_generator
|
||
# from .ros2_client import MissionActionClient # ROS2相关,已注释
|
||
|
||
# --- Application Setup ---
|
||
app = FastAPI(
|
||
title="Drone Backend Service",
|
||
description="Handles mission planning, generation, and execution for the drone.",
|
||
version="1.0.0",
|
||
)
|
||
|
||
# --- Mount Static Files for Visualizations ---
|
||
static_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'generated_visualizations'))
|
||
app.mount("/static", StaticFiles(directory=static_dir), name="static")
|
||
|
||
# --- ROS2 Node and Client Initialization ---
|
||
# ROS2相关代码已注释,项目已与ROS2解耦
|
||
# rclpy.init()
|
||
# ros2_client = MissionActionClient()
|
||
|
||
# def run_ros2_node():
|
||
# """Spins the ROS2 node in a dedicated thread."""
|
||
# logging.info("Starting to spin ROS2 node...")
|
||
# rclpy.spin(ros2_client)
|
||
# logging.info("ROS2 node has stopped spinning.")
|
||
|
||
# --- API Endpoints ---
|
||
|
||
@app.post("/generate_plan", response_model=dict)
|
||
async def generate_plan_endpoint(request: GeneratePlanRequest):
|
||
"""
|
||
Receives a user prompt and returns a generated `py_tree.json` with a visualization URL.
|
||
"""
|
||
try:
|
||
pytree_dict = await py_tree_generator.generate(request.user_prompt, drone_state=request.drone_state)
|
||
return pytree_dict
|
||
except RuntimeError as e:
|
||
return {"error": str(e)}
|
||
|
||
@app.post("/debug_stage", response_model=dict)
|
||
async def debug_stage_endpoint(request: DebugStageRequest):
|
||
"""
|
||
Stage 分阶段调试:运行到指定 stage 并返回该 stage 的输出。
|
||
target_stage: 1=TaskUnderstanding, 2=ContextBinding, 3=BTDraft, 4=MiddlewareResolution, 5=MicroFilling, 6=ValidateAndPostprocess
|
||
"""
|
||
try:
|
||
result = py_tree_generator.run_debug_stage(
|
||
user_prompt=request.user_prompt,
|
||
drone_state=request.drone_state,
|
||
target_stage=request.target_stage,
|
||
)
|
||
return result
|
||
except Exception as e:
|
||
logging.exception("debug_stage 执行异常")
|
||
return {"error": str(e)}
|
||
|
||
|
||
@app.post("/execute_mission", response_model=dict)
|
||
async def execute_mission_endpoint(request: ExecuteMissionRequest):
|
||
"""
|
||
Receives a `py_tree.json` and sends it to the drone for execution.
|
||
ROS2相关功能已注释,项目已与ROS2解耦。
|
||
"""
|
||
# ROS2相关代码已注释
|
||
# ros2_client.send_goal(request.py_tree)
|
||
logging.warning("execute_mission endpoint called but ROS2 is disabled. Mission execution is not available.")
|
||
return {"status": "execution_disabled", "message": "ROS2 integration is disabled. Mission execution is not available."}
|
||
|
||
@app.websocket("/ws/status")
|
||
async def websocket_endpoint(websocket: WebSocket):
|
||
"""
|
||
Handles the WebSocket connection for real-time status updates.
|
||
"""
|
||
await websocket_manager.connect(websocket)
|
||
try:
|
||
while True:
|
||
await websocket.receive_text()
|
||
except WebSocketDisconnect:
|
||
websocket_manager.disconnect(websocket)
|
||
logging.info("Client disconnected from WebSocket.")
|
||
|
||
|
||
# --- Server Lifecycle ---
|
||
|
||
@app.on_event("startup")
|
||
async def startup_event():
|
||
"""
|
||
On startup, get the current asyncio event loop and pass it to the websocket manager.
|
||
ROS2相关功能已注释,项目已与ROS2解耦。
|
||
"""
|
||
# Configure WebSocket Manager
|
||
loop = asyncio.get_running_loop()
|
||
websocket_manager.set_loop(loop)
|
||
logging.info("WebSocket event loop configured.")
|
||
|
||
# ROS2相关代码已注释
|
||
# Start ROS2 node in a background thread
|
||
# ros2_thread = threading.Thread(target=run_ros2_node, daemon=True)
|
||
# ros2_thread.start()
|
||
# logging.info("ROS2 node thread started.")
|
||
|
||
@app.on_event("shutdown")
|
||
async def shutdown_event():
|
||
logging.info("Backend service shutting down.")
|
||
# ROS2相关代码已注释
|
||
# ros2_client.destroy_node()
|
||
# rclpy.shutdown()
|
||
# logging.info("ROS2 node shut down successfully.")
|