Compare commits

...

3 Commits

12 changed files with 4444 additions and 2208 deletions

21
.envrc
View File

@@ -2,11 +2,18 @@
export DIRENV_WARN_TIMEOUT=20s export DIRENV_WARN_TIMEOUT=20s
eval "$(devenv direnvrc)" # 尝试加载 devenv direnv 配置
if command -v devenv >/dev/null 2>&1; then
# 如果存在 devenv
eval "$(devenv direnvrc)"
# `use devenv` supports the same options as the `devenv shell` command. # `use devenv` 支持和 `devenv shell` 相同的选项
# # 示例use devenv --quiet --impure --option services.postgres.enable:bool true
# To silence all output, use `--quiet`. use devenv
# else
# Example usage: use devenv --quiet --impure --option services.postgres.enable:bool true # 如果不存在 devenv则加载自己的 fallback 配置
use devenv -i echo "devenv not found, loading fallback configuration..."
export UV_PROJECT_ENVIRONMENT="/workspace/envs/mini-nav"
export MY_DEV_ENV=1
fi

5
.gitignore vendored
View File

@@ -227,3 +227,8 @@ devenv.local.yaml
# pre-commit # pre-commit
.pre-commit-config.yaml .pre-commit-config.yaml
# syncthing
.stversions/
.stfolder/
.backup/

View File

@@ -0,0 +1,53 @@
upload:
rsync -avLh --progress --stats --itemize-changes \
--exclude='.jj/' \
--exclude='.git/' \
--exclude='.devenv/' \
--exclude='.direnv/' \
--exclude='deps/' \
--exclude='outputs/' \
--exclude='data/versioned_data/' \
. ial-jumper-ial-pangyg:/home/ial-pangyg/docker-workspace/projects/mini-nav/
download:
rsync -avLh --progress --stats --itemize-changes \
ial-jumper-ial-pangyg:/home/ial-pangyg/docker-workspace/projects/mini-nav/outputs .
sync-pkgs:
# micromamba env create -f ./environment.yml
export UV_PROJECT_ENVIRONMENT="/workspace/envs/mini-nav/" && uv sync --inexact
sync-data:
python -m habitat_sim.utils.datasets_download --uids habitat_test_scenes --data-path data/
python -m habitat_sim.utils.datasets_download --uids habitat_example_objects --data-path data/
ssh:
ssh \
-L 127.0.0.1:22001:127.0.0.1:22000 \
-R 127.0.0.1:22001:127.0.0.1:22000 \
-L 127.0.0.1:8385:127.0.0.1:8384 \
-L 127.0.0.1:2718:172.30.0.2:2718 \
ial-gpu_workstation_1
docker:
docker exec -it docker-ial-pangyg bash
marimo:
export UV_PROJECT_ENVIRONMENT="/workspace/envs/mini-nav/" \
&& uv run marimo edit ./mini-nav/habitat/test.py --host 0.0.0.0 --port 2718
add +packages:
uv add {{ packages }} --no-sync
just sync-pkgs
remove +packages:
uv remove {{ packages }} --no-sync
just sync-pkgs
add-dev +packages:
uv add {{ packages }} --group dev --no-sync
just sync-pkgs
remove-dev +packages:
uv remove {{ packages }} --group dev --no-sync
just sync-pkgs

View File

@@ -1 +1 @@
3.13 3.10

5
.stignore Normal file
View File

@@ -0,0 +1,5 @@
.git
.jj
.venv
.pytest_cache
.ruff_cache

104
AGENTS.md
View File

