Initial webpage and backend
This commit is contained in:
16
toid_cli/package.xml
Normal file
16
toid_cli/package.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>toid_cli</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="82343504+pimpest@users.noreply.github.com">petar</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
<depend>python3-fastapi</depend>
|
||||
<depend>python3-pydantic</depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_python</build_type>
|
||||
</export>
|
||||
</package>
|
||||
0
toid_cli/resource/toid_cli
Normal file
0
toid_cli/resource/toid_cli
Normal file
4
toid_cli/setup.cfg.old
Normal file
4
toid_cli/setup.cfg.old
Normal file
@@ -0,0 +1,4 @@
|
||||
[develop]
|
||||
script_dir=$base/lib/toid_cli
|
||||
[install]
|
||||
install_scripts=$base/lib/toid_cli
|
||||
25
toid_cli/setup.py
Normal file
25
toid_cli/setup.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
package_name = 'toid_cli'
|
||||
|
||||
setup(
|
||||
name=package_name,
|
||||
version='0.0.0',
|
||||
packages=find_packages(exclude=['test']),
|
||||
data_files=[
|
||||
('share/ament_index/resource_index/packages',
|
||||
['resource/' + package_name]),
|
||||
('share/' + package_name, ['package.xml']),
|
||||
],
|
||||
install_requires=['setuptools'],
|
||||
zip_safe=True,
|
||||
maintainer='pimpest',
|
||||
maintainer_email='82343504+pimpest@users.noreply.github.com',
|
||||
description='TODO: Package description',
|
||||
license='MIT',
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'toid_cli = toid_cli.main:main'
|
||||
],
|
||||
},
|
||||
)
|
||||
0
toid_cli/toid_cli/__init__.py
Normal file
0
toid_cli/toid_cli/__init__.py
Normal file
108
toid_cli/toid_cli/main.py
Normal file
108
toid_cli/toid_cli/main.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import subprocess
|
||||
import uuid
|
||||
import os
|
||||
import signal
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
import uvicorn
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[
|
||||
"*"
|
||||
],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
# store running launch processes
|
||||
launch_processes = {}
|
||||
|
||||
|
||||
class LaunchRequest(BaseModel):
|
||||
package: str
|
||||
launch_file: str
|
||||
args: dict = {}
|
||||
|
||||
|
||||
@app.post("/launch/start")
|
||||
def start_launch(req: LaunchRequest):
|
||||
launch_id = str(uuid.uuid4())
|
||||
|
||||
cmd = ["ros2", "launch", req.package, req.launch_file]
|
||||
|
||||
for k, v in req.args.items():
|
||||
cmd.append(f"{k}:={v}")
|
||||
|
||||
log_dir = "log"
|
||||
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
|
||||
stdout_file = open(f"{log_dir}/{launch_id}_stdout.log", "w")
|
||||
stderr_file = open(f"{log_dir}/{launch_id}_stderr.log", "w")
|
||||
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=stdout_file,
|
||||
stderr=stderr_file,
|
||||
preexec_fn=os.setsid
|
||||
)
|
||||
|
||||
launch_processes[launch_id] = proc
|
||||
|
||||
return {
|
||||
"launch_id": launch_id,
|
||||
"pid": proc.pid,
|
||||
"command": " ".join(cmd)
|
||||
}
|
||||
|
||||
|
||||
@app.get("/launch/list")
|
||||
def list_launches():
|
||||
running = {}
|
||||
|
||||
for lid, proc in launch_processes.items():
|
||||
running[lid] = {
|
||||
"pid": proc.pid,
|
||||
"running": proc.poll() is None
|
||||
}
|
||||
|
||||
return running
|
||||
|
||||
|
||||
@app.post("/launch/stop/{launch_id}")
|
||||
def stop_launch(launch_id: str):
|
||||
|
||||
if launch_id not in launch_processes:
|
||||
return {"error": "launch id not found"}
|
||||
|
||||
proc = launch_processes[launch_id]
|
||||
|
||||
if proc.poll() is None:
|
||||
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||
|
||||
return {"stopped": launch_id}
|
||||
|
||||
|
||||
@app.post("/launch/stop_all")
|
||||
def stop_all():
|
||||
|
||||
for proc in launch_processes.values():
|
||||
if proc.poll() is None:
|
||||
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||
|
||||
return {"status": "all stopped"}
|
||||
|
||||
def main():
|
||||
uvicorn.run(
|
||||
"toid_cli.main:app",
|
||||
host="0.0.0.0",
|
||||
port=8000,
|
||||
reload=False
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user