diff --git a/common/libcommon.a b/common/libcommon.a index 91862e60f3..9639ce5453 100644 Binary files a/common/libcommon.a and b/common/libcommon.a differ diff --git a/common/params_keys.h b/common/params_keys.h index 9e2d28d210..9b360004f5 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -463,6 +463,7 @@ inline static std::unordered_map keys = { {"VisionSpeedLimitAutoBookmark", {PERSISTENT, BOOL, "0", "0", 0}}, {"VisionSpeedLimitAutoPreserveSegment", {PERSISTENT, BOOL, "0", "0", 0}}, {"VisionSpeedLimitDetection", {PERSISTENT, BOOL, "0", "0", 0}}, + {"VisionSpeedLimitTrainingCollector", {PERSISTENT, BOOL, "1", "1", 0}}, {"StandardFollow", {PERSISTENT, FLOAT, "1.45", "1.45", 2}}, {"StandardFollowHigh", {PERSISTENT, FLOAT, "1.45", "1.45", 2}}, {"StandardJerkAcceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}}, diff --git a/common/params_pyx.so b/common/params_pyx.so index b78ed81ff8..7735b8451f 100755 Binary files a/common/params_pyx.so and b/common/params_pyx.so differ diff --git a/panda/board/obj/body_h7.bin.signed b/panda/board/obj/body_h7.bin.signed index 72b290d68b..910be7b6ff 100644 Binary files a/panda/board/obj/body_h7.bin.signed and b/panda/board/obj/body_h7.bin.signed differ diff --git a/panda/board/obj/body_h7/bootstub.elf b/panda/board/obj/body_h7/bootstub.elf index ea483bf0a2..876fe6ba24 100755 Binary files a/panda/board/obj/body_h7/bootstub.elf and b/panda/board/obj/body_h7/bootstub.elf differ diff --git a/panda/board/obj/body_h7/main.bin b/panda/board/obj/body_h7/main.bin index 432db51f65..d923849693 100755 Binary files a/panda/board/obj/body_h7/main.bin and b/panda/board/obj/body_h7/main.bin differ diff --git a/panda/board/obj/body_h7/main.elf b/panda/board/obj/body_h7/main.elf index 29709e889e..f17445215c 100755 Binary files a/panda/board/obj/body_h7/main.elf and b/panda/board/obj/body_h7/main.elf differ diff --git a/panda/board/obj/bootstub.body_h7.bin b/panda/board/obj/bootstub.body_h7.bin index 88af1466ea..3239818326 100755 Binary files a/panda/board/obj/bootstub.body_h7.bin and b/panda/board/obj/bootstub.body_h7.bin differ diff --git a/panda/board/obj/bootstub.panda.bin b/panda/board/obj/bootstub.panda.bin index f2322a6653..d4df9df09f 100755 Binary files a/panda/board/obj/bootstub.panda.bin and b/panda/board/obj/bootstub.panda.bin differ diff --git a/panda/board/obj/bootstub.panda_h7.bin b/panda/board/obj/bootstub.panda_h7.bin index 76336ad582..e69e32136d 100755 Binary files a/panda/board/obj/bootstub.panda_h7.bin and b/panda/board/obj/bootstub.panda_h7.bin differ diff --git a/panda/board/obj/bootstub.panda_h7_remote.bin b/panda/board/obj/bootstub.panda_h7_remote.bin index 76336ad582..e69e32136d 100755 Binary files a/panda/board/obj/bootstub.panda_h7_remote.bin and b/panda/board/obj/bootstub.panda_h7_remote.bin differ diff --git a/panda/board/obj/bootstub.panda_jungle_h7.bin b/panda/board/obj/bootstub.panda_jungle_h7.bin index 4c6f82487f..8e622a110f 100755 Binary files a/panda/board/obj/bootstub.panda_jungle_h7.bin and b/panda/board/obj/bootstub.panda_jungle_h7.bin differ diff --git a/panda/board/obj/bootstub.panda_remote.bin b/panda/board/obj/bootstub.panda_remote.bin index f2322a6653..d4df9df09f 100755 Binary files a/panda/board/obj/bootstub.panda_remote.bin and b/panda/board/obj/bootstub.panda_remote.bin differ diff --git a/panda/board/obj/gitversion.h b/panda/board/obj/gitversion.h index e1e7307ca9..b66631f889 100644 --- a/panda/board/obj/gitversion.h +++ b/panda/board/obj/gitversion.h @@ -1,2 +1,2 @@ extern const uint8_t gitversion[19]; -const uint8_t gitversion[19] = "DEV-bbec8558-DEBUG"; +const uint8_t gitversion[19] = "DEV-a695eda0-DEBUG"; diff --git a/panda/board/obj/panda.bin.signed b/panda/board/obj/panda.bin.signed index 5b993b34b3..14567635ef 100644 Binary files a/panda/board/obj/panda.bin.signed and b/panda/board/obj/panda.bin.signed differ diff --git a/panda/board/obj/panda/bootstub.elf b/panda/board/obj/panda/bootstub.elf index 1f7f06056a..f00d413f40 100755 Binary files a/panda/board/obj/panda/bootstub.elf and b/panda/board/obj/panda/bootstub.elf differ diff --git a/panda/board/obj/panda/main.bin b/panda/board/obj/panda/main.bin index b73ff6285f..b7ba3bd561 100755 Binary files a/panda/board/obj/panda/main.bin and b/panda/board/obj/panda/main.bin differ diff --git a/panda/board/obj/panda/main.elf b/panda/board/obj/panda/main.elf index 541d6c5cf6..cc2125901d 100755 Binary files a/panda/board/obj/panda/main.elf and b/panda/board/obj/panda/main.elf differ diff --git a/panda/board/obj/panda_h7.bin.signed b/panda/board/obj/panda_h7.bin.signed index 1bb894ebf2..c0592f1577 100644 Binary files a/panda/board/obj/panda_h7.bin.signed and b/panda/board/obj/panda_h7.bin.signed differ diff --git a/panda/board/obj/panda_h7/bootstub.elf b/panda/board/obj/panda_h7/bootstub.elf index 4218dfb875..e55d474c91 100755 Binary files a/panda/board/obj/panda_h7/bootstub.elf and b/panda/board/obj/panda_h7/bootstub.elf differ diff --git a/panda/board/obj/panda_h7/main.bin b/panda/board/obj/panda_h7/main.bin index 47135c63f2..8a771a8534 100755 Binary files a/panda/board/obj/panda_h7/main.bin and b/panda/board/obj/panda_h7/main.bin differ diff --git a/panda/board/obj/panda_h7/main.elf b/panda/board/obj/panda_h7/main.elf index 18d393b0bb..3324136c09 100755 Binary files a/panda/board/obj/panda_h7/main.elf and b/panda/board/obj/panda_h7/main.elf differ diff --git a/panda/board/obj/panda_h7_remote.bin.signed b/panda/board/obj/panda_h7_remote.bin.signed index 4cedb3f608..3695b05caf 100644 Binary files a/panda/board/obj/panda_h7_remote.bin.signed and b/panda/board/obj/panda_h7_remote.bin.signed differ diff --git a/panda/board/obj/panda_h7_remote/bootstub.elf b/panda/board/obj/panda_h7_remote/bootstub.elf index 65d30202ac..3decfb5683 100755 Binary files a/panda/board/obj/panda_h7_remote/bootstub.elf and b/panda/board/obj/panda_h7_remote/bootstub.elf differ diff --git a/panda/board/obj/panda_h7_remote/main.bin b/panda/board/obj/panda_h7_remote/main.bin index 26c9cd09f4..a48004c358 100755 Binary files a/panda/board/obj/panda_h7_remote/main.bin and b/panda/board/obj/panda_h7_remote/main.bin differ diff --git a/panda/board/obj/panda_h7_remote/main.elf b/panda/board/obj/panda_h7_remote/main.elf index 1d35db64f8..9999b57b71 100755 Binary files a/panda/board/obj/panda_h7_remote/main.elf and b/panda/board/obj/panda_h7_remote/main.elf differ diff --git a/panda/board/obj/panda_jungle_h7.bin.signed b/panda/board/obj/panda_jungle_h7.bin.signed index 48abf0f9c6..9182d2206d 100644 Binary files a/panda/board/obj/panda_jungle_h7.bin.signed and b/panda/board/obj/panda_jungle_h7.bin.signed differ diff --git a/panda/board/obj/panda_jungle_h7/bootstub.elf b/panda/board/obj/panda_jungle_h7/bootstub.elf index b797d53021..5f3538ba51 100755 Binary files a/panda/board/obj/panda_jungle_h7/bootstub.elf and b/panda/board/obj/panda_jungle_h7/bootstub.elf differ diff --git a/panda/board/obj/panda_jungle_h7/main.bin b/panda/board/obj/panda_jungle_h7/main.bin index 464344a9af..bef71c7d9d 100755 Binary files a/panda/board/obj/panda_jungle_h7/main.bin and b/panda/board/obj/panda_jungle_h7/main.bin differ diff --git a/panda/board/obj/panda_jungle_h7/main.elf b/panda/board/obj/panda_jungle_h7/main.elf index f101b14b15..13d0fadc9c 100755 Binary files a/panda/board/obj/panda_jungle_h7/main.elf and b/panda/board/obj/panda_jungle_h7/main.elf differ diff --git a/panda/board/obj/panda_remote.bin.signed b/panda/board/obj/panda_remote.bin.signed index 8b3447760e..a314cd3af4 100644 Binary files a/panda/board/obj/panda_remote.bin.signed and b/panda/board/obj/panda_remote.bin.signed differ diff --git a/panda/board/obj/panda_remote/bootstub.elf b/panda/board/obj/panda_remote/bootstub.elf index 5003c9cf45..0cc8782445 100755 Binary files a/panda/board/obj/panda_remote/bootstub.elf and b/panda/board/obj/panda_remote/bootstub.elf differ diff --git a/panda/board/obj/panda_remote/main.bin b/panda/board/obj/panda_remote/main.bin index 49251b0427..d520249aef 100755 Binary files a/panda/board/obj/panda_remote/main.bin and b/panda/board/obj/panda_remote/main.bin differ diff --git a/panda/board/obj/panda_remote/main.elf b/panda/board/obj/panda_remote/main.elf index d825fff354..a95d4baaf3 100755 Binary files a/panda/board/obj/panda_remote/main.elf and b/panda/board/obj/panda_remote/main.elf differ diff --git a/panda/board/obj/version b/panda/board/obj/version index 7f4b0f5475..d79b060bac 100644 --- a/panda/board/obj/version +++ b/panda/board/obj/version @@ -1 +1 @@ -DEV-bbec8558-DEBUG \ No newline at end of file +DEV-a695eda0-DEBUG \ No newline at end of file diff --git a/scripts/speed_limit_vision/import_debug_sessions.py b/scripts/speed_limit_vision/import_debug_sessions.py index b890d23555..aa4edfb62e 100644 --- a/scripts/speed_limit_vision/import_debug_sessions.py +++ b/scripts/speed_limit_vision/import_debug_sessions.py @@ -41,7 +41,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--latest", type=int, default=1, help="How many latest sessions to import when no session ids are provided.") parser.add_argument("--mode", choices=("symlink", "copy"), default="symlink", help="How to place snapshots into the workspace review/images directory.") parser.add_argument("--force", action="store_true", help="Overwrite snapshot links/files if they already exist.") - parser.add_argument("--events", nargs="+", default=["bookmark", "auto_bookmark", "publish", "candidate"], help="Event types to include in the manifest.") + parser.add_argument("--events", nargs="+", default=["bookmark", "auto_bookmark", "training_candidate", "publish", "candidate"], help="Event types to include in the manifest.") return parser.parse_args() diff --git a/selfdrive/pandad/pandad b/selfdrive/pandad/pandad index 8ddfb5d888..61769d1d3d 100755 Binary files a/selfdrive/pandad/pandad and b/selfdrive/pandad/pandad differ diff --git a/selfdrive/ui/ui b/selfdrive/ui/ui index 78e81dc3dc..4dd62137ad 100755 Binary files a/selfdrive/ui/ui and b/selfdrive/ui/ui differ diff --git a/starpilot/system/speed_limit_vision.py b/starpilot/system/speed_limit_vision.py index 5be365ca7a..de0424a8e6 100644 --- a/starpilot/system/speed_limit_vision.py +++ b/starpilot/system/speed_limit_vision.py @@ -31,6 +31,9 @@ PUBLISHED_REVERT_CONFIDENCE = 0.97 AUTO_BOOKMARK_CONFIRM_DELAY_SECONDS = 0.9 AUTO_BOOKMARK_COOLDOWN_SECONDS = 8.0 AUTO_BOOKMARK_MIN_CONFIDENCE = 0.62 +TRAINING_COLLECTOR_CONFIRM_DELAY_SECONDS = 0.7 +TRAINING_COLLECTOR_COOLDOWN_SECONDS = 2.5 +TRAINING_COLLECTOR_MIN_CONFIDENCE = 0.40 MODEL_PROPOSAL_MIN_CONFIDENCE = 0.0001 MODEL_PROPOSAL_MAX_COUNT = 16 MODEL_PROPOSAL_MAX_AREA_RATIO = 0.18 @@ -223,6 +226,9 @@ class SpeedLimitVisionDaemon: self.last_auto_bookmark_speed_limit_mph = 0 self.last_auto_bookmark_publish_at = 0.0 self.pending_auto_bookmark = None + self.last_training_capture_at = 0.0 + self.last_training_capture_speed_limit_mph = 0 + self.pending_training_capture = None self.ignore_next_user_bookmark = False self.current_frame_bgr = None @@ -366,6 +372,24 @@ class SpeedLimitVisionDaemon: bookmarkCount=self.debug_bookmark_count, ) + def _record_training_candidate(self, speed_limit_mph, confidence, source_confidence, source_event): + if not self.use_runtime or self.params_memory is None or not self.debug_log_path: + return + + self._write_debug_event( + "training_candidate", + frame_bgr=self.current_frame_bgr, + snapshot_prefix=f"training_candidate_{speed_limit_mph:03d}", + candidateSpeedLimitMph=self.last_candidate_speed_limit_mph, + candidateConfidence=round(self.last_candidate_confidence, 4), + publishedSpeedLimitMph=self.published_speed_limit_mph, + publishedConfidence=round(self.published_confidence, 4), + speedLimitMph=speed_limit_mph, + confidence=round(confidence, 4), + sourceConfidence=round(source_confidence, 4), + sourceEvent=source_event, + ) + def _schedule_auto_bookmark(self, speed_limit_mph, confidence, published_at): if not self.use_runtime or self.params is None: return @@ -383,6 +407,34 @@ class SpeedLimitVisionDaemon: "confidence": confidence, } + def _schedule_training_capture(self, speed_limit_mph, confidence, detected_at): + if not self.use_runtime or self.params is None: + return + if not self.params.get_bool("VisionSpeedLimitTrainingCollector", default=True): + self.pending_training_capture = None + return + if confidence < TRAINING_COLLECTOR_MIN_CONFIDENCE: + return + if detected_at - self.last_training_capture_at < TRAINING_COLLECTOR_COOLDOWN_SECONDS and speed_limit_mph == self.last_training_capture_speed_limit_mph: + return + + pending = self.pending_training_capture + if pending is not None: + if pending["speed_limit_mph"] == speed_limit_mph: + pending["confidence"] = max(float(pending["confidence"]), confidence) + pending["last_seen_at"] = detected_at + return + if detected_at < pending["due_at"] and confidence <= float(pending["confidence"]) + 0.08: + return + + self.pending_training_capture = { + "due_at": detected_at + TRAINING_COLLECTOR_CONFIRM_DELAY_SECONDS, + "detected_at": detected_at, + "last_seen_at": detected_at, + "speed_limit_mph": speed_limit_mph, + "confidence": confidence, + } + def _emit_preserve_bookmark(self): if not self.use_runtime or self.pm is None or self.messaging is None: return @@ -418,6 +470,39 @@ class SpeedLimitVisionDaemon: if self.params is not None and self.params.get_bool("VisionSpeedLimitAutoPreserveSegment"): self._emit_preserve_bookmark() + def _maybe_commit_training_capture(self, now): + pending = self.pending_training_capture + if pending is None or now < pending["due_at"]: + return + if self.params is not None and not self.params.get_bool("VisionSpeedLimitTrainingCollector", default=True): + self.pending_training_capture = None + return + + self.pending_training_capture = None + if self.current_frame_bgr is None: + return + + speed_limit_mph = int(pending["speed_limit_mph"]) + source_confidence = float(pending["confidence"]) + if now - self.last_candidate_at > FOLLOWUP_WINDOW_SECONDS and self.published_speed_limit_mph != speed_limit_mph: + return + + confidence = source_confidence + source_event = "candidate" + if self.last_candidate_speed_limit_mph == speed_limit_mph: + confidence = max(confidence, self.last_candidate_confidence) + if self.published_speed_limit_mph == speed_limit_mph: + confidence = max(confidence, self.published_confidence) + source_event = "publish" + if confidence < TRAINING_COLLECTOR_MIN_CONFIDENCE: + return + if now - self.last_training_capture_at < TRAINING_COLLECTOR_COOLDOWN_SECONDS and speed_limit_mph == self.last_training_capture_speed_limit_mph: + return + + self.last_training_capture_at = now + self.last_training_capture_speed_limit_mph = speed_limit_mph + self._record_training_candidate(speed_limit_mph, confidence, source_confidence, source_event) + def _published_detection_stale(self, now): return self.published_speed_limit_mph > 0 and now - self.last_detection_at > PUBLISHED_HOLD_SECONDS @@ -1336,6 +1421,7 @@ class SpeedLimitVisionDaemon: self.history.clear() self.followup_until = 0.0 self.pending_auto_bookmark = None + self.pending_training_capture = None self.previous_published_speed_limit_mph = self.published_speed_limit_mph self.published_speed_limit_mph = 0 self.published_confidence = 0.0 @@ -1406,6 +1492,7 @@ class SpeedLimitVisionDaemon: self.last_candidate_speed_limit_mph = detection.speed_limit_mph self.last_candidate_confidence = detection.confidence self.last_candidate_at = now + self._schedule_training_capture(detection.speed_limit_mph, detection.confidence, now) candidate_signature = (detection.speed_limit_mph, round(detection.confidence, 2)) if candidate_signature != self.last_logged_candidate: @@ -1529,6 +1616,7 @@ class SpeedLimitVisionDaemon: self._publish_status(f"Scanning {self.stream_name}", clear_speed=False) self._maybe_commit_auto_bookmark(now) + self._maybe_commit_training_capture(now) ratekeeper.keep_time() diff --git a/starpilot/system/the_pond/assets/components/tools/device_settings_layout.json b/starpilot/system/the_pond/assets/components/tools/device_settings_layout.json index a2228f3a06..7ac59046fc 100644 --- a/starpilot/system/the_pond/assets/components/tools/device_settings_layout.json +++ b/starpilot/system/the_pond/assets/components/tools/device_settings_layout.json @@ -1159,6 +1159,14 @@ "ui_type": "toggle", "parent_key": "VisionSpeedLimitDetection" }, + { + "key": "VisionSpeedLimitTrainingCollector", + "label": "Collect Extra Vision Training Samples", + "description": "Save lower-threshold vision sign candidates into the debug session for later training import without showing or applying them live. Leave this on if you want to help improve the model.", + "data_type": "bool", + "ui_type": "toggle", + "parent_key": "VisionSpeedLimitDetection" + }, { "key": "VisionSpeedLimitAutoPreserveSegment", "label": "Preserve Auto-Bookmarked Segments", diff --git a/system/camerad/camerad b/system/camerad/camerad index 1545513b6d..f8db175631 100755 Binary files a/system/camerad/camerad and b/system/camerad/camerad differ diff --git a/system/loggerd/bootlog b/system/loggerd/bootlog index d098674adc..152cc1c758 100755 Binary files a/system/loggerd/bootlog and b/system/loggerd/bootlog differ diff --git a/system/loggerd/encoderd b/system/loggerd/encoderd index ec5d98e6b9..948fc27f86 100755 Binary files a/system/loggerd/encoderd and b/system/loggerd/encoderd differ diff --git a/system/loggerd/loggerd b/system/loggerd/loggerd index 7b63461834..2365adf40e 100755 Binary files a/system/loggerd/loggerd and b/system/loggerd/loggerd differ