@@ -1,104 +0,0 @@
# Memorix — Automatic Memory Rules
You have access to Memorix memory tools. Follow these rules to maintain persistent context across sessions.
## RULE 1: Session Start — Load Context
At the **beginning of every conversation**, BEFORE responding to the user:
1. Call `memorix_session_start` to get the previous session summary and key memories (this is a direct read, not a search — no fragmentation risk)
2. Then call `memorix_search` with a query related to the user's first message for additional context
3. If search results are found, use `memorix_detail` to fetch the most relevant ones
4. Reference relevant memories naturally — the user should feel you "remember" them
## RULE 2: Store Important Context
**Proactively** call `memorix_store` when any of the following happen:
### What MUST be recorded:
- Architecture/design decisions → type: `decision`
- Bug identified and fixed → type: `problem-solution`
- Unexpected behavior or gotcha → type: `gotcha`
- Config changed (env vars, ports, deps) → type: `what-changed`
- Feature completed or milestone → type: `what-changed`
- Trade-off discussed with conclusion → type: `trade-off`
### What should NOT be recorded:
- Simple file reads, greetings, trivial commands (ls, pwd, git status)
### Use topicKey for evolving topics:
For decisions, architecture docs, or any topic that evolves over time, ALWAYS use `topicKey` parameter.
This ensures the memory is UPDATED instead of creating duplicates.
Use `memorix_suggest_topic_key` to generate a stable key.
Example: `topicKey: "architecture/auth-model"` — subsequent stores with the same key update the existing memory.
### Track progress with the progress parameter:
When working on features or tasks, include the `progress` parameter:
```json
{
"progress": {
"feature": "user authentication",
"status": "in-progress",
"completion": 60
}
}
```
Status values: `in-progress`, `completed`, `blocked`
## RULE 3: Resolve Completed Memories
When a task is completed, a bug is fixed, or information becomes outdated:
1. Call `memorix_resolve` with the observation IDs to mark them as resolved
2. Resolved memories are hidden from default search, preventing context pollution
This is critical — without resolving, old bug reports and completed tasks will keep appearing in future searches.
## RULE 4: Session End — Store Decision Chain Summary
When the conversation is ending, create a **decision chain summary** (not just a checklist):
1. Call `memorix_store` with type `session-request` and `topicKey: "session/latest-summary"`:
**Required structure:**
```
## Goal
[What we were working on — specific, not vague]
## Key Decisions & Reasoning
- Chose X because Y. Rejected Z because [reason].
- [Every architectural/design decision with WHY]
## What Changed
- [File path] — [what changed and why]
## Current State
- [What works now, what's pending]
- [Any blockers or risks]
## Next Steps
- [Concrete next actions, in priority order]
```
**Critical: Include the "Key Decisions & Reasoning" section.** Without it, the next AI session will lack the context to understand WHY things were done a certain way and may suggest conflicting approaches.
2. Call `memorix_resolve` on any memories for tasks completed in this session
## RULE 5: Compact Awareness
Memorix automatically compacts memories on store:
- **With LLM API configured:** Smart dedup — extracts facts, compares with existing, merges or skips duplicates
- **Without LLM (free mode):** Heuristic dedup — uses similarity scores to detect and merge duplicate memories
- **You don't need to manually deduplicate.** Just store naturally and compact handles the rest.
- If you notice excessive duplicate memories, call `memorix_deduplicate` for batch cleanup.
## Guidelines
- **Use concise titles** (~5-10 words) and structured facts
- **Include file paths** in filesModified when relevant
- **Include related concepts** for better searchability
- **Always use topicKey** for recurring topics to prevent duplicates
- **Always resolve** completed tasks and fixed bugs
- **Always include reasoning** — "chose X because Y" is 10x more valuable than "did X"
- Search defaults to `status="active"` — use `status="all"` to include resolved memories

View File

@@ -3,10 +3,11 @@
"devenv": { "devenv": {
"locked": { "locked": {
"dir": "src/modules", "dir": "src/modules",
"lastModified": 1769601151, "lastModified": 1773767086,
"narHash": "sha256-3eKyl4LXswf6P17/u59x8oQXDgCfYX+UX0uh7YHFwJc=",
"owner": "cachix", "owner": "cachix",
"repo": "devenv", "repo": "devenv",
"rev": "b2ef1164b4f330d6b11c6ad3da962452eab7b3bb", "rev": "a5e5a7f8b1c9a7f33f9d82192b692768b39ec710",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -16,27 +17,13 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"owner": "NixOS",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1731533236, "lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
@@ -48,47 +35,6 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1769069492,
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1762808025,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixgl": { "nixgl": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
@@ -98,6 +44,7 @@
}, },
"locked": { "locked": {
"lastModified": 1762090880, "lastModified": 1762090880,
"narHash": "sha256-fbRQzIGPkjZa83MowjbD2ALaJf9y6KMDdJBQMKFeY/8=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixGL", "repo": "nixGL",
"rev": "b6105297e6f0cd041670c3e8628394d4ee247ed5", "rev": "b6105297e6f0cd041670c3e8628394d4ee247ed5",
@@ -110,11 +57,15 @@
} }
}, },
"nixpkgs": { "nixpkgs": {
"inputs": {
"nixpkgs-src": "nixpkgs-src"
},
"locked": { "locked": {
"lastModified": 1767052823, "lastModified": 1773704619,
"narHash": "sha256-LKtmit8Sr81z8+N2vpIaN/fyiQJ8f7XJ6tMSKyDVQ9s=",
"owner": "cachix", "owner": "cachix",
"repo": "devenv-nixpkgs", "repo": "devenv-nixpkgs",
"rev": "538a5124359f0b3d466e1160378c87887e3b51a4", "rev": "906534d75b0e2fe74a719559dfb1ad3563485f43",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -124,20 +75,34 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-src": {
"flake": false,
"locked": {
"lastModified": 1773597492,
"narHash": "sha256-hQ284SkIeNaeyud+LS0WVLX+WL2rxcVZLFEaK0e03zg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a07d4ce6bee67d7c838a8a5796e75dff9caa21ef",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"devenv": "devenv", "devenv": "devenv",
"git-hooks": "git-hooks",
"nixgl": "nixgl", "nixgl": "nixgl",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs"
"pre-commit-hooks": [
"git-hooks"
]
} }
}, },
"systems": { "systems": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems", "owner": "nix-systems",
"repo": "default", "repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
@@ -152,4 +117,4 @@
}, },
"root": "root", "root": "root",
"version": 7 "version": 7
} }

