from nicegui import ui, binding, app import subprocess from collections import defaultdict # Dictionary of applications: key is the button text, value is the command to execute applications = { "Terminal": ["qterminal"], "rqt": ["rqt"], "rviz2": ["rviz2"], "Gazebo": ["/spawn_drones.sh"], "Gazebo Standalone": "gz sim -v4".split(), # Add more applications here if needed } # Function to launch an application def launch_app(command): try: subprocess.Popen(command) except FileNotFoundError: print(f"{command[0]} not found. Make sure it's installed and accessible in the PATH.") # Create the NiceGUI interface ui.label("Spiri Robotics SDK").style('font-size: 40px; margin-bottom: 10px;').classes('w-full text-center') robots = [] from spiri_sdk_guitools.sim_drone import Robot @ui.page('/') def main(): with ui.tabs().classes('w-full') as tabs: tab_tools = ui.tab('Tools') tab_robots = ui.tab('Robots') # two = ui.tab('Two') with ui.tab_panels(tabs, value=tab_tools).classes(): with ui.tab_panel(tab_tools): # Create and place buttons dynamically based on the dictionary with ui.grid(columns=3): for app_name, command in applications.items(): ui.button(app_name, on_click=lambda cmd=command: launch_app(cmd)).style('width: 150px; height: 50px; margin: 5px;') with ui.tab_panel(tab_robots): with ui.grid(columns=3): for robot in robots: with ui.row(): ui.label(f"Robot {robot.sys_id}") ui.button(f"Start Robot {robot.sys_id}", on_click=lambda: robot.start()).style('width: 150px; height: 50px; margin: 5px;') #Add a new robot with ui.element(): ui.label("Add new robot") newRobotParams = defaultdict(binding.BindableProperty) ui.number(value=0, label="SysID").bind_value(newRobotParams, 'sysid') ui.input(value="./sdk/docker-compose.yml", label="Compose files (comma seperated)").bind_value(newRobotParams, 'compose_files') def new_robot(): robot = Robot(**newRobotParams) robots.append(robot) ui.label(str(robots)) ui.button("Add", on_click=new_robot) # Start the NiceGUI application ui.run(title="Spiri SDK Launcher", port=8923, dark=None)