Skip to content

Add files via upload#2291

Open
aash29 wants to merge 1 commit into
dimensionalOS:mainfrom
aash29:strike-agentic-submission
Open

Add files via upload#2291
aash29 wants to merge 1 commit into
dimensionalOS:mainfrom
aash29:strike-agentic-submission

Conversation

@aash29
Copy link
Copy Markdown

@aash29 aash29 commented May 28, 2026

hackathon submission from team strike

hackathon submission from team strike
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Greptile Summary

This PR adds a hackathon demo application (dimensional-hackathon/) for the Unitree Go2 quadruped robot, contributed by team strike. The app wires together WebRTC streaming, LiDAR-based aisle monitoring, YOLO object detection, a FastAPI web dashboard, and a Telegram bot for remote control.

  • demo_app/main.py is the central async orchestrator that subscribes to video/LiDAR streams, runs a 250 ms monitor loop for obstruction detection, and dispatches alerts (snapshot, Telegram photo, audio) when the corridor is blocked.
  • dashboard.py exposes a FastAPI server with WebSocket streams and HTTP command endpoints for robot control; it binds to all interfaces (0.0.0.0) with no authentication, allowing anyone on the same network to send move commands to the robot.
  • config.yaml references a hardcoded relative audio file path (../deploy_agentics_real/assets/alert.wav) that won't resolve for anyone else running the project.

Confidence Score: 3/5

Safe to merge as a self-contained hackathon demo directory, but the HTTP control API has no authentication and binds to all interfaces, which is a real physical-safety concern when deployed on shared Wi-Fi.

The robot control endpoints are openly accessible to anyone on the same network with no credentials required, and the server explicitly binds to 0.0.0.0. At a hackathon venue with shared Wi-Fi, an unintended command could cause the robot to move into people or equipment. The audio file path is also broken out of the box. The rest of the codebase is reasonably well-structured for a demo.

dimensional-hackathon/demo_app/dashboard.py (unauthenticated command endpoints) and dimensional-hackathon/config.yaml (broken audio file path) need the most attention before this is run in any shared environment.

Security Review

  • Unauthenticated robot-control HTTP API (demo_app/dashboard.py, /api/command/{name}): The FastAPI server binds to 0.0.0.0:8080 with no authentication or access control. Any host on the same Wi-Fi network can POST to /api/command/patrol, /api/command/forward, etc. to physically move the robot without credentials. At a shared hackathon venue this is a real physical-safety risk. Consider restricting the bind address to 127.0.0.1 or adding a simple shared-secret check.
  • No CSRF protection on command endpoints: The POST endpoints accept cross-origin requests without any token, making them trivially callable from any page a user on the same network visits.

Important Files Changed

Filename Overview
dimensional-hackathon/demo_app/main.py Central orchestrator wiring all subsystems together; 553 lines of async orchestration that is generally well-structured but the unauthenticated HTTP command API is the most significant concern in this file.
dimensional-hackathon/demo_app/dashboard.py FastAPI app exposing robot commands with no auth, bound to 0.0.0.0; event_log list grows unbounded; WebSocket streaming logic is otherwise clean.
dimensional-hackathon/demo_app/patrol.py Patrol loop and drive helpers; stop() sets a flag and awaits the task without cancelling it, meaning stop may take several seconds if a thread-backed move is in progress — acceptable for a demo but worth noting.
dimensional-hackathon/demo_app/robot.py Go2Runner wraps the WebRTC connection, streams, and movement; connection timeout logic is solid; odom parser silently falls back on None values which is safe.
dimensional-hackathon/demo_app/telegram_bot.py Owner-gated Telegram bot with dead-letter fallback for failed photo sends; retry delays (0, 1, 2, 4 s) are reasonable; caption formatting is clean.
dimensional-hackathon/demo_app/capture.py Rolling frame buffer and snapshot/clip encoder; annotation format bug drops direction info when distance is None; otherwise thread-safe under Python GIL for deque access.
dimensional-hackathon/demo_app/types.py Core dataclasses; Detection uses frozen=True with a mutable np.ndarray field making it technically unhashable despite the frozen annotation.
dimensional-hackathon/demo_app/config.py Pydantic settings with env-var overrides; cooldown_sec field defined in DetectionConfig but never read by any detection logic; KeyError raised directly on missing TELEGRAM_* env vars.
dimensional-hackathon/demo_app/aisle.py LiDAR point-cloud corridor detector; defensive filtering (finite check, height mask, cell counting) is thorough and correct.
dimensional-hackathon/demo_app/detector.py YOLO wrapper with alias-based class matching; model loading is deferred to a thread to avoid blocking the event loop; class resolution logic handles both dict and list name maps.
dimensional-hackathon/config.yaml Runtime config with a broken relative audio file path (../deploy_agentics_real/assets/alert.wav) that won't resolve in any standard setup.
dimensional-hackathon/demo_app/static/index.html Single-page dashboard with canvas-based map, WebSocket video stream, and event log; event payload fields rendered via innerHTML without escaping but all data originates server-side from known command names.

Sequence Diagram