View File

@@ -15,47 +15,18 @@
nvidiaVersion = "580.126.09"; nvidiaVersion = "580.126.09";
}; };
in { in {
# https://devenv.sh/basics/
# env.GREET = "devenv";
# https://devenv.sh/packages/
packages = [ packages = [
pkgs-nixgl.auto.nixGLNvidia
]; ];
# https://devenv.sh/languages/
# languages.rust.enable = true;
# https://devenv.sh/processes/
# processes.dev.exec = "${lib.getExe pkgs.watchexec} -n -- ls -la";
# https://devenv.sh/services/
# services.postgres.enable = true;
# https://devenv.sh/scripts/
# scripts.hello.exec = ''
# echo hello from $GREET
# '';
# https://devenv.sh/basics/
enterShell = '' enterShell = ''
source ./.venv/bin/activate export UV_PROJECT_ENVIRONMENT=$HOME/.local/share/mamba/envs/mini-nav/
eval "$(micromamba shell hook --shell bash)"
micromamba activate mini-nav
which uv
which python
''; '';
# https://devenv.sh/tasks/
# tasks = {
# "myproj:setup".exec = "mytool build";
# "devenv:enterShell".after = [ "myproj:setup" ];
# };
# https://devenv.sh/tests/
# enterTest = ''
# echo "Running tests"
# git --version | grep --color=auto "${pkgs.git.version}"
# '';
# https://devenv.sh/git-hooks/
# git-hooks.hooks.shellcheck.enable = true;
# See full reference at https://devenv.sh/reference/options/ # See full reference at https://devenv.sh/reference/options/
} }

18
environment.yml Normal file
View File

@@ -0,0 +1,18 @@
name: mini-nav
channels:
- pytorch
- nvidia
- aihabitat-nightly
- conda-forge
dependencies:
- python=3.10
- pip
- habitat-sim=0.3.3
- withbullet
- pytorch
- torchvision
- pytorch-cuda=12.1
# Toolsets
- uv
- just
- nodejs

159
mini-nav/habitat/test.py Normal file
View File

