diff --git a/common/libcommon.a b/common/libcommon.a index 91862e60f..9639ce545 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 9e2d28d21..9b360004f 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 b78ed81ff..7735b8451 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 72b290d68..910be7b6f 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 ea483bf0a..876fe6ba2 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 432db51f6..d92384969 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 29709e889..f17445215 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 88af1466e..323981832 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 f2322a665..d4df9df09 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 76336ad58..e69e32136 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 76336ad58..e69e32136 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 4c6f82487..8e622a110 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 f2322a665..d4df9df09 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 e1e7307ca..b66631f88 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 5b993b34b..14567635e 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 1f7f06056..f00d413f4 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 b73ff6285..b7ba3bd56 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 541d6c5cf..cc2125901 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 1bb894ebf..c0592f157 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 4218dfb87..e55d474c9 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 47135c63f..8a771a853 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 18d393b0b..3324136c0 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 4cedb3f60..3695b05ca 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 65d30202a..3decfb568 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 26c9cd09f..a48004c35 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 1d35db64f..9999b57b7 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 48abf0f9c..9182d2206 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 b797d5302..5f3538ba5 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 464344a9a..bef71c7d9 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 f101b14b1..13d0fadc9 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 8b3447760..a314cd3af 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 5003c9cf4..0cc878244 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 49251b042..d520249ae 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 d825fff35..a95d4baaf 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 7f4b0f547..d79b060ba 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 b890d2355..aa4edfb62 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 8ddfb5d88..61769d1d3 100755 Binary files a/selfdrive/pandad/pandad and b/selfdrive/pandad/pandad differ diff --git a/selfdrive/ui/ui b/selfdrive/ui/ui index 78e81dc3d..4dd62137a 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 5be365ca7..de0424a8e 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 a2228f3a0..7ac59046f 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 1545513b6..f8db17563 100755 Binary files a/system/camerad/camerad and b/system/camerad/camerad differ diff --git a/system/loggerd/bootlog b/system/loggerd/bootlog index d098674ad..152cc1c75 100755 Binary files a/system/loggerd/bootlog and b/system/loggerd/bootlog differ diff --git a/system/loggerd/encoderd b/system/loggerd/encoderd index ec5d98e6b..948fc27f8 100755 Binary files a/system/loggerd/encoderd and b/system/loggerd/encoderd differ diff --git a/system/loggerd/loggerd b/system/loggerd/loggerd index 7b6346183..2365adf40 100755 Binary files a/system/loggerd/loggerd and b/system/loggerd/loggerd differ