sequenceDiagram
    participant TG as Telegram Bot
    participant Main as main.py (AsyncLoop)
    participant Patrol as PatrolController
    participant Robot as Go2Runner
    participant Aisle as AisleCorridorDetector
    participant Vision as CenterLaneVisionDetector
    participant YOLO as YoloToolDetector
    participant Capture as CaptureBuffer
    participant Web as FastAPI Dashboard

    Robot->>Main: on_frame(frame)
    Robot->>Main: on_lidar(msg)

    loop Monitor Loop (every 250ms)
        Main->>Aisle: analyze(lidar_points)
        Aisle-->>Main: AisleObservation
        Main->>Vision: detect(frame)
        Vision-->>Main: VisionObstruction
        alt corridor blocked
            Main->>YOLO: detect(frame)
            YOLO-->>Main: list[Detection]
            Main->>Capture: snapshot(event)
            Capture-->>Main: jpg_path
            Main->>TG: send_photo_alert(event, jpg_path)
            Main->>Robot: audio.play(event)
            Main->>Web: push_event(corridor_blocked)
        end
    end

    TG->>Main: /patrol command
    Main->>Patrol: start()
    loop Patrol Cycle
        Patrol->>Robot: drive_for_duration(forward)
        Patrol->>Robot: drive_for_duration(yaw sweep)
    end

    Web->>Main: POST /api/command/stop
    Main->>Patrol: stop()
    Patrol-->>Main: (awaits task completion)
Loading

Comments Outside Diff (5)

  1. dimensional-hackathon/demo_app/dashboard.py, line 572-586 (link)

    P1 security Unauthenticated robot-control endpoints on all interfaces

    The HTTP server binds to 0.0.0.0 (via web.host default) and exposes /api/command/{name} with no authentication. Anyone on the same Wi-Fi can POST patrol, forward, back, etc. to physically move the robot without any credentials. At a hackathon venue with shared Wi-Fi this is a real concern — an unintended forward or patrol command could cause the robot to collide with people or equipment. Consider restricting the host to 127.0.0.1 or adding a simple shared-secret header check, even for a demo.

  2. dimensional-hackathon/demo_app/capture.py, line 334-339 (link)

    P2 Direction label silently dropped when distance is None

    The second list element uses implicit f-string concatenation followed by a ternary: f"dir=..." f"dist=..." if condition else "dist=unknown". Python's grammar concatenates the two adjacent f-strings first, making the entire combined string the "then" branch. When obstruction_distance_m is None, the whole line collapses to just "dist=unknown" — the dir= portion is silently omitted from the snapshot annotation, losing useful debug context about which side the obstruction was on.

  3. dimensional-hackathon/demo_app/dashboard.py, line 532-547 (link)

    P2 Unbounded event_log causes uncapped memory growth

    state["event_log"] and web_state["event_log"] are plain lists that are appended to throughout the session and never pruned. The /ws/events WebSocket handler uses a last_seen cursor that also keeps growing. In a long-running patrol session every move, detection, command, and corridor event accumulates indefinitely. Consider capping the list (e.g., keep the last 1000 entries) or switching to a collections.deque(maxlen=...) to bound memory.

  4. dimensional-hackathon/demo_app/types.py, line 447-453 (link)

    P2 frozen=True dataclass with a mutable np.ndarray field

    Detection is declared frozen=True (which implies immutability and attempts to make it hashable), but the frame: np.ndarray field is a mutable numpy array. NumPy arrays are not hashable, so any attempt to put a Detection in a set or as a dict key will raise TypeError: unhashable type: 'numpy.ndarray'. The frozen flag also gives a false impression of deep immutability — the array contents can still be mutated in place. Consider using frozen=False (or setting eq=False) and documenting the intent, or making frame a bytes blob.

  5. dimensional-hackathon/demo_app/config.py, line 441-447 (link)

    P2 cooldown_sec in DetectionConfig is never consumed

    DetectionConfig declares a cooldown_sec field (defaulting to 300 s) and config.yaml sets it to 0, but no code in main.py or detector.py reads this field. The per-detection cooldown logic that would use it is simply absent. The aisle monitor uses cfg.aisle.alert_repeat_sec for its own repeat guard, but YOLO detections have no cooldown applied — every obstruction frame triggers a new Telegram alert as soon as alert_repeat_sec passes, regardless of cooldown_sec. If the intent was to prevent re-alerting on the same object class within a cooldown window, this feature is not implemented.

Reviews (1): Last reviewed commit: "Add files via upload" | Re-trigger Greptile

reclear_consecutive_frames: 2

alert:
audio_file: ../deploy_agentics_real/assets/alert.wav
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The audio_file path is a relative reference to ../deploy_agentics_real/assets/alert.wav, which is outside the repo and almost certainly won't exist for anyone cloning this project. The app will fail silently (the _play_local_blocking catches exceptions) but no alert sound will ever play. The README doesn't mention this file or how to obtain it. Consider shipping a placeholder path (e.g., assets/alert.wav) and documenting how to provide the file.

Suggested change
audio_file: ../deploy_agentics_real/assets/alert.wav
audio_file: assets/alert.wav # Provide a WAV file at this path

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yaalasan
Copy link
Copy Markdown

yaalasan commented May 28, 2026

Link for slides and demo: https://docs.google.com/presentation/d/1Tunlzho993FiveP9Ls0WgZhHAWKzkx-icZYmPOnv6MU/edit?slide=id.p7#slide=id.p7

@leshy leshy added the hackaton label May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants