代码内容转移
This commit is contained in:
266
README.md
Normal file
266
README.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# 无人机自然语言控制项目
|
||||
|
||||
本项目构建了一个完整的无人机自然语言控制系统,集成了检索增强生成(RAG)知识库、大型语言模型(LLM)、FastAPI后端服务和ROS2通信,最终实现通过自然语言指令控制无人机执行复杂任务。
|
||||
|
||||
## 项目结构
|
||||
|
||||
项目被清晰地划分为几个核心模块:
|
||||
|
||||
```
|
||||
.
|
||||
├── backend_service/
|
||||
│ ├── src/ # FastAPI应用核心代码
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── main.py # 应用主入口,提供Web API
|
||||
│ │ ├── py_tree_generator.py # RAG与LLM集成,生成py_tree
|
||||
│ │ ├── ...
|
||||
│ ├── generated_visualizations/ # 存放最新生成的py_tree可视化图像
|
||||
│ └── requirements.txt # 后端服务的Python依赖
|
||||
│
|
||||
├── tools/
|
||||
│ ├── map/ # 【数据源】存放原始地图文件(如.world, .json)
|
||||
│ ├── knowledge_base/ # 【处理后】存放build_knowledge_base.py生成的.ndjson文件
|
||||
│ ├── vector_store/ # 【数据库】存放最终的ChromaDB向量数据库
|
||||
│ ├── build_knowledge_base.py # 【步骤1】用于将原始数据转换为自然语言知识
|
||||
│ └── ingest.py # 【步骤2】用于将自然语言知识摄入向量数据库
|
||||
│
|
||||
├── drone_interfaces/ # ROS2接口定义 (保持不变)
|
||||
└── docs/
|
||||
└── README.md # 本说明文件
|
||||
```
|
||||
|
||||
## 核心配置:Orin IP 地址
|
||||
|
||||
**重要提示:** 本项目的后端服务和知识库工具需要与在NVIDIA Jetson Orin设备上运行的服务进行通信(嵌入模型和LLM推理服务)。
|
||||
|
||||
在使用前,您必须配置正确的Orin设备IP地址。您可以通过以下两种方式之一进行设置:
|
||||
|
||||
1. **设置环境变量 (推荐)**:
|
||||
在您的终端中设置一个名为 `ORIN_IP` 的环境变量。
|
||||
```bash
|
||||
export ORIN_IP="192.168.1.100" # 请替换为您的Orin设备的实际IP地址
|
||||
```
|
||||
脚本会优先使用这个环境变量。
|
||||
|
||||
2. **直接修改脚本**:
|
||||
如果您不想设置环境变量,可以打开 `tools/ingest.py` 和 `backend_service/src/py_tree_generator.py` 文件,找到 `orin_ip = os.getenv("ORIN_IP", "...")` 这样的行,并将默认的IP地址修改为您的Orin设备的实际IP地址。
|
||||
|
||||
**在继续后续步骤之前,请务必完成此项配置。**
|
||||
|
||||
---
|
||||
|
||||
## 工作流程
|
||||
|
||||
整个系统的工作流程分为两个主要阶段:
|
||||
|
||||
1. **知识库构建(一次性设置)**: 将环境信息、无人机能力等知识加工并存入向量数据库。
|
||||
2. **后端服务运行与交互**: 启动主服务,通过API接收指令、生成并执行任务。
|
||||
|
||||
### 阶段一:环境设置与编译
|
||||
|
||||
此阶段为项目准备好运行环境,仅需在初次配置或依赖变更时执行。一个稳定、隔离且兼容的环境是所有后续步骤成功的基础。
|
||||
|
||||
#### 1. 创建Conda环境 (关键步骤)
|
||||
|
||||
为了从根源上避免本地Python环境与系统ROS 2环境的库版本冲突(特别是Python版本和C++标准库),我们**必须**使用Conda创建一个干净、隔离且版本精确的虚拟环境。
|
||||
|
||||
```bash
|
||||
# 1. 创建一个使用Python 3.10的新环境。
|
||||
# --name backend: 指定环境名称。
|
||||
# python=3.10: 指定Python版本,必须与ROS 2 Humble要求的版本一致。
|
||||
# --channel conda-forge: 使用conda-forge社区源,其包通常有更好的兼容性。
|
||||
# --no-default-packages: 关键!不安装Conda默认的包(如libgcc),避免与系统ROS 2的C++库冲突。
|
||||
conda create --name backend --channel conda-forge --no-default-packages python=3.10
|
||||
|
||||
# 2. 激活新创建的环境
|
||||
conda activate backend
|
||||
```
|
||||
|
||||
#### 2. 安装所有Python依赖
|
||||
|
||||
在激活`backend`环境后,使用`pip`一次性安装所有依赖。`requirements.txt`已包含**运行时**(如fastapi, rclpy)和**编译时**(如empy, catkin-pkg, lark)所需的所有库。
|
||||
|
||||
```bash
|
||||
# 确保在项目根目录 (drone/) 下执行
|
||||
pip install -r backend_service/requirements.txt
|
||||
```
|
||||
|
||||
#### 3. 编译ROS 2接口
|
||||
|
||||
为了让后端服务能够像导入普通Python包一样导入我们自定义的Action接口 (`drone_interfaces`),你需要先使用`colcon`对其进行编译。
|
||||
|
||||
```bash
|
||||
# 确保在项目根目录 (drone/) 下执行
|
||||
colcon build
|
||||
```
|
||||
成功后,您会看到`build/`, `install/`, `log/`三个新目录。这一步会将`.action`文件转换为Python和C++代码。
|
||||
|
||||
---
|
||||
|
||||
### 阶段二:数据处理流水线
|
||||
|
||||
此阶段为RAG系统准备数据,让LLM能够理解任务环境。
|
||||
|
||||
#### 1. 准备原始数据
|
||||
|
||||
将你的原始数据文件(例如,`.world`, `.json` 文件等)放入 `tools/map/` 目录中。
|
||||
|
||||
#### 2. 数据预处理
|
||||
|
||||
运行脚本将原始数据“翻译”成自然语言知识。
|
||||
|
||||
```bash
|
||||
# 确保在项目根目录 (drone/) 下,并已激活backend环境
|
||||
cd tools
|
||||
python build_knowledge_base.py
|
||||
```
|
||||
该脚本会扫描 `tools/map/` 目录,并在 `tools/knowledge_base/` 目录下生成对应的 `_knowledge.ndjson` 文件。
|
||||
|
||||
#### 3. 数据入库(Ingestion)
|
||||
|
||||
运行脚本将处理好的知识加载到向量数据库中。
|
||||
|
||||
```bash
|
||||
# 仍在tools/目录下执行
|
||||
python ingest.py
|
||||
```
|
||||
该脚本会自动扫描 `tools/knowledge_base/` 目录,并将数据存入 `tools/vector_store/` 目录中。
|
||||
|
||||
---
|
||||
|
||||
### 阶段三:服务启动与测试
|
||||
|
||||
完成前两个阶段后,即可启动并测试后端服务。
|
||||
|
||||
#### 1. 启动后端服务
|
||||
|
||||
启动服务的关键在于**按顺序激活环境**:先激活ROS 2工作空间,再激活Conda环境。
|
||||
|
||||
```bash
|
||||
# 1. 切换到项目根目录
|
||||
cd /path/to/your/drone
|
||||
|
||||
# 2. 激活ROS 2编译环境
|
||||
# 作用:将我们编译好的`drone_interfaces`包的路径告知系统,否则Python会报`ModuleNotFoundError`。
|
||||
# 注意:此命令必须在每次打开新终端时执行一次。
|
||||
source install/setup.bash
|
||||
|
||||
# 3. 激活Conda Python环境
|
||||
conda activate backend
|
||||
|
||||
# 4. 启动FastAPI服务
|
||||
cd backend_service/
|
||||
uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
当您看到日志中出现 `Uvicorn running on http://0.0.0.0:8000` 时,表示服务已成功启动。
|
||||
|
||||
#### 2. 运行API接口测试
|
||||
|
||||
我们提供了一个脚本来验证核心的“任务生成”功能。
|
||||
|
||||
**打开一个新的终端**,并执行以下命令:
|
||||
|
||||
```bash
|
||||
# 1. 切换到项目根目录
|
||||
cd /path/to/your/drone
|
||||
|
||||
# 2. 激活Conda环境
|
||||
conda activate backend
|
||||
|
||||
# 3. 运行测试脚本
|
||||
cd tools/
|
||||
python test_api.py
|
||||
```
|
||||
如果一切正常,您将在终端看到一系列 `PASS` 信息,以及从服务器返回的Pytree JSON。
|
||||
|
||||
#### 3. API接口使用说明
|
||||
|
||||
---
|
||||
|
||||
## 故障排除 / 常见问题 (FAQ)
|
||||
|
||||
以下是在配置和运行此项目时可能遇到的一些常见问题及其解决方案。
|
||||
|
||||
#### **Q1: 启动服务时报错 `ModuleNotFoundError: No module named 'drone_interfaces'`**
|
||||
|
||||
- **原因**: 您当前的终端环境没有加载ROS 2工作空间的路径。仅仅激活Conda环境是不够的。
|
||||
- **解决方案**: 严格遵循“启动后端服务”章节的说明,在激活Conda环境**之前**,必须先运行 `source install/setup.bash` 命令。
|
||||
|
||||
#### **Q2: `colcon build` 编译失败,提示 `ModuleNotFoundError: No module named 'em'`, `'catkin_pkg'`, 或 `'lark'`**
|
||||
|
||||
- **原因**: 您的Python环境中缺少ROS 2编译代码时所必需的依赖包。
|
||||
- **解决方案**: 我们已将所有已知的编译时依赖(`empy`, `catkin-pkg`, `lark`等)添加到了`requirements.txt`中。请确保您已激活正确的Conda环境,然后运行 `pip install -r backend_service/requirements.txt` 来安装它们。
|
||||
|
||||
#### **Q3: 启动服务时报错 `ImportError: ... GLIBCXX_... not found` 或 `ModuleNotFoundError: No module named 'rclpy._rclpy_pybind11'`**
|
||||
|
||||
- **原因**: 您的Conda环境与系统ROS 2环境存在核心库冲突。最常见的原因是Python版本不匹配(例如,Conda是Python 3.11而ROS 2 Humble需要3.10),或者Conda自带的C++库与系统库冲突。
|
||||
- **解决方案**: 这是最棘手的环境问题。最可靠的解决方法是彻底删除当前的Conda环境 (`conda env remove --name backend`),然后严格按照本文档「环境设置」章节的说明,用正确的命令 (`conda create --name backend --channel conda-forge --no-default-packages python=3.10`) 重建一个干净、兼容的环境。
|
||||
|
||||
#### **Q4: 服务启动时,日志显示正在从网络上下载模型(例如 `all-MiniLM-L6-v2`)**
|
||||
|
||||
- **原因**: 后端服务在连接向量数据库时,没有正确指定使用远程嵌入模型,导致ChromaDB退回到默认的、需要下载模型的本地嵌入函数。
|
||||
- **解决方案**: 此问题在当前代码中**已被修复**。`backend_service/src/py_tree_generator.py`现在会正确地将远程嵌入函数实例传递给ChromaDB。如果您在自己的代码中遇到此问题,请检查您的`get_collection`调用。
|
||||
|
||||
#### **Q5: 服务启动时,日志停在 `waiting for action server...`,无法访问API**
|
||||
|
||||
- **原因**: 代码中存在阻塞式的`wait_for_server()`调用,它会一直等待直到无人机端的Action服务器上线,从而卡住了Web服务的启动流程。
|
||||
- **解决方案**: 此问题在当前代码中**已被修复**。`backend_service/src/ros2_client.py`现在使用非阻塞的方式初始化,并在发送任务时检查服务器是否可用。
|
||||
|
||||
##### **A. 生成任务计划**
|
||||
|
||||
接收自然语言指令,返回生成的行为树(py_tree)JSON。
|
||||
|
||||
- **Endpoint**: `POST /generate_plan`
|
||||
- **Request Body**:
|
||||
```json
|
||||
{
|
||||
"user_prompt": "无人机起飞到10米,然后前往机库,最后降落。"
|
||||
}
|
||||
```
|
||||
- **Success Response**:
|
||||
```json
|
||||
{
|
||||
"root": { ... },
|
||||
"plan_id": "some-unique-id",
|
||||
"visualization_url": "/static/py_tree.png"
|
||||
}
|
||||
```
|
||||
|
||||
##### **B. 查看任务可视化**
|
||||
|
||||
获取最新生成的行为树的可视化图像。
|
||||
|
||||
- **Endpoint**: `GET /static/py_tree.png`
|
||||
- **Usage**: 在浏览器中直接打开 `http://<服务器IP>:8000/static/py_tree.png` 即可查看。每次成功调用 `/generate_plan` 后,该图像都会被更新。
|
||||
|
||||
##### **C. 执行任务**
|
||||
|
||||
接收一个py_tree JSON,下发给无人机执行(当前为模拟执行)。
|
||||
|
||||
- **Endpoint**: `POST /execute_mission`
|
||||
- **Request Body**: (使用 `/generate_plan` 返回的 `root` 对象)
|
||||
```json
|
||||
{
|
||||
"py_tree": {
|
||||
"root": { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"status": "execution_started"
|
||||
}
|
||||
```
|
||||
|
||||
##### **D. 接收实时状态**
|
||||
|
||||
通过WebSocket连接,实时接收无人机在执行任务时的状态反馈。
|
||||
|
||||
- **Endpoint**: `WS /ws/status`
|
||||
- **Usage**: 使用任意WebSocket客户端连接到 `ws://<服务器IP>:8000/ws/status`。当任务执行时,服务器会主动推送JSON消息,例如:
|
||||
```json
|
||||
{"node_id": "takeoff_node_1", "status": 0} // 0: RUNNING
|
||||
{"node_id": "takeoff_node_1", "status": 1} // 1: SUCCESS
|
||||
```
|
||||
|
||||
BIN
backend_service/generated_visualizations/py_tree.png
Normal file
BIN
backend_service/generated_visualizations/py_tree.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
19
backend_service/requirements.txt
Normal file
19
backend_service/requirements.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
fastapi
|
||||
uvicorn
|
||||
python-multipart
|
||||
pydantic
|
||||
websockets
|
||||
openai
|
||||
chromadb
|
||||
jsonschema
|
||||
graphviz
|
||||
rclpy
|
||||
unstructured[all]
|
||||
|
||||
# ROS 2 Build Dependencies
|
||||
empy==3.3.4
|
||||
catkin-pkg
|
||||
lark
|
||||
colcon-common-extensions
|
||||
vcstool
|
||||
rosdep
|
||||
0
backend_service/src/__init__.py
Normal file
0
backend_service/src/__init__.py
Normal file
BIN
backend_service/src/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
backend_service/src/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
backend_service/src/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/main.cpython-310.pyc
Normal file
BIN
backend_service/src/__pycache__/main.cpython-310.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/main.cpython-313.pyc
Normal file
BIN
backend_service/src/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/models.cpython-310.pyc
Normal file
BIN
backend_service/src/__pycache__/models.cpython-310.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/models.cpython-313.pyc
Normal file
BIN
backend_service/src/__pycache__/models.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
backend_service/src/__pycache__/ros2_client.cpython-310.pyc
Normal file
BIN
backend_service/src/__pycache__/ros2_client.cpython-310.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/__pycache__/ros2_client.cpython-313.pyc
Normal file
BIN
backend_service/src/__pycache__/ros2_client.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
93
backend_service/src/main.py
Normal file
93
backend_service/src/main.py
Normal file
@@ -0,0 +1,93 @@
|
||||
import asyncio
|
||||
import os
|
||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import logging
|
||||
import threading
|
||||
import rclpy
|
||||
|
||||
from .models import GeneratePlanRequest, ExecuteMissionRequest
|
||||
from .websocket_manager import websocket_manager
|
||||
from .py_tree_generator import py_tree_generator
|
||||
from .ros2_client import MissionActionClient
|
||||
|
||||
# --- 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 ---
|
||||
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)
|
||||
return pytree_dict
|
||||
except RuntimeError as e:
|
||||
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_client.send_goal(request.py_tree)
|
||||
return {"status": "execution_started"}
|
||||
|
||||
@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.
|
||||
Also, start the ROS2 node in a background thread.
|
||||
"""
|
||||
# Configure WebSocket Manager
|
||||
loop = asyncio.get_running_loop()
|
||||
websocket_manager.set_loop(loop)
|
||||
logging.info("WebSocket event loop configured.")
|
||||
|
||||
# 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_client.destroy_node()
|
||||
rclpy.shutdown()
|
||||
logging.info("ROS2 node shut down successfully.")
|
||||
12
backend_service/src/models.py
Normal file
12
backend_service/src/models.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Dict, Any
|
||||
|
||||
class GeneratePlanRequest(BaseModel):
|
||||
user_prompt: str
|
||||
|
||||
class ExecuteMissionRequest(BaseModel):
|
||||
py_tree: Dict[str, Any]
|
||||
|
||||
class StatusUpdate(BaseModel):
|
||||
node_id: str
|
||||
status: int
|
||||
143
backend_service/src/prompts/system_prompt.txt
Normal file
143
backend_service/src/prompts/system_prompt.txt
Normal file
@@ -0,0 +1,143 @@
|
||||
你是一个无人机任务规划专家。你的**唯一**任务是根据用户提供的任务指令和参考知识,生成一个结构化、可执行的行为树(Pytree)。
|
||||
|
||||
你的输出**必须**是一个严格的、单一的JSON对象,不包含任何形式的解释、总结或自然语言描述。
|
||||
|
||||
---
|
||||
|
||||
#### 1. 可用节点定义 (必须遵守)
|
||||
|
||||
你**必须**严格从以下JSON定义的列表中选择节点来构建行为树。不允许幻想或使用任何未定义的节点。
|
||||
|
||||
```json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"name": "takeoff",
|
||||
"description": "无人机从当前位置垂直起飞到指定的海拔高度。",
|
||||
"params": {
|
||||
"altitude": "float, 目标海拔高度(米)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fly_to_waypoint",
|
||||
"description": "导航至一个WGS84坐标航点。无人机到达航点后该动作才算完成。",
|
||||
"params": {
|
||||
"latitude": "float, 目标纬度",
|
||||
"longitude": "float, 目标经度",
|
||||
"altitude": "float, 目标海拔高度(米)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "loiter_for_duration",
|
||||
"description": "在当前位置上空悬停或盘旋一段时间。",
|
||||
"params": {
|
||||
"duration": "float, 悬停时间(秒)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "land_at_position",
|
||||
"description": "在当前位置降落。",
|
||||
"params": {}
|
||||
},
|
||||
{
|
||||
"name": "return_to_launch",
|
||||
"description": "自动返航并降落到起飞点。",
|
||||
"params": {}
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"control_flow": [
|
||||
{
|
||||
"name": "Sequence",
|
||||
"description": "序列节点,按顺序执行其子节点。只有当所有子节点都成功时,它才成功。",
|
||||
"params": {},
|
||||
"children": "array, 包含按顺序执行的子节点"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. JSON结构规范 (必须遵守)
|
||||
|
||||
生成的JSON对象**必须**有一个名为`root`的键,其值是一个有效的行为树节点对象。每个节点都必须包含 "type" 和 "name" 字段。
|
||||
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "string, 'action' 或 'Sequence'",
|
||||
"name": "string, 来自上方可用节点列表",
|
||||
"params": "object, 包含所需的参数",
|
||||
"children": "array, (可选) 包含子节点对象"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 3. 如何使用参考知识 (必须遵守)
|
||||
|
||||
当系统提供“参考知识”时,你**必须**使用其中的坐标来填充`params`字段。例如,如果任务是“飞到教学楼”,并且参考知识中提供了“教学楼”的坐标是 `(纬度: 31.2304, 经度: 121.4737)`,那么你的 `fly_to_waypoint` 节点应该写成:
|
||||
|
||||
`"params": {"latitude": 31.2304, "longitude": 121.4737, "altitude": 50.0}` (高度为默认或指定值)
|
||||
|
||||
---
|
||||
|
||||
#### 4. 任务规划示例 (Few-shot Learning)
|
||||
|
||||
以下是一些完整的任务规划示例,请学习并模仿它们的思考过程和输出格式。
|
||||
|
||||
##### 示例 1
|
||||
|
||||
**用户任务:**
|
||||
"无人机起飞,飞到教学楼进行30秒的勘察,然后返航降落。"
|
||||
|
||||
**参考知识:**
|
||||
"地理元素 '教学楼' (ID: 123) 是一个 建筑。 其中心位置坐标大约为 (纬度: 31.2304, 经度: 121.4737)。"
|
||||
|
||||
**生成的Pytree:**
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "Mission",
|
||||
"children": [
|
||||
{ "type": "action", "name": "takeoff", "params": { "altitude": 20.0 } },
|
||||
{ "type": "action", "name": "fly_to_waypoint", "params": { "latitude": 31.2304, "longitude": 121.4737, "altitude": 20.0 } },
|
||||
{ "type": "action", "name": "loiter_for_duration", "params": { "duration": 30.0 } },
|
||||
{ "type": "action", "name": "return_to_launch", "params": {} }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### 示例 2
|
||||
|
||||
**用户任务:**
|
||||
"飞到图书馆,然后去体育馆,最后在体育馆的位置降落。"
|
||||
|
||||
**参考知识:**
|
||||
"地理元素 '图书馆' (ID: 456) 是一个 建筑。 其中心位置坐标大约为 (纬度: 31.2315, 经度: 121.4758)。
|
||||
地理元素 '体育馆' (ID: 789) 是一个 建筑。 其中心位置坐标大约为 (纬度: 31.2330, 经度: 121.4780)。"
|
||||
|
||||
**生成的Pytree:**
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "Mission",
|
||||
"children": [
|
||||
{ "type": "action", "name": "takeoff", "params": { "altitude": 50.0 } },
|
||||
{ "type": "action", "name": "fly_to_waypoint", "params": { "latitude": 31.2315, "longitude": 121.4758, "altitude": 50.0 } },
|
||||
{ "type": "action", "name": "fly_to_waypoint", "params": { "latitude": 31.2330, "longitude": 121.4780, "altitude": 50.0 } },
|
||||
{ "type": "action", "name": "land_at_position", "params": {} }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
#### 5. 最终指令
|
||||
|
||||
现在,请严格按照以上规则和示例,根据用户提供的最新任务和参考知识,生成行为树JSON。直接输出JSON对象,不要有任何其他内容。
|
||||
330
backend_service/src/py_tree_generator.py
Normal file
330
backend_service/src/py_tree_generator.py
Normal file
@@ -0,0 +1,330 @@
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
import uuid
|
||||
import re
|
||||
from typing import Dict, Any, Optional, Set
|
||||
|
||||
import chromadb
|
||||
import openai
|
||||
from openai import OpenAIError
|
||||
import jsonschema
|
||||
import requests
|
||||
|
||||
# --- 自定义远程嵌入函数 (与ingest.py中定义一致) ---
|
||||
from chromadb.api.types import Documents, EmbeddingFunction, Embeddings, Embeddable
|
||||
|
||||
class RemoteEmbeddingFunction(EmbeddingFunction[Embeddable]):
|
||||
def __init__(self, api_url: str):
|
||||
self._api_url = api_url
|
||||
|
||||
def __call__(self, input: Embeddable) -> Embeddings:
|
||||
if not isinstance(input, list) or not all(isinstance(doc, str) for doc in input):
|
||||
return []
|
||||
try:
|
||||
response = requests.post(
|
||||
self._api_url,
|
||||
json={"input": input},
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json().get("data", [])
|
||||
if not data:
|
||||
return []
|
||||
return [item['embedding'] for item in data]
|
||||
except Exception as e:
|
||||
logging.error(f"调用远程嵌入API时出错: {e}")
|
||||
return []
|
||||
|
||||
# --- 日志记录设置 ---
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
# VALIDATION LOGIC (from utils/validation.py)
|
||||
# ==============================================================================
|
||||
|
||||
def _parse_allowed_nodes_from_prompt(prompt_text: str) -> tuple[Set[str], Set[str]]:
|
||||
"""
|
||||
从系统提示词中解析出允许的行动和条件节点。
|
||||
"""
|
||||
try:
|
||||
# 使用正则表达式查找JSON代码块
|
||||
match = re.search(r"```json\s*({.*?})\s*```", prompt_text, re.DOTALL)
|
||||
if not match:
|
||||
logging.error("在系统提示词中未找到可用节点的JSON定义块。")
|
||||
return set(), set()
|
||||
|
||||
json_str = match.group(1)
|
||||
allowed_nodes = json.loads(json_str)
|
||||
|
||||
# 从对象列表中提取节点名称
|
||||
actions = {action['name'] for action in allowed_nodes.get("actions", []) if 'name' in action}
|
||||
conditions = {condition['name'] for condition in allowed_nodes.get("conditions", []) if 'name' in condition}
|
||||
|
||||
if not actions:
|
||||
logging.warning("关键错误:从提示词解析出的行动节点列表为空,无法生成任何有效任务。")
|
||||
|
||||
return actions, conditions
|
||||
|
||||
except json.JSONDecodeError:
|
||||
logging.error("解析系统提示词中的JSON时失败。请检查格式。")
|
||||
return set(), set()
|
||||
except Exception as e:
|
||||
logging.error(f"解析可用节点时发生未知错误: {e}")
|
||||
return set(), set()
|
||||
|
||||
def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> dict:
|
||||
"""
|
||||
根据允许的行动和条件节点,动态生成一个JSON Schema。
|
||||
"""
|
||||
# 递归节点定义
|
||||
node_definition = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"type": "string", "enum": ["action", "condition", "Sequence", "Selector"]},
|
||||
"name": {"type": "string"},
|
||||
"params": {"type": "object"},
|
||||
"children": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/definitions/node"}
|
||||
}
|
||||
},
|
||||
"required": ["type", "name"],
|
||||
# 使用 allOf 和 if/then 来实现基于'type'字段的条件性'name'验证
|
||||
"allOf": [
|
||||
{
|
||||
"if": {"properties": {"type": {"const": "action"}}},
|
||||
"then": {"properties": {"name": {"enum": sorted(list(allowed_actions))}}}
|
||||
},
|
||||
{
|
||||
"if": {"properties": {"type": {"const": "condition"}}},
|
||||
"then": {"properties": {"name": {"enum": sorted(list(allowed_conditions))}}}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# 完整的Schema结构
|
||||
schema = {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Pytree",
|
||||
"definitions": {
|
||||
"node": node_definition
|
||||
},
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"root": { "$ref": "#/definitions/node" }
|
||||
},
|
||||
"required": ["root"]
|
||||
}
|
||||
return schema
|
||||
|
||||
def _validate_pytree_with_schema(pytree_instance: dict, schema: dict) -> bool:
|
||||
"""
|
||||
使用JSON Schema验证给定的Pytree实例。
|
||||
"""
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_instance, schema=schema)
|
||||
logging.info("验证成功!Pytree格式和内容均符合规范。")
|
||||
return True
|
||||
except jsonschema.ValidationError as e:
|
||||
logging.warning("--- Pytree验证失败 ---")
|
||||
logging.warning(f"错误信息: {e.message}")
|
||||
error_path = list(e.path)
|
||||
logging.warning(f"错误路径: {' -> '.join(map(str, error_path)) if error_path else '根节点'}")
|
||||
logging.warning(f"出错的实例部分: {e.instance}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"进行JSON Schema验证时发生未知错误: {e}")
|
||||
return False
|
||||
|
||||
# ==============================================================================
|
||||
# VISUALIZATION LOGIC (from utils/visualization.py)
|
||||
# ==============================================================================
|
||||
|
||||
def _visualize_pytree(node: Dict, file_path: str):
|
||||
"""
|
||||
使用Graphviz将Pytree字典可视化,并保存到指定路径。
|
||||
"""
|
||||
try:
|
||||
from graphviz import Digraph
|
||||
except ImportError:
|
||||
logging.critical("错误:未安装graphviz库。请运行: pip install graphviz")
|
||||
return
|
||||
|
||||
dot = Digraph('Pytree', comment='Drone Mission Plan')
|
||||
dot.attr('node', shape='box', style='rounded,filled', fontname='helvetica')
|
||||
dot.attr(rankdir='TB', label='Drone Mission Plan', fontsize='20')
|
||||
|
||||
_add_nodes_and_edges(node, dot)
|
||||
|
||||
try:
|
||||
# 保存为 .png 文件,并自动删除源码 .gv 文件
|
||||
output_path = dot.render(file_path, format='png', cleanup=True, view=False)
|
||||
logging.info("--- 任务树可视化成功 ---")
|
||||
logging.info(f"图形已保存到: {output_path}")
|
||||
except Exception as e:
|
||||
logging.error("--- 错误:生成可视化图形失败 ---")
|
||||
logging.error("请确保您的系统已经正确安装了Graphviz图形库。")
|
||||
logging.error(f"错误详情: {e}")
|
||||
|
||||
def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
||||
"""递归辅助函数,用于添加节点和边。"""
|
||||
|
||||
# 为每个节点创建一个唯一的ID
|
||||
current_id = str(id(node))
|
||||
|
||||
# 准备节点标签
|
||||
node_label = f"<{node['name']}<br/><i>({node['type']})</i>"
|
||||
if node.get('params'):
|
||||
params_str = json.dumps(node.get('params'))
|
||||
node_label += f"<br/><font point-size='10'>params: {params_str}</font>"
|
||||
node_label += ">"
|
||||
|
||||
# 根据类型设置节点样式
|
||||
node_type = node.get('type', '').lower()
|
||||
if node_type == 'action':
|
||||
dot.node(current_id, label=node_label, shape='box', color="#cde4ff")
|
||||
elif node_type == 'condition':
|
||||
dot.node(current_id, label=node_label, shape='diamond', color="#fff2cc")
|
||||
else: # Sequence, Selector, etc.
|
||||
dot.node(current_id, label=node_label, shape='ellipse', color='#e6e6e6')
|
||||
|
||||
# 连接父节点
|
||||
if parent_id:
|
||||
dot.edge(parent_id, current_id)
|
||||
|
||||
# 递归处理子节点
|
||||
last_child_id = current_id
|
||||
for child in node.get("children", []):
|
||||
# 对于序列,边是连续的;对于选择器,所有子节点都连接到父节点
|
||||
if node_type in ['sequence']:
|
||||
last_child_id = _add_nodes_and_edges(child, dot, last_child_id)
|
||||
else: # Selector, Parallel
|
||||
_add_nodes_and_edges(child, dot, current_id)
|
||||
|
||||
return current_id
|
||||
|
||||
# ==============================================================================
|
||||
# CORE PYTREE GENERATOR CLASS
|
||||
# ==============================================================================
|
||||
|
||||
class PyTreeGenerator:
|
||||
def __init__(self):
|
||||
self.base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
self.prompts_dir = os.path.join(self.base_dir, 'prompts')
|
||||
|
||||
# Updated output directory for visualizations
|
||||
self.vis_dir = os.path.abspath(os.path.join(self.base_dir, '..', 'generated_visualizations'))
|
||||
os.makedirs(self.vis_dir, exist_ok=True)
|
||||
|
||||
self.system_prompt = self._load_prompt("system_prompt.txt")
|
||||
|
||||
self.orin_ip = os.getenv("ORIN_IP", "172.101.1.117")
|
||||
self.llm_client = openai.OpenAI(
|
||||
api_key=os.getenv("OPENAI_API_KEY", "sk-no-key-required"),
|
||||
base_url=f"http://{self.orin_ip}:8081/v1"
|
||||
)
|
||||
|
||||
# --- ChromaDB Client Setup ---
|
||||
vector_store_path = os.path.abspath(os.path.join(self.base_dir, '..', '..', 'tools', 'vector_store'))
|
||||
self.chroma_client = chromadb.PersistentClient(path=vector_store_path)
|
||||
|
||||
# Explicitly use the remote embedding function for queries
|
||||
embedding_api_url = f"http://{self.orin_ip}:8090/v1/embeddings"
|
||||
embedding_func = RemoteEmbeddingFunction(api_url=embedding_api_url)
|
||||
|
||||
self.collection = self.chroma_client.get_collection(
|
||||
name="drone_docs",
|
||||
embedding_function=embedding_func
|
||||
)
|
||||
|
||||
allowed_actions, allowed_conditions = _parse_allowed_nodes_from_prompt(self.system_prompt)
|
||||
self.schema = _generate_pytree_schema(allowed_actions, allowed_conditions)
|
||||
|
||||
def _load_prompt(self, file_name: str) -> str:
|
||||
try:
|
||||
with open(os.path.join(self.prompts_dir, file_name), 'r', encoding='utf-8') as f:
|
||||
return f.read()
|
||||
except FileNotFoundError:
|
||||
logging.error(f"提示词文件未找到 -> {file_name}")
|
||||
return ""
|
||||
|
||||
def _retrieve_context(self, query: str) -> Optional[str]:
|
||||
logging.info("--- 开始从向量数据库检索上下文 ---")
|
||||
try:
|
||||
results = self.collection.query(query_texts=[query], n_results=5)
|
||||
retrieved_docs = results.get("documents", [[]])[0]
|
||||
if not retrieved_docs:
|
||||
logging.warning("在向量数据库中没有找到相关的上下文信息。")
|
||||
return None
|
||||
context_str = "\n\n".join(retrieved_docs)
|
||||
logging.info("--- 成功检索到上下文信息 ---")
|
||||
return context_str
|
||||
except Exception as e:
|
||||
logging.error(f"从向量数据库检索时发生错误: {e}")
|
||||
return None
|
||||
|
||||
async def generate(self, user_prompt: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Generates a py_tree.json structure based on the user's prompt.
|
||||
"""
|
||||
logging.info(f"接收到用户请求: {user_prompt}")
|
||||
|
||||
retrieved_context = self._retrieve_context(user_prompt)
|
||||
|
||||
final_user_prompt = user_prompt
|
||||
if retrieved_context:
|
||||
augmentation = (
|
||||
"\n\n---\n"
|
||||
"参考知识:\n"
|
||||
"以下是从知识库中检索到的、与当前任务最相关的信息,请优先参考这些信息来生成行为树:\n"
|
||||
f"{retrieved_context}"
|
||||
"\n---"
|
||||
)
|
||||
final_user_prompt += augmentation
|
||||
else:
|
||||
logging.warning("未检索到上下文或检索失败,将使用原始用户提示词。")
|
||||
|
||||
for attempt in range(3):
|
||||
logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---")
|
||||
try:
|
||||
response = self.llm_client.chat.completions.create(
|
||||
model="local-model",
|
||||
messages=[
|
||||
{"role": "system", "content": self.system_prompt},
|
||||
{"role": "user", "content": final_user_prompt}
|
||||
],
|
||||
temperature=0.1,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
pytree_str = response.choices[0].message.content
|
||||
pytree_dict = json.loads(pytree_str)
|
||||
|
||||
if _validate_pytree_with_schema(pytree_dict, self.schema):
|
||||
logging.info("成功生成并验证了Pytree。")
|
||||
plan_id = str(uuid.uuid4())
|
||||
pytree_dict['plan_id'] = plan_id
|
||||
|
||||
# Generate visualization to a static path
|
||||
vis_filename = "py_tree.png"
|
||||
vis_path = os.path.join(self.vis_dir, vis_filename)
|
||||
_visualize_pytree(pytree_dict['root'], os.path.splitext(vis_path)[0])
|
||||
pytree_dict['visualization_url'] = f"/static/{vis_filename}"
|
||||
|
||||
return pytree_dict
|
||||
else:
|
||||
logging.warning("生成的Pytree验证失败,正在重试...")
|
||||
|
||||
except (OpenAIError, json.JSONDecodeError) as e:
|
||||
logging.error(f"生成Pytree时发生错误: {e}")
|
||||
|
||||
raise RuntimeError("在3次尝试后,仍未能生成一个有效的Pytree。")
|
||||
|
||||
# Create a single instance for the application
|
||||
py_tree_generator = PyTreeGenerator()
|
||||
67
backend_service/src/ros2_client.py
Normal file
67
backend_service/src/ros2_client.py
Normal file
@@ -0,0 +1,67 @@
|
||||
import rclpy
|
||||
from rclpy.action import ActionClient
|
||||
from rclpy.node import Node
|
||||
import json
|
||||
from typing import Dict, Any
|
||||
import logging
|
||||
|
||||
from drone_interfaces.action import ExecuteMission
|
||||
from .websocket_manager import websocket_manager
|
||||
|
||||
class MissionActionClient(Node):
|
||||
"""
|
||||
Interfaces with the drone's `ExecuteMission` ROS2 Action Server.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__('mission_action_client')
|
||||
self._action_client = ActionClient(self, ExecuteMission, 'execute_mission')
|
||||
self.get_logger().info("MissionActionClient initialized.")
|
||||
|
||||
def send_goal(self, py_tree: Dict[str, Any]):
|
||||
"""
|
||||
Sends the mission (py_tree) to the action server.
|
||||
"""
|
||||
if not self._action_client.server_is_ready():
|
||||
self.get_logger().error("Action server not available, goal not sent.")
|
||||
# Optionally, you could broadcast a status update to the frontend here
|
||||
return
|
||||
|
||||
self.get_logger().info("Received request to send goal to drone.")
|
||||
goal_msg = ExecuteMission.Goal()
|
||||
goal_msg.py_tree_json = json.dumps(py_tree)
|
||||
|
||||
self.get_logger().info(f"Sending goal to action server...")
|
||||
send_goal_future = self._action_client.send_goal_async(
|
||||
goal_msg,
|
||||
feedback_callback=self.feedback_callback
|
||||
)
|
||||
|
||||
send_goal_future.add_done_callback(self.goal_response_callback)
|
||||
|
||||
def goal_response_callback(self, future):
|
||||
goal_handle = future.result()
|
||||
if not goal_handle.accepted:
|
||||
self.get_logger().info('Goal rejected :(')
|
||||
return
|
||||
|
||||
self.get_logger().info('Goal accepted :)')
|
||||
|
||||
self._get_result_future = goal_handle.get_result_async()
|
||||
self._get_result_future.add_done_callback(self.get_result_callback)
|
||||
|
||||
def get_result_callback(self, future):
|
||||
result = future.result().result
|
||||
self.get_logger().info(f'Result: {{success: {result.success}, message: {result.message}}}')
|
||||
# Optionally, you can broadcast the final result via WebSocket here
|
||||
|
||||
def feedback_callback(self, feedback_msg):
|
||||
"""
|
||||
This callback is triggered by the action server.
|
||||
It forwards the status to the QGC plugin via the WebSocket manager in a thread-safe manner.
|
||||
"""
|
||||
feedback = feedback_msg.feedback
|
||||
feedback_payload = json.dumps({"node_id": feedback.node_id, "status": feedback.status})
|
||||
self.get_logger().info(f"Received feedback: {feedback_payload}")
|
||||
websocket_manager.broadcast(feedback_payload)
|
||||
|
||||
# Note: The rclpy.init() and spinning of the node will be handled in main.py
|
||||
48
backend_service/src/websocket_manager.py
Normal file
48
backend_service/src/websocket_manager.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import asyncio
|
||||
from typing import List
|
||||
from fastapi import WebSocket
|
||||
import logging
|
||||
|
||||
class ConnectionManager:
|
||||
def __init__(self):
|
||||
self.active_connections: List[WebSocket] = []
|
||||
self.loop: asyncio.AbstractEventLoop | None = None
|
||||
|
||||
def set_loop(self, loop: asyncio.AbstractEventLoop):
|
||||
"""Sets the asyncio event loop."""
|
||||
self.loop = loop
|
||||
|
||||
async def connect(self, websocket: WebSocket):
|
||||
await websocket.accept()
|
||||
self.active_connections.append(websocket)
|
||||
|
||||
def disconnect(self, websocket: WebSocket):
|
||||
self.active_connections.remove(websocket)
|
||||
|
||||
def broadcast(self, message: str):
|
||||
"""
|
||||
Thread-safely broadcasts a message to all active WebSocket connections.
|
||||
This method is designed to be called from a different thread (e.g., a ROS2 callback).
|
||||
"""
|
||||
if not self.loop:
|
||||
logging.error("Event loop not set in ConnectionManager. Cannot broadcast.")
|
||||
return
|
||||
|
||||
# Schedule the coroutine to be executed in the event loop
|
||||
self.loop.call_soon_threadsafe(self._broadcast_in_loop, message)
|
||||
|
||||
def _broadcast_in_loop(self, message: str):
|
||||
"""
|
||||
Helper to run the broadcast coroutine in the correct event loop.
|
||||
"""
|
||||
asyncio.ensure_future(self._broadcast_async(message), loop=self.loop)
|
||||
|
||||
async def _broadcast_async(self, message: str):
|
||||
"""
|
||||
The actual async method that sends messages.
|
||||
"""
|
||||
tasks = [connection.send_text(message) for connection in self.active_connections]
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
# Create a single instance of the manager to be used across the application
|
||||
websocket_manager = ConnectionManager()
|
||||
48
backend_service/uvicorn.log
Normal file
48
backend_service/uvicorn.log
Normal file
@@ -0,0 +1,48 @@
|
||||
2025-07-25 15:08:52,193 - INFO - Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
|
||||
Traceback (most recent call last):
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/bin/uvicorn", line 8, in <module>
|
||||
sys.exit(main())
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/click/core.py", line 1442, in __call__
|
||||
return self.main(*args, **kwargs)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/click/core.py", line 1363, in main
|
||||
rv = self.invoke(ctx)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/click/core.py", line 1226, in invoke
|
||||
return ctx.invoke(self.callback, **ctx.params)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/click/core.py", line 794, in invoke
|
||||
return callback(*args, **kwargs)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/main.py", line 413, in main
|
||||
run(
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/main.py", line 580, in run
|
||||
server.run()
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/server.py", line 67, in run
|
||||
return asyncio.run(self.serve(sockets=sockets))
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/asyncio/runners.py", line 44, in run
|
||||
return loop.run_until_complete(main)
|
||||
File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/server.py", line 71, in serve
|
||||
await self._serve(sockets)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/server.py", line 78, in _serve
|
||||
config.load()
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/config.py", line 436, in load
|
||||
self.loaded_app = import_from_string(self.app)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/uvicorn/importer.py", line 19, in import_from_string
|
||||
module = importlib.import_module(module_str)
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/importlib/__init__.py", line 126, in import_module
|
||||
return _bootstrap._gcd_import(name[level:], package, level)
|
||||
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
|
||||
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
|
||||
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
|
||||
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
|
||||
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
|
||||
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
|
||||
File "/home/huangfuqixun/Chat_QPG/drone/backend_service/src/main.py", line 9, in <module>
|
||||
from .py_tree_generator import py_tree_generator
|
||||
File "/home/huangfuqixun/Chat_QPG/drone/backend_service/src/py_tree_generator.py", line 295, in <module>
|
||||
py_tree_generator = PyTreeGenerator()
|
||||
File "/home/huangfuqixun/Chat_QPG/drone/backend_service/src/py_tree_generator.py", line 210, in __init__
|
||||
self.collection = self.chroma_client.get_collection(name="drone_docs")
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/chromadb/api/client.py", line 192, in get_collection
|
||||
model = self._server.get_collection(
|
||||
File "/home/huangfuqixun/miniconda3/envs/backend/lib/python3.10/site-packages/chromadb/api/rust.py", line 248, in get_collection
|
||||
collection = self.bindings.get_collection(name, tenant, database)
|
||||
chromadb.errors.NotFoundError: Collection [drone_docs] does not exists
|
||||
140
docs/地面站后端开发文档.md
Normal file
140
docs/地面站后端开发文档.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 地面站后端开发文档
|
||||
|
||||
**版本**: 1.0
|
||||
**负责人**: 后端开发团队
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述与目标
|
||||
|
||||
本文档旨在为 **模块二:后端服务** 提供一份完整、清晰的开发与实现指南。后端服务是整个无人机自然语言控制系统的核心枢纽,其主要职责包括:
|
||||
|
||||
1. **接收前端指令**: 通过Web API接收来自QGC插件的自然语言指令。
|
||||
2. **智能任务规划**: 集成并调用RAG(检索增强生成)系统和大型语言模型(LLM),将用户指令转化为结构化的无人机任务(`py_tree.json`)。
|
||||
3. **任务下发与监控**: 通过ROS2 Action将用户确认后的任务下发给无人机执行,并实时接收无人机的执行状态。
|
||||
4. **状态实时反馈**: 通过WebSocket将无人机的执行状态实时、透明地转发给前端QGC插件,实现闭环监控。
|
||||
|
||||
本项目将整合现有零散的脚本和资源,构建一个统一、健壮且可扩展的FastAPI应用程序。
|
||||
|
||||
## 2. 技术栈
|
||||
|
||||
- **Web框架**: FastAPI (用于构建高性能的HTTP和WebSocket接口)
|
||||
- **ROS2通信**: `rclpy` (Python客户端库,用于与无人机ROS2节点交互)
|
||||
- **异步处理**: `asyncio` (Python标准库,FastAPI和`rclpy`都基于此)
|
||||
- **数据模型**: Pydantic (用于API请求/响应的数据验证)
|
||||
- **RAG向量数据库**: ChromaDB (基于现有`vector_store`目录推断)
|
||||
- **依赖管理**: `pip` 和 `requirements.txt`
|
||||
|
||||
## 3. 最终项目结构
|
||||
|
||||
为了实现模块化和高可维护性,项目将采用以下目录结构:
|
||||
|
||||
```
|
||||
.
|
||||
├── backend_service/
|
||||
│ ├── src/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── main.py # FastAPI应用主入口
|
||||
│ │ ├── websocket_manager.py # WebSocket连接管理器
|
||||
│ │ ├── py_tree_generator.py # RAG与LLM集成,生成py_tree
|
||||
│ │ ├── ros2_client.py # ROS2 Action客户端
|
||||
│ │ ├── models.py # Pydantic数据模型
|
||||
│ │ └── prompts/ # 存放LLM的prompt模板
|
||||
│ │ ├── system_prompt.txt
|
||||
│ │ └── ...
|
||||
│ ├── knowledge_base/ # RAG知识库源文件
|
||||
│ │ └── first.ndjson
|
||||
│ ├── vector_store/ # ChromaDB向量数据库
|
||||
│ │ └── ...
|
||||
│ └── requirements.txt # Python依赖项
|
||||
│
|
||||
├── drone_interfaces/ # ROS2接口定义 (保持不变)
|
||||
│ └── ...
|
||||
└── (其他项目文件...)
|
||||
```
|
||||
|
||||
## 4. 核心模块详解
|
||||
|
||||
### 4.1. FastAPI应用 (`main.py`)
|
||||
|
||||
这是整个服务的入口点,负责初始化所有组件并定义API端点。
|
||||
|
||||
- **职责**:
|
||||
- 创建FastAPI应用实例。
|
||||
- 初始化`PyTreeGenerator`, `MissionActionClient`, 和 `ConnectionManager`的单例对象。
|
||||
- 定义`POST /generate_plan`, `POST /execute_mission`, 和 `WS /ws/status`三个核心接口。
|
||||
- 在后台启动ROS2节点,并确保其与FastAPI的事件循环正确集成。
|
||||
|
||||
### 4.2. WebSocket管理器 (`websocket_manager.py`)
|
||||
|
||||
该模块专门处理与QGC插件的WebSocket连接。
|
||||
|
||||
- **类**: `ConnectionManager`
|
||||
- **职责**:
|
||||
- `connect(websocket: WebSocket)`: 接受并存储新的客户端连接。
|
||||
- `disconnect(websocket: WebSocket)`: 移除断开的连接。
|
||||
- `broadcast(message: str)`: 向所有已连接的客户端广播消息。此方法必须是**线程安全**的,因为它将被ROS2回调(运行在不同线程)调用。
|
||||
|
||||
### 4.3. PyTree生成器 (`py_tree_generator.py`)
|
||||
|
||||
封装了所有与任务生成相关的复杂逻辑。
|
||||
|
||||
- **类**: `PyTreeGenerator`
|
||||
- **职责**:
|
||||
- 初始化RAG系统,加载`vector_store`中的知识库。
|
||||
- 提供一个核心方法 `generate(user_prompt: str) -> dict`。
|
||||
- **`generate`方法内部流程**:
|
||||
1. 接收用户输入。
|
||||
2. 使用RAG的检索器从`vector_store`中查找最相关的知识片段(例如,可用的无人机动作、地理位置信息等)。
|
||||
3. 从`prompts/`目录加载系统Prompt模板。
|
||||
4. 将用户输入、检索到的知识组合成一个完整的Prompt。
|
||||
5. 调用外部或本地的LLM服务,获取生成的`py_tree.json`字符串。
|
||||
6. 验证返回的JSON是否符合`00_System_Overview_and_Interfaces.md`中定义的契约,确保其结构正确。
|
||||
7. 返回验证通过的Python字典。
|
||||
|
||||
### 4.4. ROS2 Action客户端 (`ros2_client.py`)
|
||||
|
||||
负责与无人机(模块三)进行通信。
|
||||
|
||||
- **类**: `MissionActionClient` (继承自 `rclpy.node.Node`)
|
||||
- **职责**:
|
||||
- 初始化一个ROS2节点。
|
||||
- 创建一个`ExecuteMission` Action的客户端。
|
||||
- 提供一个核心方法 `send_goal(py_tree: dict)`。
|
||||
- **`send_goal`方法内部流程**:
|
||||
1. 将`py_tree`字典序列化为JSON字符串。
|
||||
2. 构建`ExecuteMission.Goal`消息。
|
||||
3. 异步发送Action目标,并注册`feedback_callback`。
|
||||
- **`feedback_callback`方法**:
|
||||
1. 此回调由`rclpy`的执行器在单独的线程中触发。
|
||||
2. 当收到无人机的状态反馈时,将`current_node_id`和`status`打包成一个字典。
|
||||
3. 获取FastAPI的事件循环,并使用`loop.call_soon_threadsafe()`安全地调用`websocket_manager.broadcast()`方法,将状态更新推送到前端。
|
||||
|
||||
### 4.5. 数据模型 (`models.py`)
|
||||
|
||||
使用Pydantic定义清晰、严格的API数据结构。
|
||||
|
||||
- **类**:
|
||||
- `GeneratePlanRequest(BaseModel)`: 包含`user_prompt: str`。
|
||||
- `ExecuteMissionRequest(BaseModel)`: 包含`py_tree: dict`。
|
||||
- `StatusUpdate(BaseModel)`: 包含`node_id: str`和`status: int`。
|
||||
|
||||
## 5. 数据流
|
||||
|
||||
### 5.1. 任务规划流程
|
||||
|
||||
`QGC Plugin` -> `POST /generate_plan` -> `main.py` -> `py_tree_generator.generate()` -> `RAG/LLM` -> `py_tree.json` -> `main.py` -> `QGC Plugin`
|
||||
|
||||
### 5.2. 任务执行与反馈流程
|
||||
|
||||
`QGC Plugin` -> `POST /execute_mission` -> `main.py` -> `ros2_client.send_goal()` -> `ROS2 Network` -> `Drone`
|
||||
`Drone` -> `ROS2 Feedback` -> `ros2_client.feedback_callback()` -> `websocket_manager.broadcast()` -> `WS /ws/status` -> `QGC Plugin`
|
||||
|
||||
## 6. 后续步骤
|
||||
|
||||
1. **环境搭建**: 根据`requirements.txt`创建虚拟环境并安装所有依赖。
|
||||
2. **代码实现**: 按照上述设计,逐一编写`websocket_manager.py`, `py_tree_generator.py`, `ros2_client.py`, `models.py`, 和 `main.py`。
|
||||
3. **单元测试与集成测试**: (可选,但建议) 为关键模块(如`py_tree_generator`)编写单元测试,并进行完整的集成测试。
|
||||
4. **部署**: 使用`uvicorn`等ASGI服务器运行FastAPI应用。
|
||||
|
||||
---
|
||||
14
drone_interfaces/CMakeLists.txt
Normal file
14
drone_interfaces/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(drone_interfaces)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# find dependencies
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(rosidl_default_generators REQUIRED)
|
||||
|
||||
rosidl_generate_interfaces(${PROJECT_NAME} "action/ExecuteMission.action")
|
||||
|
||||
ament_package()
|
||||
10
drone_interfaces/action/ExecuteMission.action
Normal file
10
drone_interfaces/action/ExecuteMission.action
Normal file
@@ -0,0 +1,10 @@
|
||||
# Goal definition
|
||||
string py_tree_json
|
||||
---
|
||||
# Result definition
|
||||
bool success
|
||||
string message
|
||||
---
|
||||
# Feedback definition
|
||||
string node_id
|
||||
int32 status # 0: RUNNING, 1: SUCCESS, 2: FAILURE
|
||||
15
drone_interfaces/package.xml
Normal file
15
drone_interfaces/package.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="3">
|
||||
<name>drone_interfaces</name>
|
||||
<version>0.0.0</version>
|
||||
<description>Interfaces for the drone project</description>
|
||||
<maintainer email="user@todo.todo">user</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
|
||||
<build_depend>rosidl_default_generators</build_depend>
|
||||
<exec_depend>rosidl_default_runtime</exec_depend>
|
||||
<member_of_group>rosidl_interface_packages</member_of_group>
|
||||
|
||||
</package>
|
||||
157
tools/build_knowledge_base.py
Normal file
157
tools/build_knowledge_base.py
Normal file
@@ -0,0 +1,157 @@
|
||||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
from pathlib import Path
|
||||
import logging
|
||||
import os
|
||||
|
||||
# --- 配置日志 ---
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
def process_osm_json(input_path: Path) -> list[str]:
|
||||
"""
|
||||
处理OpenStreetMap的JSON文件,返回描述性句子列表。
|
||||
"""
|
||||
logging.info(f"正在以OSM JSON格式处理文件: {input_path.name}")
|
||||
descriptions = []
|
||||
try:
|
||||
with open(input_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
except (json.JSONDecodeError, IOError) as e:
|
||||
logging.error(f"读取或解析 {input_path.name} 时出错: {e}")
|
||||
return []
|
||||
|
||||
elements = data.get('elements', [])
|
||||
if not elements:
|
||||
return []
|
||||
|
||||
nodes_map = {node['id']: node for node in elements if node.get('type') == 'node'}
|
||||
ways = [elem for elem in elements if elem.get('type') == 'way']
|
||||
|
||||
for way in ways:
|
||||
tags = way.get('tags', {})
|
||||
if 'name' not in tags:
|
||||
continue
|
||||
|
||||
way_name = tags.get('name')
|
||||
way_nodes_ids = way.get('nodes', [])
|
||||
if not way_nodes_ids:
|
||||
continue
|
||||
|
||||
total_lat, total_lon, node_count = 0, 0, 0
|
||||
for node_id in way_nodes_ids:
|
||||
node_info = nodes_map.get(node_id)
|
||||
if node_info:
|
||||
total_lat += node_info.get('lat', 0)
|
||||
total_lon += node_info.get('lon', 0)
|
||||
node_count += 1
|
||||
|
||||
if node_count == 0:
|
||||
continue
|
||||
|
||||
center_lat = total_lat / node_count
|
||||
center_lon = total_lon / node_count
|
||||
|
||||
sentence = f"在地图上有一个名为 '{way_name}' 的地点或区域"
|
||||
other_tags = {k: v for k, v in tags.items() if k != 'name'}
|
||||
if other_tags:
|
||||
tag_descs = [f"{key}是'{value}'" for key, value in other_tags.items()]
|
||||
sentence += f",它的{ '、'.join(tag_descs) }"
|
||||
sentence += f",其中心位置坐标大约在 ({center_lat:.6f}, {center_lon:.6f})。"
|
||||
descriptions.append(sentence)
|
||||
|
||||
logging.info(f"从 {input_path.name} 提取了 {len(descriptions)} 条位置描述。")
|
||||
return descriptions
|
||||
|
||||
|
||||
def process_gazebo_world(input_path: Path) -> list[str]:
|
||||
"""
|
||||
处理Gazebo的.world文件,返回描述性句子列表。
|
||||
"""
|
||||
logging.info(f"正在以Gazebo World格式处理文件: {input_path.name}")
|
||||
descriptions = []
|
||||
try:
|
||||
tree = ET.parse(input_path)
|
||||
root = tree.getroot()
|
||||
except ET.ParseError as e:
|
||||
logging.error(f"解析XML文件 {input_path.name} 失败: {e}")
|
||||
return []
|
||||
|
||||
models = root.findall('.//model')
|
||||
for model in models:
|
||||
model_name = model.get('name')
|
||||
pose_element = model.find('pose')
|
||||
|
||||
if model_name and pose_element is not None and pose_element.text:
|
||||
try:
|
||||
pose_values = [float(p) for p in pose_element.text.strip().split()]
|
||||
sentence = (
|
||||
f"仿真环境中有一个名为 '{model_name}' 的物体,"
|
||||
f"其位置和姿态(x, y, z, roll, pitch, yaw)为: {pose_values}。"
|
||||
)
|
||||
descriptions.append(sentence)
|
||||
except (ValueError, IndexError):
|
||||
logging.warning(f"跳过模型 '{model_name}',因其pose格式不正确。")
|
||||
|
||||
logging.info(f"从 {input_path.name} 提取了 {len(descriptions)} 个物体信息。")
|
||||
return descriptions
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
主函数,扫描源数据目录,为每个文件生成独立的NDJSON知识库。
|
||||
"""
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
# 输入源: tools/map/
|
||||
source_data_dir = script_dir / 'map'
|
||||
# 输出目录: tools/knowledge_base/
|
||||
output_knowledge_base_dir = script_dir / 'knowledge_base'
|
||||
|
||||
if not source_data_dir.exists():
|
||||
logging.error(f"源数据目录不存在: {source_data_dir}")
|
||||
return
|
||||
|
||||
# 确保输出目录存在
|
||||
output_knowledge_base_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
total_files_processed = 0
|
||||
logging.info(f"--- 开始扫描源数据目录: {source_data_dir} ---")
|
||||
|
||||
for file_path in source_data_dir.iterdir():
|
||||
if not file_path.is_file():
|
||||
continue
|
||||
|
||||
descriptions = []
|
||||
if file_path.suffix == '.json':
|
||||
descriptions = process_osm_json(file_path)
|
||||
elif file_path.suffix == '.world':
|
||||
descriptions = process_gazebo_world(file_path)
|
||||
else:
|
||||
logging.warning(f"跳过不支持的文件类型: {file_path.name}")
|
||||
continue
|
||||
|
||||
if not descriptions:
|
||||
logging.warning(f"未能从 {file_path.name} 提取有效信息,跳过生成文件。")
|
||||
continue
|
||||
|
||||
output_filename = file_path.stem + '_knowledge.ndjson'
|
||||
output_path = output_knowledge_base_dir / output_filename
|
||||
|
||||
try:
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
for sentence in descriptions:
|
||||
json_record = {"text": sentence}
|
||||
f.write(json.dumps(json_record, ensure_ascii=False) + '\n')
|
||||
logging.info(f"成功为 '{file_path.name}' 生成知识库文件: {output_path.name}")
|
||||
total_files_processed += 1
|
||||
except IOError as e:
|
||||
logging.error(f"写入输出文件 '{output_path.name}' 失败: {e}")
|
||||
|
||||
logging.info("--- 数据处理完成 ---")
|
||||
if total_files_processed > 0:
|
||||
logging.info(f"共为 {total_files_processed} 个源文件生成了知识库。")
|
||||
else:
|
||||
logging.warning("未生成任何知识库文件。")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
194
tools/ingest.py
Normal file
194
tools/ingest.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# 该代码用于将本地知识库中的文档导入到ChromaDB中,并使用远程嵌入模型进行向量化
|
||||
import os
|
||||
from pathlib import Path
|
||||
import chromadb
|
||||
# from chromadb.utils import embedding_functions - 不再需要
|
||||
from chromadb.api.types import Documents, EmbeddingFunction, Embeddings, Embeddable
|
||||
from unstructured.partition.auto import partition
|
||||
from rich.progress import track
|
||||
import logging
|
||||
import requests # 导入requests
|
||||
import json # 导入json模块
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
# --- 配置 ---
|
||||
# 获取脚本所在目录,确保路径的正确性
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
KNOWLEDGE_BASE_DIR = SCRIPT_DIR / "knowledge_base"
|
||||
VECTOR_STORE_DIR = SCRIPT_DIR / "vector_store"
|
||||
COLLECTION_NAME = "drone_docs"
|
||||
# EMBEDDING_MODEL_NAME = "bge-small-zh-v1.5" # 不再需要,模型名在函数内部处理
|
||||
|
||||
# --- 自定义远程嵌入函数 ---
|
||||
class RemoteEmbeddingFunction(EmbeddingFunction[Embeddable]):
|
||||
"""
|
||||
一个使用远程、兼容OpenAI API的嵌入服务的嵌入函数。
|
||||
"""
|
||||
def __init__(self, api_url: str):
|
||||
self._api_url = api_url
|
||||
logging.info(f"自定义嵌入函数已初始化,将连接到: {self._api_url}")
|
||||
|
||||
def __call__(self, input: Embeddable) -> Embeddings:
|
||||
"""
|
||||
对输入的文档进行嵌入。
|
||||
"""
|
||||
# 我们的服务只能处理文本,所以检查输入是否为字符串列表
|
||||
if not isinstance(input, list) or not all(isinstance(doc, str) for doc in input):
|
||||
logging.error("此嵌入函数仅支持字符串列表(文档)作为输入。")
|
||||
return []
|
||||
|
||||
try:
|
||||
# 移除 "model" 参数,因为embedding服务可能不需要它
|
||||
response = requests.post(
|
||||
self._api_url,
|
||||
json={"input": input},
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
response.raise_for_status() # 如果请求失败则抛出HTTPError
|
||||
|
||||
# 按照OpenAI API的格式解析返回的嵌入向量
|
||||
data = response.json().get("data", [])
|
||||
if not data:
|
||||
raise ValueError("API响应中没有找到'data'字段或'data'为空")
|
||||
|
||||
embeddings = [item['embedding'] for item in data]
|
||||
return embeddings
|
||||
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"调用嵌入API失败: {e}")
|
||||
# 返回一个空列表或根据需要处理错误
|
||||
return []
|
||||
except (ValueError, KeyError) as e:
|
||||
logging.error(f"解析API响应失败: {e}")
|
||||
logging.error(f"收到的响应内容: {response.text}")
|
||||
return []
|
||||
|
||||
|
||||
def get_documents(directory: Path):
|
||||
"""从知识库目录加载所有文档并进行切分"""
|
||||
documents = []
|
||||
logging.info(f"从 '{directory}' 加载文档...")
|
||||
for file_path in directory.rglob("*"):
|
||||
if file_path.is_file() and not file_path.name.startswith('.'):
|
||||
try:
|
||||
# 对简单文本文件直接读取
|
||||
if file_path.suffix in ['.txt', '.md']:
|
||||
text = file_path.read_text(encoding='utf-8')
|
||||
documents.append({
|
||||
"text": text,
|
||||
"metadata": {"source": str(file_path.name)}
|
||||
})
|
||||
logging.info(f"成功处理文本文件: {file_path.name}")
|
||||
# 特别处理常规的JSON文件
|
||||
elif file_path.suffix == '.json':
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
if 'elements' in data and isinstance(data['elements'], list):
|
||||
for element in data['elements']:
|
||||
documents.append({
|
||||
"text": json.dumps(element, ensure_ascii=False),
|
||||
"metadata": {"source": str(file_path.name)}
|
||||
})
|
||||
logging.info(f"成功处理JSON文件: {file_path.name}, 提取了 {len(data['elements'])} 个元素。")
|
||||
else:
|
||||
documents.append({
|
||||
"text": json.dumps(data, ensure_ascii=False),
|
||||
"metadata": {"source": str(file_path.name)}
|
||||
})
|
||||
logging.info(f"成功处理JSON文件: {file_path.name} (作为单个文档)")
|
||||
# 新增:专门处理我们生成的 NDJSON 文件
|
||||
elif file_path.suffix == '.ndjson':
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
count = 0
|
||||
for line in f:
|
||||
try:
|
||||
record = json.loads(line)
|
||||
if 'text' in record and isinstance(record['text'], str):
|
||||
documents.append({
|
||||
"text": record['text'],
|
||||
"metadata": {"source": str(file_path.name)}
|
||||
})
|
||||
count += 1
|
||||
except json.JSONDecodeError:
|
||||
logging.warning(f"跳过无效的JSON行: {line.strip()}")
|
||||
if count > 0:
|
||||
logging.info(f"成功处理NDJSON文件: {file_path.name}, 提取了 {count} 个文档。")
|
||||
# 对其他所有文件类型,使用unstructured
|
||||
else:
|
||||
elements = partition(filename=str(file_path))
|
||||
for element in elements:
|
||||
documents.append({
|
||||
"text": element.text,
|
||||
"metadata": {"source": str(file_path.name)}
|
||||
})
|
||||
logging.info(f"成功处理文件: {file_path.name} (使用unstructured)")
|
||||
except Exception as e:
|
||||
logging.error(f"处理文件 {file_path.name} 失败: {e}")
|
||||
return documents
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数,执行文档入库流程"""
|
||||
if not KNOWLEDGE_BASE_DIR.exists():
|
||||
KNOWLEDGE_BASE_DIR.mkdir(parents=True)
|
||||
logging.warning(f"知识库目录不存在,已自动创建: {KNOWLEDGE_BASE_DIR}")
|
||||
logging.warning("请向该目录中添加您的知识文件(如 .txt, .pdf, .md)。")
|
||||
return
|
||||
|
||||
# 1. 加载并切分文档
|
||||
docs_to_ingest = get_documents(KNOWLEDGE_BASE_DIR)
|
||||
if not docs_to_ingest:
|
||||
logging.warning("在知识库中未找到可处理的文档。")
|
||||
return
|
||||
|
||||
# 2. 初始化ChromaDB客户端和远程嵌入函数
|
||||
orin_ip = os.getenv("ORIN_IP", "172.101.1.117")
|
||||
embedding_api_url = f"http://{orin_ip}:8090/v1/embeddings"
|
||||
|
||||
logging.info(f"正在初始化远程嵌入函数,目标服务地址: {embedding_api_url}")
|
||||
embedding_func = RemoteEmbeddingFunction(api_url=embedding_api_url)
|
||||
|
||||
client = chromadb.PersistentClient(path=str(VECTOR_STORE_DIR))
|
||||
|
||||
# 3. 创建或获取集合
|
||||
logging.info(f"正在访问ChromaDB集合: {COLLECTION_NAME}")
|
||||
collection = client.get_or_create_collection(
|
||||
name=COLLECTION_NAME,
|
||||
embedding_function=embedding_func
|
||||
)
|
||||
|
||||
# 4. 将文档向量化并存入数据库
|
||||
logging.info(f"开始将 {len(docs_to_ingest)} 个文档块入库...")
|
||||
|
||||
# 为了避免重复添加,可以先检查
|
||||
# (这里为了简单,我们每次都重新添加,生产环境需要更复杂的逻辑)
|
||||
|
||||
doc_texts = [doc['text'] for doc in docs_to_ingest]
|
||||
metadatas = [doc['metadata'] for doc in docs_to_ingest]
|
||||
ids = [f"doc_{KNOWLEDGE_BASE_DIR.name}_{i}" for i in range(len(doc_texts))]
|
||||
|
||||
try:
|
||||
# ChromaDB的add方法会自动处理嵌入
|
||||
collection.add(
|
||||
documents=doc_texts,
|
||||
metadatas=metadatas,
|
||||
ids=ids
|
||||
)
|
||||
logging.info("所有文档块已成功入库!")
|
||||
except Exception as e:
|
||||
logging.error(f"向ChromaDB添加文档时出错: {e}")
|
||||
|
||||
|
||||
# 验证一下
|
||||
count = collection.count()
|
||||
logging.info(f"数据库中现在有 {count} 个条目。")
|
||||
|
||||
print("\n✅ 数据入库完成!")
|
||||
print(f"知识库位于: {KNOWLEDGE_BASE_DIR}")
|
||||
print(f"向量数据库位于: {VECTOR_STORE_DIR}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
326
tools/knowledge_base/export.ndjson
Normal file
326
tools/knowledge_base/export.ndjson
Normal file
@@ -0,0 +1,326 @@
|
||||
{"text": "在地图上有一个名为 '学生宿舍10幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍10幢',其中心位置坐标大约在 (32.118363, 118.951407)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5'、layer是'1',其中心位置坐标大约在 (32.112578, 118.952441)。"}
|
||||
{"text": "在地图上有一个名为 '学生第九餐厅、清真餐厅、教工二餐厅' 的地点或区域,它的amenity是'restaurant'、building是'yes'、cuisine是'chinese'、diet:halal是'yes'、fast_food是'cafeteria'、name:zh是'学生第九餐厅、清真餐厅、教工二餐厅',其中心位置坐标大约在 (32.118835, 118.950338)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5'、layer是'1',其中心位置坐标大约在 (32.112291, 118.951332)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍9幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍9幢',其中心位置坐标大约在 (32.117856, 118.950905)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍6幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍6幢',其中心位置坐标大约在 (32.117406, 118.952443)。"}
|
||||
{"text": "在地图上有一个名为 '信息化建设管理服务中心' 的地点或区域,它的building是'yes'、building:levels是'3'、name:en是'Information Technology Service Center',其中心位置坐标大约在 (32.117418, 118.955253)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍11幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍11幢',其中心位置坐标大约在 (32.119133, 118.950956)。"}
|
||||
{"text": "在地图上有一个名为 '南京大学档案馆' 的地点或区域,它的building是'yes'、name:zh是'南京大学档案馆',其中心位置坐标大约在 (32.117318, 118.954447)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍8幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍8幢',其中心位置坐标大约在 (32.117844, 118.951860)。"}
|
||||
{"text": "在地图上有一个名为 '校史馆(沈小平楼)' 的地点或区域,它的building是'university'、name:zh是'校史馆(沈小平楼)',其中心位置坐标大约在 (32.116735, 118.953156)。"}
|
||||
{"text": "在地图上有一个名为 '学生第四、五、六餐厅' 的地点或区域,它的amenity是'restaurant'、building是'yes'、building:levels是'3'、cuisine是'chinese'、fast_food是'cafeteria'、internet_access是'wlan'、name:zh是'学生第四、五、六餐厅',其中心位置坐标大约在 (32.113385, 118.950076)。"}
|
||||
{"text": "在地图上有一个名为 '敬文学生活动中心' 的地点或区域,它的building是'yes'、name:zh是'敬文学生活动中心',其中心位置坐标大约在 (32.116008, 118.952685)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍7幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍7幢',其中心位置坐标大约在 (32.116881, 118.951416)。"}
|
||||
{"text": "在地图上有一个名为 '扬州楼(行政北楼)' 的地点或区域,它的building是'yes'、building:levels是'7'、name:zh是'扬州楼(行政北楼)',其中心位置坐标大约在 (32.114996, 118.957869)。"}
|
||||
{"text": "在地图上有一个名为 '行政南楼' 的地点或区域,它的building是'yes'、building:levels是'3'、name:zh是'行政南楼',其中心位置坐标大约在 (32.114177, 118.958016)。"}
|
||||
{"text": "在地图上有一个名为 '南大仙林校区' 的地点或区域,它的building是'transportation'、layer是'2',其中心位置坐标大约在 (32.110999, 118.954498)。"}
|
||||
{"text": "在地图上有一个名为 '气象观测站' 的地点或区域,它的building是'yes'、man_made是'monitoring_station'、monitoring:weather是'yes'、name:zh是'气象观测站',其中心位置坐标大约在 (32.120581, 118.952775)。"}
|
||||
{"text": "在地图上有一个名为 '侨裕楼(外国语学院)' 的地点或区域,它的building是'university'、name:zh是'侨裕楼(外国语学院)',其中心位置坐标大约在 (32.118473, 118.956012)。"}
|
||||
{"text": "在地图上有一个名为 '游泳馆' 的地点或区域,它的building是'yes'、leisure是'swimming_pool'、name:zh是'游泳馆'、sport是'swimming',其中心位置坐标大约在 (32.118386, 118.953233)。"}
|
||||
{"text": "在地图上有一个名为 '社会学院' 的地点或区域,它的addr:city是'南京市'、addr:housenumber是'163号'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'university'、name:zh是'河仁楼(社会学院)',其中心位置坐标大约在 (32.120251, 118.954777)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍5幢' 的地点或区域,它的building是'dormitory'、building:levels是'6'、name:zh是'学生宿舍5幢',其中心位置坐标大约在 (32.116960, 118.948511)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍3幢' 的地点或区域,它的building是'dormitory'、building:levels是'6'、name:zh是'学生宿舍3幢',其中心位置坐标大约在 (32.115783, 118.949095)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍1幢' 的地点或区域,它的building是'dormitory'、building:levels是'6'、name:zh是'学生宿舍1幢',其中心位置坐标大约在 (32.114598, 118.949687)。"}
|
||||
{"text": "在地图上有一个名为 '逸夫楼' 的地点或区域,它的building是'university'、building:levels是'5'、loc_name是'邵逸夫楼'、name:zh是'逸夫楼',其中心位置坐标大约在 (32.112757, 118.954903)。"}
|
||||
{"text": "在地图上有一个名为 '国际学院' 的地点或区域,它的building是'university'、building:levels是'5'、loc_name是'邵逸夫楼'、name:zh是'国际学院',其中心位置坐标大约在 (32.112661, 118.954128)。"}
|
||||
{"text": "在地图上有一个名为 '左涤江楼' 的地点或区域,它的building是'university'、building:levels是'5'、loc_name是'邵逸夫楼'、name:zh是'左涤江楼',其中心位置坐标大约在 (32.112855, 118.954377)。"}
|
||||
{"text": "在地图上有一个名为 '大气科学学院' 的地点或区域,它的building是'university'、building:levels是'5;4',其中心位置坐标大约在 (32.119925, 118.950090)。"}
|
||||
{"text": "在地图上有一个名为 '学生第十食堂/教工餐厅' 的地点或区域,它的amenity是'restaurant'、building是'yes'、cuisine是'chinese'、fast_food是'cafeteria'、name:zh是'学生第十食堂/教工餐厅',其中心位置坐标大约在 (32.117211, 118.957967)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍15幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生宿舍15幢',其中心位置坐标大约在 (32.117771, 118.958196)。"}
|
||||
{"text": "在地图上有一个名为 '生命科学学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121291, 118.949637)。"}
|
||||
{"text": "在地图上有一个名为 '生命科学学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121679, 118.950162)。"}
|
||||
{"text": "在地图上有一个名为 '生命科学学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121464, 118.950208)。"}
|
||||
{"text": "在地图上有一个名为 '左涤江天文台' 的地点或区域,它的building是'yes'、man_made是'observatory'、name:zh是'左涤江天文台',其中心位置坐标大约在 (32.124128, 118.955593)。"}
|
||||
{"text": "在地图上有一个名为 '配电房' 的地点或区域,它的building是'yes'、name:zh是'配电房',其中心位置坐标大约在 (32.121665, 118.958760)。"}
|
||||
{"text": "在地图上有一个名为 '37栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131308, 118.947252)。"}
|
||||
{"text": "在地图上有一个名为 '38栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.130640, 118.947807)。"}
|
||||
{"text": "在地图上有一个名为 '中合集团' 的地点或区域,它的building是'yes'、name:zh是'中合集团',其中心位置坐标大约在 (32.130732, 118.957853)。"}
|
||||
{"text": "在地图上有一个名为 '智慧园2' 的地点或区域,它的building是'yes'、name:zh是'智慧园2',其中心位置坐标大约在 (32.129285, 118.958509)。"}
|
||||
{"text": "在地图上有一个名为 '智慧园3' 的地点或区域,它的building是'yes'、name:zh是'智慧园3',其中心位置坐标大约在 (32.129662, 118.958611)。"}
|
||||
{"text": "在地图上有一个名为 '智慧园1' 的地点或区域,它的building是'yes'、name:zh是'智慧园1',其中心位置坐标大约在 (32.128997, 118.958774)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍2幢' 的地点或区域,它的building是'dormitory'、building:levels是'6'、name:zh是'学生宿舍2幢',其中心位置坐标大约在 (32.116117, 118.950136)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍4幢' 的地点或区域,它的building是'dormitory'、building:levels是'6'、name:zh是'学生宿舍4幢',其中心位置坐标大约在 (32.117266, 118.949547)。"}
|
||||
{"text": "在地图上有一个名为 '南京信息职业技术学院行政大楼' 的地点或区域,它的building是'yes'、name:zh是'南京信息职业技术学院行政大楼',其中心位置坐标大约在 (32.127694, 118.937821)。"}
|
||||
{"text": "在地图上有一个名为 '1号教学楼' 的地点或区域,它的building是'yes'、layer是'1'、name:zh是'1号教学楼',其中心位置坐标大约在 (32.130094, 118.937824)。"}
|
||||
{"text": "在地图上有一个名为 '2号教学楼' 的地点或区域,它的building是'yes'、layer是'1'、name:zh是'2号教学楼',其中心位置坐标大约在 (32.130590, 118.937746)。"}
|
||||
{"text": "在地图上有一个名为 '3号教学楼' 的地点或区域,它的building是'yes'、layer是'1'、name:zh是'3号教学楼',其中心位置坐标大约在 (32.131123, 118.937560)。"}
|
||||
{"text": "在地图上有一个名为 '阶教室(1~4)' 的地点或区域,它的building是'yes'、name:zh是'阶教室(1~4)',其中心位置坐标大约在 (32.130217, 118.938816)。"}
|
||||
{"text": "在地图上有一个名为 '阶教室(5~8)' 的地点或区域,它的building是'yes'、name:zh是'阶教室(5~8)',其中心位置坐标大约在 (32.130733, 118.938732)。"}
|
||||
{"text": "在地图上有一个名为 '阶教室(9~10)' 的地点或区域,它的building是'yes'、name:zh是'阶教室(9~10)',其中心位置坐标大约在 (32.131223, 118.938468)。"}
|
||||
{"text": "在地图上有一个名为 '南大国际会议中心' 的地点或区域,它的building是'yes'、tourism是'hotel',其中心位置坐标大约在 (32.116389, 118.957899)。"}
|
||||
{"text": "在地图上有一个名为 '仙林校区第二体育场附属体育馆' 的地点或区域,它的building是'yes'、name:zh是'仙林校区第二体育场附属体育馆',其中心位置坐标大约在 (32.123331, 118.946338)。"}
|
||||
{"text": "在地图上有一个名为 '学生第十一餐厅' 的地点或区域,它的amenity是'restaurant'、building是'yes'、fast_food是'cafeteria'、name:zh是'学生第十一餐厅',其中心位置坐标大约在 (32.124886, 118.946992)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓18幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生公寓18幢',其中心位置坐标大约在 (32.126459, 118.946337)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓21幢/招待所/留学生公寓' 的地点或区域,它的building是'dormitory'、name:zh是'学生公寓21幢/招待所/留学生公寓',其中心位置坐标大约在 (32.126662, 118.948693)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓16幢' 的地点或区域,它的building是'university'、name:zh是'学生公寓16幢',其中心位置坐标大约在 (32.124798, 118.946197)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓20幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生公寓20幢',其中心位置坐标大约在 (32.126612, 118.947908)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓19幢' 的地点或区域,它的building是'dormitory'、name:zh是'学生公寓19幢',其中心位置坐标大约在 (32.126517, 118.947121)。"}
|
||||
{"text": "在地图上有一个名为 '学生公寓17幢' 的地点或区域,它的building是'university'、name:zh是'学生公寓17幢',其中心位置坐标大约在 (32.125641, 118.946295)。"}
|
||||
{"text": "在地图上有一个名为 '历史学院' 的地点或区域,它的addr:city是'南京市'、addr:housenumber是'163号'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'university'、name:zh是'历史学院',其中心位置坐标大约在 (32.121063, 118.954117)。"}
|
||||
{"text": "在地图上有一个名为 '匡亚明学院' 的地点或区域,它的building是'university'、name:zh是'匡亚明学院',其中心位置坐标大约在 (32.118904, 118.955208)。"}
|
||||
{"text": "在地图上有一个名为 '信息管理学院' 的地点或区域,它的building是'university'、name:zh是'信息管理学院',其中心位置坐标大约在 (32.119130, 118.955489)。"}
|
||||
{"text": "在地图上有一个名为 '南京大学美术馆' 的地点或区域,它的addr:city是'南京'、addr:housenumber是'163'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'yes'、name:zh是'南京大学美术馆',其中心位置坐标大约在 (32.116135, 118.957631)。"}
|
||||
{"text": "在地图上有一个名为 '教学楼' 的地点或区域,它的addr:city是'南京'、addr:street是'仙林大道'、building是'school'、name:zh是'教学楼',其中心位置坐标大约在 (32.111407, 118.961720)。"}
|
||||
{"text": "在地图上有一个名为 '教学楼' 的地点或区域,它的building是'school'、name:zh是'教学楼',其中心位置坐标大约在 (32.111990, 118.962025)。"}
|
||||
{"text": "在地图上有一个名为 '学生宿舍25幢' 的地点或区域,它的building是'dormitory'、building:levels是'5'、name:zh是'学生宿舍25幢',其中心位置坐标大约在 (32.127235, 118.954093)。"}
|
||||
{"text": "在地图上有一个名为 '天文与空间科学学院' 的地点或区域,它的building是'university'、building:levels是'5'、name:zh是'天文与空间科学学院',其中心位置坐标大约在 (32.127596, 118.954874)。"}
|
||||
{"text": "在地图上有一个名为 '南京大学量子材料微结构研究中心' 的地点或区域,它的building是'university'、building:levels是'1',其中心位置坐标大约在 (32.127804, 118.954043)。"}
|
||||
{"text": "在地图上有一个名为 '39幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109930, 118.951469)。"}
|
||||
{"text": "在地图上有一个名为 '40幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109632, 118.951555)。"}
|
||||
{"text": "在地图上有一个名为 '37幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.110030, 118.952233)。"}
|
||||
{"text": "在地图上有一个名为 '38幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109744, 118.952319)。"}
|
||||
{"text": "在地图上有一个名为 '30幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.110134, 118.953036)。"}
|
||||
{"text": "在地图上有一个名为 '31幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109840, 118.953103)。"}
|
||||
{"text": "在地图上有一个名为 '41幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109254, 118.951746)。"}
|
||||
{"text": "在地图上有一个名为 '42幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108965, 118.951820)。"}
|
||||
{"text": "在地图上有一个名为 '43幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108625, 118.951928)。"}
|
||||
{"text": "在地图上有一个名为 '44幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108319, 118.952017)。"}
|
||||
{"text": "在地图上有一个名为 '45幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107998, 118.952113)。"}
|
||||
{"text": "在地图上有一个名为 '32幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109502, 118.953026)。"}
|
||||
{"text": "在地图上有一个名为 '33幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.109186, 118.953071)。"}
|
||||
{"text": "在地图上有一个名为 '34幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108885, 118.953131)。"}
|
||||
{"text": "在地图上有一个名为 '35幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108578, 118.953183)。"}
|
||||
{"text": "在地图上有一个名为 '36幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.108245, 118.953227)。"}
|
||||
{"text": "在地图上有一个名为 '46幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107483, 118.952259)。"}
|
||||
{"text": "在地图上有一个名为 '47幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107174, 118.952342)。"}
|
||||
{"text": "在地图上有一个名为 '48幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.106871, 118.952440)。"}
|
||||
{"text": "在地图上有一个名为 '53幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107842, 118.953462)。"}
|
||||
{"text": "在地图上有一个名为 '54幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107507, 118.953356)。"}
|
||||
{"text": "在地图上有一个名为 '55幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107182, 118.953363)。"}
|
||||
{"text": "在地图上有一个名为 '56幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.106892, 118.953424)。"}
|
||||
{"text": "在地图上有一个名为 '62幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107907, 118.954543)。"}
|
||||
{"text": "在地图上有一个名为 '63幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107589, 118.954466)。"}
|
||||
{"text": "在地图上有一个名为 '64幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.107264, 118.954429)。"}
|
||||
{"text": "在地图上有一个名为 '65幢' 的地点或区域,它的building是'residential'、building:levels是'6',其中心位置坐标大约在 (32.106970, 118.954427)。"}
|
||||
{"text": "在地图上有一个名为 '垃圾场' 的地点或区域,它的building是'yes'、name:zh是'垃圾场',其中心位置坐标大约在 (32.118340, 118.957592)。"}
|
||||
{"text": "在地图上有一个名为 '25幢' 的地点或区域,它的building是'apartments'、building:levels是'6'、name:zh是'25幢',其中心位置坐标大约在 (32.109631, 118.954057)。"}
|
||||
{"text": "在地图上有一个名为 '24幢' 的地点或区域,它的building是'apartments'、building:levels是'6'、name:zh是'24幢',其中心位置坐标大约在 (32.109899, 118.953932)。"}
|
||||
{"text": "在地图上有一个名为 '环境学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.119491, 118.948427)。"}
|
||||
{"text": "在地图上有一个名为 '环境学院' 的地点或区域,它的building是'university'、layer是'1',其中心位置坐标大约在 (32.119185, 118.948005)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.112310, 118.950955)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.112523, 118.952460)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.112429, 118.951419)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.112593, 118.952946)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5'、layer是'1',其中心位置坐标大约在 (32.112491, 118.951825)。"}
|
||||
{"text": "在地图上有一个名为 '基础实验楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.112494, 118.952244)。"}
|
||||
{"text": "在地图上有一个名为 '花房' 的地点或区域,它的building是'university'、name:zh是'花房',其中心位置坐标大约在 (32.118788, 118.948634)。"}
|
||||
{"text": "在地图上有一个名为 '大气科学学院' 的地点或区域,它的building是'university'、building:levels是'5;4',其中心位置坐标大约在 (32.120083, 118.950190)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6'、building:min_level是'1'、layer是'1',其中心位置坐标大约在 (32.121157, 118.947274)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6'、building:min_level是'1'、layer是'1',其中心位置坐标大约在 (32.120775, 118.947408)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6'、building:min_level是'1'、layer是'1',其中心位置坐标大约在 (32.120376, 118.947546)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6',其中心位置坐标大约在 (32.120444, 118.946806)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6',其中心位置坐标大约在 (32.120901, 118.948341)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6',其中心位置坐标大约在 (32.120601, 118.948172)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6',其中心位置坐标大约在 (32.121236, 118.947934)。"}
|
||||
{"text": "在地图上有一个名为 '化学化工学院' 的地点或区域,它的building是'university'、building:levels是'6'、layer是'1',其中心位置坐标大约在 (32.120922, 118.948087)。"}
|
||||
{"text": "在地图上有一个名为 '26幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109311, 118.954077)。"}
|
||||
{"text": "在地图上有一个名为 '27幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108977, 118.954186)。"}
|
||||
{"text": "在地图上有一个名为 '28幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108684, 118.954248)。"}
|
||||
{"text": "在地图上有一个名为 '29幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108380, 118.954421)。"}
|
||||
{"text": "在地图上有一个名为 '15幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110100, 118.955418)。"}
|
||||
{"text": "在地图上有一个名为 '16幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109806, 118.955426)。"}
|
||||
{"text": "在地图上有一个名为 '17幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109490, 118.955344)。"}
|
||||
{"text": "在地图上有一个名为 '18幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109173, 118.955389)。"}
|
||||
{"text": "在地图上有一个名为 '19幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108864, 118.955484)。"}
|
||||
{"text": "在地图上有一个名为 '20幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108538, 118.955531)。"}
|
||||
{"text": "在地图上有一个名为 '21幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108277, 118.955617)。"}
|
||||
{"text": "在地图上有一个名为 '22幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109996, 118.954613)。"}
|
||||
{"text": "在地图上有一个名为 '23幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109712, 118.954772)。"}
|
||||
{"text": "在地图上有一个名为 '菜根谭快递站' 的地点或区域,它的amenity是'post_office'、building是'yes',其中心位置坐标大约在 (32.116479, 118.951733)。"}
|
||||
{"text": "在地图上有一个名为 '6栋快递自提柜' 的地点或区域,它的amenity是'post_office'、building是'yes',其中心位置坐标大约在 (32.116825, 118.952329)。"}
|
||||
{"text": "在地图上有一个名为 '15栋快递自提柜' 的地点或区域,它的amenity是'post_office'、building是'yes',其中心位置坐标大约在 (32.117748, 118.957996)。"}
|
||||
{"text": "在地图上有一个名为 '勇园快递站' 的地点或区域,它的amenity是'post_office'、building是'yes',其中心位置坐标大约在 (32.125444, 118.946840)。"}
|
||||
{"text": "在地图上有一个名为 '南京和光智能制造研究院' 的地点或区域,它的building是'commercial',其中心位置坐标大约在 (32.128399, 118.947911)。"}
|
||||
{"text": "在地图上有一个名为 '淳朴亭' 的地点或区域,它的amenity是'shelter'、building是'yes',其中心位置坐标大约在 (32.120761, 118.950780)。"}
|
||||
{"text": "在地图上有一个名为 '1号楼' 的地点或区域,它的amenity是'restaurant'、building是'yes'、layer是'1',其中心位置坐标大约在 (32.125778, 118.958005)。"}
|
||||
{"text": "在地图上有一个名为 '4号楼' 的地点或区域,它的building是'yes'、office是'research',其中心位置坐标大约在 (32.125877, 118.958793)。"}
|
||||
{"text": "在地图上有一个名为 '2号楼' 的地点或区域,它的building是'yes'、office是'research',其中心位置坐标大约在 (32.126742, 118.958709)。"}
|
||||
{"text": "在地图上有一个名为 '3号楼' 的地点或区域,它的building是'yes'、office是'research',其中心位置坐标大约在 (32.126479, 118.958768)。"}
|
||||
{"text": "在地图上有一个名为 '四组团十一食堂站' 的地点或区域,它的amenity是'shelter'、building是'yes'、shelter_type是'public_transport',其中心位置坐标大约在 (32.125395, 118.947557)。"}
|
||||
{"text": "在地图上有一个名为 '68幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.107854, 118.955680)。"}
|
||||
{"text": "在地图上有一个名为 '69幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.107528, 118.955660)。"}
|
||||
{"text": "在地图上有一个名为 '70幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.107215, 118.955609)。"}
|
||||
{"text": "在地图上有一个名为 '71幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.106868, 118.955563)。"}
|
||||
{"text": "在地图上有一个名为 '8幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110285, 118.956830)。"}
|
||||
{"text": "在地图上有一个名为 '9幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109995, 118.957069)。"}
|
||||
{"text": "在地图上有一个名为 '10幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109699, 118.957142)。"}
|
||||
{"text": "在地图上有一个名为 '11幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109385, 118.957204)。"}
|
||||
{"text": "在地图上有一个名为 '12幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109062, 118.957116)。"}
|
||||
{"text": "在地图上有一个名为 '社区中心' 的地点或区域,它的building是'yes'、building:levels是'2',其中心位置坐标大约在 (32.107709, 118.956429)。"}
|
||||
{"text": "在地图上有一个名为 '74幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.108124, 118.957410)。"}
|
||||
{"text": "在地图上有一个名为 '80幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.108339, 118.957947)。"}
|
||||
{"text": "在地图上有一个名为 '75幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107766, 118.957429)。"}
|
||||
{"text": "在地图上有一个名为 '81幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.108037, 118.958140)。"}
|
||||
{"text": "在地图上有一个名为 '76幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107430, 118.957603)。"}
|
||||
{"text": "在地图上有一个名为 '82幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107778, 118.958480)。"}
|
||||
{"text": "在地图上有一个名为 '77幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107061, 118.957794)。"}
|
||||
{"text": "在地图上有一个名为 '83幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107447, 118.958692)。"}
|
||||
{"text": "在地图上有一个名为 '78幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.106817, 118.958220)。"}
|
||||
{"text": "在地图上有一个名为 '84幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.107141, 118.958941)。"}
|
||||
{"text": "在地图上有一个名为 '85幢' 的地点或区域,它的building是'apartments'、building:levels是'7',其中心位置坐标大约在 (32.106847, 118.959144)。"}
|
||||
{"text": "在地图上有一个名为 '6幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110385, 118.957643)。"}
|
||||
{"text": "在地图上有一个名为 '7幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110093, 118.957839)。"}
|
||||
{"text": "在地图上有一个名为 '5幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109132, 118.958036)。"}
|
||||
{"text": "在地图上有一个名为 '4幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109522, 118.958366)。"}
|
||||
{"text": "在地图上有一个名为 '3幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.109844, 118.958394)。"}
|
||||
{"text": "在地图上有一个名为 '2幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110169, 118.958529)。"}
|
||||
{"text": "在地图上有一个名为 '1幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.110483, 118.958469)。"}
|
||||
{"text": "在地图上有一个名为 '169幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110268, 118.954063)。"}
|
||||
{"text": "在地图上有一个名为 '168幢' 的地点或区域,它的building是'retail',其中心位置坐标大约在 (32.110328, 118.955335)。"}
|
||||
{"text": "在地图上有一个名为 '166幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110523, 118.955614)。"}
|
||||
{"text": "在地图上有一个名为 '167幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110430, 118.954565)。"}
|
||||
{"text": "在地图上有一个名为 '165幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110555, 118.957025)。"}
|
||||
{"text": "在地图上有一个名为 '162幢' 的地点或区域,它的building是'commercial'、building:levels是'3',其中心位置坐标大约在 (32.110836, 118.958390)。"}
|
||||
{"text": "在地图上有一个名为 '163幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110824, 118.957713)。"}
|
||||
{"text": "在地图上有一个名为 '164幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110672, 118.956623)。"}
|
||||
{"text": "在地图上有一个名为 '校图书馆' 的地点或区域,它的amenity是'library'、building是'yes'、layer是'1',其中心位置坐标大约在 (32.122664, 118.939190)。"}
|
||||
{"text": "在地图上有一个名为 '创客空间' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.122582, 118.938378)。"}
|
||||
{"text": "在地图上有一个名为 '乐业楼' 的地点或区域,它的building是'university'、building:levels是'5',其中心位置坐标大约在 (32.122773, 118.938103)。"}
|
||||
{"text": "在地图上有一个名为 '敬业楼' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121950, 118.938149)。"}
|
||||
{"text": "在地图上有一个名为 '大学生文艺活动室' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.122076, 118.938397)。"}
|
||||
{"text": "在地图上有一个名为 '求真楼' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121952, 118.939201)。"}
|
||||
{"text": "在地图上有一个名为 '乐群楼' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.120856, 118.937737)。"}
|
||||
{"text": "在地图上有一个名为 '国际教育学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.120584, 118.938605)。"}
|
||||
{"text": "在地图上有一个名为 '躬行楼' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.125922, 118.938780)。"}
|
||||
{"text": "在地图上有一个名为 '捷豹路虎南京卓越培训中心' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.125456, 118.938323)。"}
|
||||
{"text": "在地图上有一个名为 '国际贸易与物流管理研究所' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.124787, 118.938531)。"}
|
||||
{"text": "在地图上有一个名为 '北京精雕科技集团有限公司' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.125507, 118.938939)。"}
|
||||
{"text": "在地图上有一个名为 '南京市第十三国家职业技能鉴定所' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.125120, 118.938871)。"}
|
||||
{"text": "在地图上有一个名为 'NYG-1918' 的地点或区域,它的aeroway是'hangar'、building是'hangar',其中心位置坐标大约在 (32.125464, 118.937265)。"}
|
||||
{"text": "在地图上有一个名为 '行政楼' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.119834, 118.936977)。"}
|
||||
{"text": "在地图上有一个名为 '南京工业职业技术大学(北门)' 的地点或区域,它的amenity是'shelter'、building是'yes'、layer是'1',其中心位置坐标大约在 (32.126320, 118.937323)。"}
|
||||
{"text": "在地图上有一个名为 '南京工业职业技术大学(东门)' 的地点或区域,它的amenity是'shelter'、building是'yes'、layer是'1',其中心位置坐标大约在 (32.124452, 118.940097)。"}
|
||||
{"text": "在地图上有一个名为 '大玻璃教室' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.120889, 118.938660)。"}
|
||||
{"text": "在地图上有一个名为 '科技园' 的地点或区域,它的building是'yes'、name:zh是'科技园',其中心位置坐标大约在 (32.127799, 118.938988)。"}
|
||||
{"text": "在地图上有一个名为 '科技园' 的地点或区域,它的building是'yes'、name:zh是'科技园',其中心位置坐标大约在 (32.127746, 118.939689)。"}
|
||||
{"text": "在地图上有一个名为 '科技园' 的地点或区域,它的building是'yes'、name:zh是'科技园',其中心位置坐标大约在 (32.128082, 118.939604)。"}
|
||||
{"text": "在地图上有一个名为 '科技园' 的地点或区域,它的building是'yes'、name:zh是'科技园',其中心位置坐标大约在 (32.127996, 118.939891)。"}
|
||||
{"text": "在地图上有一个名为 '科技园' 的地点或区域,它的building是'yes'、name:zh是'科技园',其中心位置坐标大约在 (32.129711, 118.939745)。"}
|
||||
{"text": "在地图上有一个名为 '国际关系学院' 的地点或区域,它的building是'university',其中心位置坐标大约在 (32.121706, 118.951702)。"}
|
||||
{"text": "在地图上有一个名为 '18栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132807, 118.959391)。"}
|
||||
{"text": "在地图上有一个名为 '南大和园农贸市场' 的地点或区域,它的building是'retail',其中心位置坐标大约在 (32.110969, 118.959158)。"}
|
||||
{"text": "在地图上有一个名为 '14幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108454, 118.957242)。"}
|
||||
{"text": "在地图上有一个名为 '垃圾站' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.109919, 118.956197)。"}
|
||||
{"text": "在地图上有一个名为 '羊山书苑' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.116108, 118.938897)。"}
|
||||
{"text": "在地图上有一个名为 '166幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110489, 118.955112)。"}
|
||||
{"text": "在地图上有一个名为 '164幢' 的地点或区域,它的building是'retail'、building:levels是'3',其中心位置坐标大约在 (32.110733, 118.957095)。"}
|
||||
{"text": "在地图上有一个名为 '13幢' 的地点或区域,它的building是'apartments'、building:levels是'6',其中心位置坐标大约在 (32.108746, 118.957172)。"}
|
||||
{"text": "在地图上有一个名为 '栖霞区核酸小屋(废弃)' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.111018, 118.956190)。"}
|
||||
{"text": "在地图上有一个名为 'B4栋' 的地点或区域,它的addr:place是'江苏生命科技创新园'、building是'yes',其中心位置坐标大约在 (32.132991, 118.951775)。"}
|
||||
{"text": "在地图上有一个名为 'B6栋' 的地点或区域,它的addr:place是'江苏生命科技创新园'、building是'yes',其中心位置坐标大约在 (32.132506, 118.951993)。"}
|
||||
{"text": "在地图上有一个名为 '17栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132902, 118.959949)。"}
|
||||
{"text": "在地图上有一个名为 'A1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.133079, 118.956082)。"}
|
||||
{"text": "在地图上有一个名为 '协同创新大厦' 的地点或区域,它的building是'commercial',其中心位置坐标大约在 (32.127895, 118.958680)。"}
|
||||
{"text": "在地图上有一个名为 '中国游戏数码港' 的地点或区域,它的building是'university'、name:zh是'中国游戏数码港',其中心位置坐标大约在 (32.130547, 118.954394)。"}
|
||||
{"text": "在地图上有一个名为 '智慧园6' 的地点或区域,它的building是'university'、name:zh是'智慧园6',其中心位置坐标大约在 (32.130347, 118.955872)。"}
|
||||
{"text": "在地图上有一个名为 '7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.130157, 118.955108)。"}
|
||||
{"text": "在地图上有一个名为 '1号楼' 的地点或区域,它的building是'commercial',其中心位置坐标大约在 (32.129982, 118.953671)。"}
|
||||
{"text": "在地图上有一个名为 'B7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132289, 118.951108)。"}
|
||||
{"text": "在地图上有一个名为 'B5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132869, 118.952425)。"}
|
||||
{"text": "在地图上有一个名为 'B3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132862, 118.952796)。"}
|
||||
{"text": "在地图上有一个名为 '5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128561, 118.963282)。"}
|
||||
{"text": "在地图上有一个名为 '4栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128913, 118.963328)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129287, 118.963404)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129487, 118.962760)。"}
|
||||
{"text": "在地图上有一个名为 '3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129674, 118.962109)。"}
|
||||
{"text": "在地图上有一个名为 '12栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129635, 118.960945)。"}
|
||||
{"text": "在地图上有一个名为 '15栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129482, 118.960264)。"}
|
||||
{"text": "在地图上有一个名为 '17栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128992, 118.960374)。"}
|
||||
{"text": "在地图上有一个名为 '16栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128719, 118.961012)。"}
|
||||
{"text": "在地图上有一个名为 '18栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128271, 118.961030)。"}
|
||||
{"text": "在地图上有一个名为 '19栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128476, 118.960509)。"}
|
||||
{"text": "在地图上有一个名为 '2号楼' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129411, 118.952702)。"}
|
||||
{"text": "在地图上有一个名为 '4栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129165, 118.964417)。"}
|
||||
{"text": "在地图上有一个名为 '江苏省体育科学研究所' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.121071, 118.965970)。"}
|
||||
{"text": "在地图上有一个名为 '7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120339, 118.961607)。"}
|
||||
{"text": "在地图上有一个名为 '14栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.121731, 118.961821)。"}
|
||||
{"text": "在地图上有一个名为 '13栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.121459, 118.961716)。"}
|
||||
{"text": "在地图上有一个名为 '12栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.121172, 118.961455)。"}
|
||||
{"text": "在地图上有一个名为 '5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120905, 118.959973)。"}
|
||||
{"text": "在地图上有一个名为 '6栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120919, 118.960480)。"}
|
||||
{"text": "在地图上有一个名为 '10栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120890, 118.961643)。"}
|
||||
{"text": "在地图上有一个名为 '11栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120895, 118.961136)。"}
|
||||
{"text": "在地图上有一个名为 '8栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120623, 118.961565)。"}
|
||||
{"text": "在地图上有一个名为 '9栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120621, 118.961001)。"}
|
||||
{"text": "在地图上有一个名为 '4栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120641, 118.960413)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120370, 118.960301)。"}
|
||||
{"text": "在地图上有一个名为 '3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120642, 118.959976)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.120378, 118.959871)。"}
|
||||
{"text": "在地图上有一个名为 '社会学院' 的地点或区域,它的addr:city是'南京市'、addr:housenumber是'163号'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'university'、name:zh是'河仁楼(社会学院)',其中心位置坐标大约在 (32.120253, 118.955138)。"}
|
||||
{"text": "在地图上有一个名为 '社会学院' 的地点或区域,它的addr:city是'南京市'、addr:housenumber是'163号'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'university'、name:zh是'河仁楼(社会学院)',其中心位置坐标大约在 (32.120383, 118.954906)。"}
|
||||
{"text": "在地图上有一个名为 '社会学院' 的地点或区域,它的addr:city是'南京市'、addr:housenumber是'163号'、addr:postcode是'210023'、addr:street是'仙林大道'、building是'university'、name:zh是'河仁楼(社会学院)',其中心位置坐标大约在 (32.120413, 118.954960)。"}
|
||||
{"text": "在地图上有一个名为 'C栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.119948, 118.960706)。"}
|
||||
{"text": "在地图上有一个名为 'B栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.119634, 118.960664)。"}
|
||||
{"text": "在地图上有一个名为 'A栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.119320, 118.960599)。"}
|
||||
{"text": "在地图上有一个名为 '64栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.125317, 118.969390)。"}
|
||||
{"text": "在地图上有一个名为 '67栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126039, 118.969808)。"}
|
||||
{"text": "在地图上有一个名为 '66栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.125863, 118.968927)。"}
|
||||
{"text": "在地图上有一个名为 '19栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126518, 118.966927)。"}
|
||||
{"text": "在地图上有一个名为 '19栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126366, 118.966595)。"}
|
||||
{"text": "在地图上有一个名为 '16栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126936, 118.966471)。"}
|
||||
{"text": "在地图上有一个名为 '16栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127019, 118.966836)。"}
|
||||
{"text": "在地图上有一个名为 '13栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127508, 118.966792)。"}
|
||||
{"text": "在地图上有一个名为 '13栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127494, 118.966445)。"}
|
||||
{"text": "在地图上有一个名为 '21栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.125988, 118.965525)。"}
|
||||
{"text": "在地图上有一个名为 '21栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.125873, 118.965161)。"}
|
||||
{"text": "在地图上有一个名为 '20栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126193, 118.966009)。"}
|
||||
{"text": "在地图上有一个名为 '18栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126449, 118.965650)。"}
|
||||
{"text": "在地图上有一个名为 '17栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126884, 118.965660)。"}
|
||||
{"text": "在地图上有一个名为 '17栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.126884, 118.965212)。"}
|
||||
{"text": "在地图上有一个名为 '14栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127321, 118.965718)。"}
|
||||
{"text": "在地图上有一个名为 '14栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127322, 118.965270)。"}
|
||||
{"text": "在地图上有一个名为 '11栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127760, 118.965718)。"}
|
||||
{"text": "在地图上有一个名为 '11栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127761, 118.965270)。"}
|
||||
{"text": "在地图上有一个名为 '15栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127162, 118.964452)。"}
|
||||
{"text": "在地图上有一个名为 '12栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127669, 118.964467)。"}
|
||||
{"text": "在地图上有一个名为 '8栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128144, 118.966811)。"}
|
||||
{"text": "在地图上有一个名为 '5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128669, 118.966843)。"}
|
||||
{"text": "在地图上有一个名为 '10栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128170, 118.964445)。"}
|
||||
{"text": "在地图上有一个名为 '9栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128200, 118.965509)。"}
|
||||
{"text": "在地图上有一个名为 '6栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128684, 118.965523)。"}
|
||||
{"text": "在地图上有一个名为 '7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128662, 118.964463)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129204, 118.966742)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129179, 118.965975)。"}
|
||||
{"text": "在地图上有一个名为 '3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129175, 118.965204)。"}
|
||||
{"text": "在地图上有一个名为 '63栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.124969, 118.970335)。"}
|
||||
{"text": "在地图上有一个名为 '62栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.124820, 118.969650)。"}
|
||||
{"text": "在地图上有一个名为 '61栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.124294, 118.970244)。"}
|
||||
{"text": "在地图上有一个名为 '60栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.123897, 118.970512)。"}
|
||||
{"text": "在地图上有一个名为 '65栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.125580, 118.970582)。"}
|
||||
{"text": "在地图上有一个名为 '17栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129717, 118.970176)。"}
|
||||
{"text": "在地图上有一个名为 '16栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129524, 118.969207)。"}
|
||||
{"text": "在地图上有一个名为 '15栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129399, 118.968380)。"}
|
||||
{"text": "在地图上有一个名为 '9栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128441, 118.969340)。"}
|
||||
{"text": "在地图上有一个名为 '6栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127960, 118.969911)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127368, 118.969415)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127087, 118.968454)。"}
|
||||
{"text": "在地图上有一个名为 '5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.127656, 118.968453)。"}
|
||||
{"text": "在地图上有一个名为 '8栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128310, 118.968501)。"}
|
||||
{"text": "在地图上有一个名为 '12栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.128893, 118.968532)。"}
|
||||
{"text": "在地图上有一个名为 '13栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.129073, 118.969856)。"}
|
||||
{"text": "在地图上有一个名为 '3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.130874, 118.970144)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.130780, 118.969386)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.130813, 118.968619)。"}
|
||||
{"text": "在地图上有一个名为 '13栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131817, 118.969006)。"}
|
||||
{"text": "在地图上有一个名为 '14栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131887, 118.969861)。"}
|
||||
{"text": "在地图上有一个名为 '22栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132974, 118.969870)。"}
|
||||
{"text": "在地图上有一个名为 '18栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132380, 118.969319)。"}
|
||||
{"text": "在地图上有一个名为 '19栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132455, 118.970049)。"}
|
||||
{"text": "在地图上有一个名为 '9栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131374, 118.970134)。"}
|
||||
{"text": "在地图上有一个名为 '8栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131265, 118.969410)。"}
|
||||
{"text": "在地图上有一个名为 '7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131298, 118.968695)。"}
|
||||
{"text": "在地图上有一个名为 '10栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.133020, 118.966464)。"}
|
||||
{"text": "在地图上有一个名为 '7栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132756, 118.966139)。"}
|
||||
{"text": "在地图上有一个名为 '4栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132447, 118.965873)。"}
|
||||
{"text": "在地图上有一个名为 '3栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132080, 118.966671)。"}
|
||||
{"text": "在地图上有一个名为 '1栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131734, 118.966638)。"}
|
||||
{"text": "在地图上有一个名为 '2栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.131682, 118.967276)。"}
|
||||
{"text": "在地图上有一个名为 '5栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132085, 118.967455)。"}
|
||||
{"text": "在地图上有一个名为 '8栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132447, 118.967655)。"}
|
||||
{"text": "在地图上有一个名为 '11栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132833, 118.967891)。"}
|
||||
{"text": "在地图上有一个名为 '12栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.133128, 118.967260)。"}
|
||||
{"text": "在地图上有一个名为 '9栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132782, 118.967042)。"}
|
||||
{"text": "在地图上有一个名为 '6栋' 的地点或区域,它的building是'yes',其中心位置坐标大约在 (32.132436, 118.966831)。"}
|
||||
{"text": "在地图上有一个名为 '仙林自行车场' 的地点或区域,它的leisure是'sports_centre'、name:zh是'仙林自行车场'、sport是'cycling',其中心位置坐标大约在 (32.117653, 118.960528)。"}
|
||||
{"text": "在地图上有一个名为 '1号楼' 的地点或区域,它的building是'commercial',其中心位置坐标大约在 (32.129982, 118.953671)。"}
|
||||
318
tools/knowledge_base/first.ndjson
Normal file
318
tools/knowledge_base/first.ndjson
Normal file
@@ -0,0 +1,318 @@
|
||||
{"text": "仿真环境中有一个名为 'wall' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.0, 49.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.0, -49.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [49.0, 0.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-49.0, 0.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'law_office_82' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.47, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'thrift_shop_83' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.35, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'salon_84' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [15.7, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_85' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-6.418, 10.37, 0.0, 0.0, -0.0, 0.55]。"}
|
||||
{"text": "仿真环境中有一个名为 'apartment_86' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.573, 27.565, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'osrf_first_office_87' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.003, 20.15, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_88' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [16.096, 34.82, 0.0, 0.0, -0.0, 2.24546]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_89' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [18.7, 29.33, 0.0, 0.0, -0.0, 0.605226]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_90' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [22.56, 34.58, 0.0, 0.0, -0.0, 0.34397]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_91' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [31.49, 35.89, 0.0, 0.0, 0.0, -3.03]。"}
|
||||
{"text": "仿真环境中有一个名为 'postbox_92' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.0, 4.33, 0.15, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'fast_food_93' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.25, -13.93, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'dumpster_94' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [15.94, -13.63, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'fire_hydrant_95' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [38.5, -4.38, 0.15, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.61, -14.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_126' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-0.59, -26.6, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_127' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -37.0, 0.0, 0.0, -0.0, 0.124132]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_128' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-2.0, -37.0, 0.0, 0.0, -0.0, 0.143519]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_129' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.0, -37.0, 0.0, 0.0, -0.0, 1.74324]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_130' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.0, -37.0, 0.0, 0.0, -0.0, 2.04822]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_131' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.0, -37.0, 0.0, 0.0, -0.0, 0.035642]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_132' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -32.0, 0.0, 0.0, -0.0, 2.69167]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_133' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -27.0, 0.0, 0.0, -0.0, 1.45432]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_134' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -22.0, 0.0, 0.0, -0.0, 2.10283]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_135' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -17.0, 0.0, 0.0, -0.0, 1.33207]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_136' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -12.0, 0.0, 0.0, -0.0, 2.93245]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_137' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -7.0, 0.0, 0.0, -0.0, 0.63871]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_138' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-2.0, -8.0, 0.0, 0.0, -0.0, 0.416833]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_139' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.0, -8.0, 0.0, 0.0, -0.0, 1.84106]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_140' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.0, -8.0, 0.0, 0.0, -0.0, 2.21107]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_141' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.0, -8.0, 0.0, 0.0, -0.0, 0.145852]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_142' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [18.0, -8.0, 0.0, 0.0, -0.0, 2.31415]。"}
|
||||
{"text": "仿真环境中有一个名为 'post_office_143' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-26.686, 11.119, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'postbox_144' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.58, 4.33, 0.15, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_145' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-30.709, 7.15, 0.0, 0.0, -0.0, 2.2424]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_1_146' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.49, 25.344, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_147' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-36.72, 21.02, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_148' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.811, 11.78, 0.0, 0.0, -0.0, 0.55]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_149' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.97, 15.87, 0.0, 0.0, -0.0, 1.82]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_150' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-36.78, 36.47, 0.0, 0.0, -0.0, 1.7]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_151' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-23.94, 34.92, 0.0, 0.0, -0.0, 0.56]。"}
|
||||
{"text": "仿真环境中有一个名为 'cardboard_box_152' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-32.0, 8.0, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'salon_154' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.65, -9.35, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'law_office_155' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-34.886, -9.408, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_156' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-33.39, -21.3, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_157' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.126, -32.93, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_158' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.739, -19.38, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_159' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-37.48, -13.67, 0.0, 0.0, -0.0, 2.99694]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_160' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.26, -7.39, 0.0, 0.0, -0.0, 0.002426]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_161' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.26, -10.46, 0.0, 0.0, -0.0, 0.646469]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_162' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.045, -28.058, 0.0, 0.0, -0.0, 2.2678]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_163' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-37.48, -36.76, 0.0, 0.0, -0.0, 1.67752]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_164' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-33.06, -37.17, 0.0, 0.0, -0.0, 0.584309]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_165' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.34, -29.166, 0.0, 0.0, -0.0, 2.40377]。"}
|
||||
{"text": "仿真环境中有一个名为 'fire_hydrant_166' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-20.34, -4.38, 0.15, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_169' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_170' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_171' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_172' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_174' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-48.7, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_175' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_176' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_177' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_178' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_180' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-48.7, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_181' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_183' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_184' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -41.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_185' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_186' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_187' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_189' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_190' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_191' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-3.0, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_192' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [9.0, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_193' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [21.0, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_194' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.0, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_199' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_200' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_201' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_202' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_203' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_204' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_205' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_206' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_207' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_208' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_211' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_212' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_213' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_214' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_215' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_216' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_218' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_219' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_220' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_223' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_224' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_225' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_226' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_227' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_228' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_229' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_230' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_231' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_232' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_233' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_234' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_241' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-17.55, -32.5226, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_242' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-12.45, -20.8953, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'suv_243' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [42.45, -34.7406, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_244' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [47.55, -27.5423, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_245' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-17.55, 32.931, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_246' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-12.45, 30.6875, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_247' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [42.45, 28.0591, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_249' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-24.9957, -2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_250' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-21.6052, 2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'suv_251' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [21.4393, -2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_252' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [7.08835, 2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'apartment_86' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.573, 27.565, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'cardboard_box_152' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-32.0, 8.0, 0.149, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'dumpster_94' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [15.94, -13.63, 0.000918, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'fast_food_93' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.25, -13.93, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'fire_hydrant_166' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-20.34, -4.38, 0.15, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'fire_hydrant_95' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [38.5, -4.38, 0.15, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'ground_plane_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.0, 0.0, -0.1, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_247' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [42.45, 28.0591, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_250' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-21.6052, 2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_241' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-17.55, -32.5226, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_245' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-17.55, 32.931, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'hatchback_blue_252' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [7.08835, 2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_1_146' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.49, 25.344, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.61, -14.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [14.3003, -27.3963, 0.0, 0.0, -0.0, 3.14159]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125_clone_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.4365, -27.4764, 0.0, 0.0, -0.0, 3.14159]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_126' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-0.59, -26.6, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_156' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-33.39, -21.3, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_157' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.126, -32.93, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_3_158' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.739, -19.38, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_189' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_190' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_191' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-3.0, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_192' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [9.0, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_193' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [21.0, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'lamp_post_194' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.0, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'law_office_155' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-34.886, -9.408, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'law_office_82' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.47, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_148' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.811, 11.78, 0.0, 0.0, -0.0, 0.55]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_150' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-36.78, 36.47, 0.0, 0.0, -0.0, 1.7]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_85' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-6.418, 10.37, 0.0, 0.0, -0.0, 0.55]。"}
|
||||
{"text": "仿真环境中有一个名为 'oak_tree_91' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [31.49, 35.89, 0.0, 0.0, 0.0, -3.03]。"}
|
||||
{"text": "仿真环境中有一个名为 'osrf_first_office_87' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.003, 20.15, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_147' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-36.72, 21.02, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_242' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-12.45, -20.8953, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_244' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [47.55, -27.5423, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_246' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-12.45, 30.6875, 0.0, 0.0, -0.0, 1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'pickup_249' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-24.9957, -2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_127' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -37.0, 0.0, 0.0, -0.0, 0.124132]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_128' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-2.0, -37.0, 0.0, 0.0, -0.0, 0.143519]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_129' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.0, -37.0, 0.0, 0.0, -0.0, 1.74324]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_130' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.0, -37.0, 0.0, 0.0, -0.0, 2.04822]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_131' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.0, -37.0, 0.0, 0.0, -0.0, 0.035642]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_132' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -32.0, 0.0, 0.0, -0.0, 2.69167]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_133' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -27.0, 0.0, 0.0, -0.0, 1.45432]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_134' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -22.0, 0.0, 0.0, -0.0, 2.10283]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_135' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -17.0, 0.0, 0.0, -0.0, 1.33207]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_136' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -12.0, 0.0, 0.0, -0.0, 2.93245]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_137' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-7.0, -7.0, 0.0, 0.0, -0.0, 0.63871]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_138' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-2.0, -8.0, 0.0, 0.0, -0.0, 0.416833]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_139' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.0, -8.0, 0.0, 0.0, -0.0, 1.84106]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_140' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.0, -8.0, 0.0, 0.0, -0.0, 2.21107]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_141' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.0, -8.0, 0.0, 0.0, -0.0, 0.145852]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_142' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [18.0, -8.0, 0.0, 0.0, -0.0, 2.31415]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_145' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-30.709, 7.15, 0.0, 0.0, -0.0, 2.2424]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_149' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.97, 15.87, 0.0, 0.0, -0.0, 1.82]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_151' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-23.94, 34.92, 0.0, 0.0, -0.0, 0.56]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_159' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-37.48, -13.67, 0.0, 0.0, -0.0, 2.99694]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_160' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.26, -7.39, 0.0, 0.0, -0.0, 0.002426]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_161' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-22.26, -10.46, 0.0, 0.0, -0.0, 0.646469]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_162' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.045, -28.058, 0.0, 0.0, -0.0, 2.2678]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_163' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-37.48, -36.76, 0.0, 0.0, -0.0, 1.67752]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_164' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-33.06, -37.17, 0.0, 0.0, -0.0, 0.584309]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_165' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.34, -29.166, 0.0, 0.0, -0.0, 2.40377]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_88' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [16.096, 34.82, 0.0, 0.0, -0.0, 2.24546]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_89' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [18.7, 29.33, 0.0, 0.0, -0.0, 0.605226]。"}
|
||||
{"text": "仿真环境中有一个名为 'pine_tree_90' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [22.56, 34.58, 0.0, 0.0, -0.0, 0.34397]。"}
|
||||
{"text": "仿真环境中有一个名为 'post_office_143' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-26.686, 11.119, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'postbox_144' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.58, 4.33, 0.15, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'postbox_92' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.0, 4.33, 0.15, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'salon_154' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.65, -9.35, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'salon_84' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [15.7, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_169' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_170' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_171' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_172' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_174' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-48.7, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_175' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_176' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_177' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_178' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_180' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-48.7, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_light_post_181' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_183' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -3.7, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_184' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -41.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_185' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 3.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_186' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'stop_sign_187' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -3.7, 0.0, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'suv_243' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [42.45, -34.7406, 0.0, 0.0, 0.0, -1.5708]。"}
|
||||
{"text": "仿真环境中有一个名为 'suv_251' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [21.4393, -2.55, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_199' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_200' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_201' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_202' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_203' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_204' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_205' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_206' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_206_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_207' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -30.15, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_208' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, -15.3, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_211' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_212' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-41.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_213' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_214' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-11.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_215' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_216' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-18.7, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_218' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.7, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_219' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 14.85, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_220' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [41.3, 29.7, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_223' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_224' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_225' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_226' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_227' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-35.1, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_228' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.2, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_229' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_230' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, -41.3, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_231' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_232' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, 3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_233' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.8, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_234' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.6, -3.7, 0.0, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.626, 29.3431, 1.5636, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.5396, 9.27041, 1.52314, 0.0, -0.0, 3.1384]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-34.6937, -19.4703, 1.23472, 0.0, -0.0, 1.58393]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_10' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.85316, -27.5651, 1.06281, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_11' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.1838, -29.0718, 1.3, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_12' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.2798, -29.1869, 1.3, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-24.4421, -21.2078, 1.23942, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-29.9588, -34.22, 1.21346, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-34.8868, -8.05648, 1.65897, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [9.49647, 25.4469, 1.93202, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_6' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-0.959037, 7.52929, 2.3312, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_7' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [24.485, 8.07813, 1.9831, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_8' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.6711, -17.7386, 2.25038, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_9' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.6481, -15.5815, 1.21912, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-24.9409, 28.6794, 1.57869, 0.0, 0.0, -1.52716]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-32.0989, -20.9209, 1.20285, 0.0, 0.0, -1.56366]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.0336, -19.7574, 1.20887, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_10' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.4714, -25.2341, 1.3, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_11' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.6367, -25.3145, 1.3, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.5112, -31.6317, 1.21235, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.3234, -7.52915, 1.96408, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-6.48868, 24.506, 1.93221, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.51104, 7.97486, 1.5687, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_6' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [29.5159, 8.05862, 1.68793, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_7' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.6861, -10.0987, 1.62563, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_8' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.18864, -12.1442, 1.04206, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_9' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-2.59305, -27.0309, 1.08359, 0.0, -0.0, 1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [16.0786, -29.8724, 1.3, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [30.5156, -30.1889, 1.3, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.3752, 7.56599, 2.29163, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.82571, -16.4045, 0.823551, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.66214, -24.3491, 0.831783, 0.0, 0.0, -1.57]。"}
|
||||
{"text": "仿真环境中有一个名为 'thrift_shop_83' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.35, 9.356, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.0, 49.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.0, -49.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [49.0, 0.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'wall_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-49.0, 0.0, 2.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-31.827, 31.5085, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-25.6311, 30.6182, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-26.8003, 8.35325, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-37.6617, -20.0872, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-31.2117, -23.79, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-23.4712, -20.896, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_1' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-27.3657, -20.3372, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-29.8503, -35.7088, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_2' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.8359, -31.3351, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-34.1638, -5.49078, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-28.8844, -5.77655, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [12.5719, 24.0672, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-9.74093, 24.1795, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_6' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-0.52561, 3.27106, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [8.06137, 6.29462, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_7' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [21.4701, 4.0873, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_6' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [31.9781, 5.86941, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_8' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.8526, -31.0723, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_7' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [31.517, -2.96729, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_9' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [0.448999, -17.1905, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_8' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [1.08878, -11.5143, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_10' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [11.1354, -29.1096, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_9' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-4.35234, -25.1903, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [14.0061, 1.63948, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_4' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [4.2153, -19.7779, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_5' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [3.52886, -24.2947, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'ground_plane_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [-10.2583, 20.1204, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'telephone_pole_206_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [48.6722, 16.6841, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [11.3102, -26.491, 0.0, 0.0, -0.0, 3.14]。"}
|
||||
{"text": "仿真环境中有一个名为 'house_2_125_clone_clone' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [28.4365, -27.4764, 0.0, 0.0, -0.0, 3.14159]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_11' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.1838, -29.0718, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [16.0786, -29.8724, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_10' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [13.4714, -25.2341, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model2_11' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.6367, -25.3145, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model1_12' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [27.2798, -29.1869, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
{"text": "仿真环境中有一个名为 'text_model3_0' 的物体,其位置和姿态(x, y, z, roll, pitch, yaw)为: [30.5156, -30.1889, 0.0, 0.0, -0.0, 0.0]。"}
|
||||
70349
tools/map/export.json
Normal file
70349
tools/map/export.json
Normal file
File diff suppressed because it is too large
Load Diff
75
tools/test_api.py
Normal file
75
tools/test_api.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
# --- Configuration ---
|
||||
# The base URL of your running FastAPI service
|
||||
BASE_URL = "http://127.0.0.1:8000"
|
||||
|
||||
# The endpoint we want to test
|
||||
ENDPOINT = "/generate_plan"
|
||||
|
||||
# The user prompt we will send for the test
|
||||
TEST_PROMPT = "无人机从信息化建设管理服务中心起飞,飞到学生宿舍10幢降落"
|
||||
|
||||
def test_generate_plan():
|
||||
"""
|
||||
Sends a request to the /generate_plan endpoint and validates the response.
|
||||
"""
|
||||
url = BASE_URL + ENDPOINT
|
||||
payload = {"user_prompt": TEST_PROMPT}
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
print("--- API Test: Generate Plan ---")
|
||||
print(f"✅ URL: {url}")
|
||||
print(f"✅ Sending Prompt: \"{TEST_PROMPT}\"")
|
||||
|
||||
try:
|
||||
# Send the POST request
|
||||
response = requests.post(url, data=json.dumps(payload), headers=headers)
|
||||
|
||||
# Check for HTTP errors (e.g., 404, 500)
|
||||
response.raise_for_status()
|
||||
|
||||
# Parse the JSON response
|
||||
data = response.json()
|
||||
|
||||
print("✅ Received Response:")
|
||||
print(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
|
||||
# --- Validation ---
|
||||
print("\n--- Validation Checks ---")
|
||||
|
||||
# 1. Check if the response is a dictionary
|
||||
if isinstance(data, dict):
|
||||
print("PASS: Response is a valid JSON object.")
|
||||
else:
|
||||
print("FAIL: Response is not a valid JSON object.")
|
||||
return
|
||||
|
||||
# 2. Check for the existence of the 'root' key
|
||||
if "root" in data and isinstance(data['root'], dict):
|
||||
print("PASS: Response contains a valid 'root' key.")
|
||||
else:
|
||||
print("FAIL: Response does not contain a valid 'root' key.")
|
||||
|
||||
# 3. Check for the existence and format of the 'visualization_url' key
|
||||
if "visualization_url" in data and data["visualization_url"].endswith(".png"):
|
||||
print(f"PASS: Response contains a valid 'visualization_url': {data['visualization_url']}")
|
||||
else:
|
||||
print("FAIL: Response does not contain a valid 'visualization_url'.")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"\n❌ TEST FAILED: Could not connect to the server.")
|
||||
print(" Please make sure the backend service is running.")
|
||||
print(f" Error details: {e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"\n❌ TEST FAILED: The server response was not valid JSON.")
|
||||
print(f" Response text: {response.text}")
|
||||
except Exception as e:
|
||||
print(f"\n❌ TEST FAILED: An unexpected error occurred: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_generate_plan()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tools/vector_store/chroma.sqlite3
Normal file
BIN
tools/vector_store/chroma.sqlite3
Normal file
Binary file not shown.
Reference in New Issue
Block a user