Sense Core (s6)¶
Sense Core (package s6) is a modular framework for real-time multi-camera instrument tracking, 3D reconstruction, and robotic control. It provides tools for camera calibration, data streaming, inference pipelines, visualization, and hardware integration.
Features¶
Real-time detection and 3D triangulation of instrument tip points using multiple cameras
Interactive GUI (Vispy + PyQt6) displaying live feeds, synthesized views, 3D frustums, and trajectories
Robotic control interface for XYZ motion and lighting adjustments via RPC or manual keyboard input
Video stream server based on FastAPI for remote camera feed access
Blender-based rendering pipeline for synthetic view generation
Offline dataset preview and annotation visualization tools
Built-in profiling and performance statistics export
Command-line interface for launching individual components
Installation¶
Clone the repository:
git clone <repo-url> cd <repo-directory>
(Optional) Create and activate a Python virtual environment:
python3 -m venv venv source venv/bin/activate
Install dependencies:
pip install -r requirements.txt
(Optional) Install the package in editable mode:
pip install -e .
Quick Start¶
Use the s6 CLI to launch modules:
s6 <module> [options]
Alternatively, invoke via Python:
python -m s6.app.main <module> [options]
To extend the CLI with new commands or nested subcommands, simply add new Python modules or subdirectories under src/s6/app. Each module should define a main() function as the entrypoint. For example, placing src/s6/app/tools/foo.py with a main() allows invoking:
s6 tools foo [options]
Remote Operations¶
The s6 package supports remote servo control and snapshot capture via RPC and HTTP streaming.
Loading Connection Configuration¶
from s6.schema.connection import ConnectionConfig
# Load the remote stream server address from a JSON config file
config = ConnectionConfig.parse_file("configs/common.config.json")
Unit Testing¶
This section outlines best practices for designing and writing unit tests in the s6 project, as well as instructions for running the test suite.
Test Design Guidelines¶
File and Naming Conventions
Name test files with
test_*.py.Place test files alongside the code they test, mirroring the source directory structure.
Define test classes inheriting from
unittest.TestCaseor use pytest-style functions when pytest is available.Prefix test methods or functions with
test_to ensure automatic discovery.
Test Structure and Scope
Write small, focused tests that verify a single behavior or function.
Use
setUp/tearDown(unittest) or pytest fixtures for setup and cleanup.Mock external dependencies (I/O, network, hardware) with
unittest.mockor pytest’smonkeypatch.Keep tests independent and deterministic; avoid reliance on shared state or random data without fixed seeds.
Assertions and Feedback
Use clear assertion methods (
assertEqual,assertTrue,assertRaises, etc.) or pytest assertions.Include informative messages for expected vs. actual results when necessary.
Performance and Scope
Aim for fast execution; avoid long-running or resource-intensive operations in unit tests.
Separate integration or end-to-end tests (if any) from unit tests.
Test Coverage
Strive for high coverage on core modules (e.g., vision, datastore, profiler, networking).
Use coverage tools (e.g., pytest-cov) to identify untested code paths.
Running Tests¶
Install dependencies:
pip install -r requirements.txt pip install -e .[dev] # includes pytest and other dev tools
Run the full test suite via the s6 CLI (uses unittest):
s6 test
Alternatively, run tests directly with unittest:
python -m unittest discover -s src/s6 -p "test_*.py"
If pytest is installed, you can use it for more features:
pytest pytest --maxfail=1 --disable-warnings -q
To generate a coverage report (requires pytest-cov):
pytest --cov=src/s6 --cov-report=term-missing
Profiler¶
The Profiler class (in s6.utils) provides fine-grained performance tracing within pipelines and applications.
Profiler.frame(): Context manager for timing overall frame or iteration processing.Profiler.trace(scope_name: str, remark: str = None): Context manager for named code regions.scope_namemust follow snake_case naming convention (lowercase letters, numbers, and underscores).
trace.attach(**kwargs): Attach custom metadata (e.g., coordinates, counters) to the current trace.
Example:
from s6.utils import Profiler
with Profiler.frame():
with Profiler.trace("array_copy", remark="convert rgb to grayscale") as trace:
# perform array operations
trace.attach(size=len(data))
The profiler writes detailed timing data and metadata to frames.log.jsonl alongside datasets or logs.