@@ -0,0 +1,159 @@
import marimo
__generated_with = "0.21.1"
app = marimo.App()
@app.cell
def _():
import habitat_sim
from habitat_sim import ShortestPath
import numpy as np
import plotly.express as px
from matplotlib import pyplot as plt
return ShortestPath, habitat_sim, np, plt
@app.cell
def _(habitat_sim):
# 配置场景
scene_path = "data/scene_datasets/habitat-test-scenes/skokloster-castle.glb"
sim_cfg = habitat_sim.SimulatorConfiguration()
sim_cfg.scene_id = scene_path
sim_cfg.enable_physics = False
return (sim_cfg,)
@app.cell
def _(habitat_sim, sim_cfg):
# 配置 agent
agent_cfg = habitat_sim.agent.AgentConfiguration()
rgb_sensor_spec = habitat_sim.CameraSensorSpec()
rgb_sensor_spec.uuid = "color_sensor"
rgb_sensor_spec.sensor_type = habitat_sim.SensorType.COLOR
rgb_sensor_spec.resolution = [256, 256]
rgb_sensor_spec.position = [0.0, 1.5, 0.0]
agent_cfg.sensor_specifications = [rgb_sensor_spec]
# 创建 simulator 实例
cfg = habitat_sim.Configuration(sim_cfg, [agent_cfg])
sim = habitat_sim.Simulator(cfg)
return (sim,)
@app.cell
def _(habitat_sim, plt, sim):
# 初始化 agent
agent = sim.initialize_agent(0)
# 设置 agent 初始位置:使用可导航点,而不是写死 [0,0,0]
agent_state = habitat_sim.AgentState()
agent_state.position = sim.pathfinder.get_random_navigable_point()
agent.set_state(agent_state)
state = agent.get_state()
print("位置:", state.position)
print("旋转四元数:", state.rotation)
observations = sim.get_sensor_observations()
rgb_image = observations["color_sensor"]
print("RGB shape:", rgb_image.shape)
print("RGB min/max:", rgb_image[..., :3].min(), rgb_image[..., :3].max())
plt.imshow(rgb_image)
plt.axis("off")
plt.show()
return (agent,)
@app.cell
def _(agent, plt, sim):
action_names = list(agent.agent_config.action_space.keys())
print("可用动作:", action_names)
# 进行一步移动
sim.step("move_forward")
import random
6
for i in range(5):
action = random.choice(action_names)
obs = sim.step(action)
rgb = obs["color_sensor"]
plt.imshow(rgb)
plt.axis("off")
plt.show()
return
@app.cell
def _(sim):
pathfinder = sim.pathfinder
print("NavMesh是否加载:", pathfinder.is_loaded)
print("可导航面积:", pathfinder.navigable_area)
print("场景边界:", pathfinder.get_bounds())
# 获取随机可导航点
rand_point = pathfinder.get_random_navigable_point()
print("随机可导航点:", rand_point)
return (pathfinder,)
@app.cell
def _(ShortestPath, pathfinder):
start = pathfinder.get_random_navigable_point()
end = pathfinder.get_random_navigable_point()
path = ShortestPath()
path.requested_start = start
path.requested_end = end
found = pathfinder.find_path(path)
print("是否找到路径:", found)
print("路径点:", path.points)
print("路径长度:", path.geodesic_distance)
return path, start
@app.cell
def _(path, pathfinder, plt, sim, start):
from habitat.utils.visualizations import maps
top_down_map = maps.get_topdown_map(
pathfinder, height=start[1], meters_per_pixel=0.05
)
# 绘制路径
trajectory = [
maps.to_grid(p[2], p[0], top_down_map.shape, pathfinder=sim.pathfinder)
for p in path.points
]
maps.draw_path(top_down_map, trajectory)
plt.imshow(top_down_map)
plt.axis("off")
plt.show()
return
@app.cell
def _(habitat_sim, np):
# 高级控制:连续动作和滑动碰撞
vel_control = habitat_sim.physics.VelocityControl()
vel_control.controlling_lin_vel = True
vel_control.lin_vel_is_local = True
vel_control.controlling_ang_vel = True
# 设置线速度和角速度
vel_control.linear_velocity = np.array([0, 0, -1.0]) # forward
vel_control.angular_velocity = np.array([0, 0.1, 0]) # rotation
return
if __name__ == "__main__":
app.run()

View File

@@ -3,24 +3,23 @@ name = "mini-nav"
version = "0.1.0" version = "0.1.0"
description = "Add your description here" description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.13" requires-python = ">=3.10"
dependencies = [ dependencies = [
"accelerate>=1.12.0", "altair>=6.0.0",
"dash>=3.4.0", "dash>=3.4.0",
"dash-ag-grid>=33.3.3", "dash-ag-grid>=33.3.3",
"dash-mantine-components>=2.5.1", "dash-mantine-components>=2.5.1",
"datasets>=4.5.0", "datasets>=4.5.0",
"habitat-baselines>=0.3.320250127", "habitat-baselines>=0.3.320250127",
"habitat-lab>=0.3.320250127", "habitat-lab>=0.3.320250127",
"habitat-sim-uv-wheels-experimental>=0.2.2a2",
"httpx[socks]>=0.28.1", "httpx[socks]>=0.28.1",
"lancedb>=0.27.1", "lancedb>=0.27.1",
"marimo>=0.21.1",
"matplotlib>=3.10.8",
"polars[database,numpy,pandas,pydantic]>=1.37.1", "polars[database,numpy,pandas,pydantic]>=1.37.1",
"pyarrow>=23.0.0", "pyarrow>=23.0.0",
"pydantic>=2.12.5", "pydantic>=2.12.5",
"scikit-learn>=1.7.2", "scikit-learn>=1.7.2",
"torch>=2.10.0",
"torchvision>=0.25.0",
"transformers>=5.0.0", "transformers>=5.0.0",
"typer>=0.24.1", "typer>=0.24.1",
] ]
@@ -28,21 +27,13 @@ dependencies = [
[dependency-groups] [dependency-groups]
dev = [ dev = [
"basedpyright>=1.37.4", "basedpyright>=1.37.4",
"pip>=26.0.1",
"pytest>=9.0.2", "pytest>=9.0.2",
"pytest-mpi>=0.6", "pytest-mpi>=0.6",
] "python-lsp-server>=1.14.0",
"ruff>=0.15.7",
[[tool.uv.index]] "ty>=0.0.24",
name = "pytorch-cu130" "websockets>=16.0",
url = "https://download.pytorch.org/whl/cu130"
explicit = true
[tool.uv.sources]
torch = [
{ index = "pytorch-cu130", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
torchvision = [
{ index = "pytorch-cu130", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
] ]
[tool.ty.environment] [tool.ty.environment]

6118
uv.lock generated

File diff suppressed because it is too large Load Diff