This repository hosts the weights and code for a neural network that plans paths in a 3D voxel grid (32×32×32). The model encodes the voxelized environment (obstacles + start + goal) with a 3D CNN, fuses learned position embeddings, and autoregressively generates a sequence of movement actions with a Transformer decoder.
1import torch, numpy as np
2from huggingface_hub import hf_hub_download
3import importlib.util, sys
4
5REPO_ID = "c1tr0n75/VoxelPathFinder"
6# Download files from the Hub
7pth_path = hf_hub_download(repo_id=REPO_ID, filename="final_model.pth")
8py_path = hf_hub_download(repo_id=REPO_ID, filename="pathfinding_nn.py")
9
10# Dynamically import the model code
11spec = importlib.util.spec_from_file_location("pathfinding_nn", py_path)
12mod = importlib.util.module_from_spec(spec)
13spec.loader.exec_module(mod)
14PathfindingNetwork = mod.PathfindingNetwork
15create_voxel_input = mod.create_voxel_input
16
17device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
18model = PathfindingNetwork().to(device).eval()
19
20# Load weights (supports either a plain state_dict or {'model_state_dict': ...})
21ckpt = torch.load(pth_path, map_location=device)
22state = ckpt["model_state_dict"] if isinstance(ckpt, dict) and "model_state_dict" in ckpt else ckpt
23model.load_state_dict(state)
24
25# Build a random test environment
26voxel_dim = model.voxel_dim # (32, 32, 32)
27D, H, W = voxel_dim
28obstacle_prob = 0.2
29obstacles = (np.random.rand(D, H, W) < obstacle_prob).astype(np.float32)
30free = np.argwhere(obstacles == 0)
31assert len(free) >= 2, "Not enough free cells; lower obstacle_prob"
32s_idx, g_idx = np.random.choice(len(free), size=2, replace=False)
33start = tuple(free[s_idx])
34goal = tuple(free[g_idx])
35
36voxel_np = create_voxel_input(obstacles, start, goal, voxel_dim=voxel_dim) # (3,32,32,32)
37voxel = torch.from_numpy(voxel_np).float().unsqueeze(0).to(device) # (1,3,32,32,32)
38pos = torch.tensor([[start, goal]], dtype=torch.long, device=device) # (1,2,3)
39
40with torch.no_grad():
41 actions = model(voxel, pos)[0].tolist()
42
43ACTION_NAMES = ['FORWARD', 'BACK', 'LEFT', 'RIGHT', 'UP', 'DOWN']
44decoded = [ACTION_NAMES[a] for a in actions if 0 <= a < 6]
45print(f"Start: {start} | Goal: {goal}")
46print(f"Generated {len(decoded)} steps (first 30): {decoded[:30]}")