Skip to content
PreciSim
dev

Python quick start

Call vmc.dll with ctypes and run a calibration chain in 20 lines.

Minimal example

import ctypes as C
import json
 
vmc = C.CDLL(r"C:\Program Files\PreciSim\vmc.dll")
 
vmc.vmc_open.restype = C.c_void_p
vmc.vmc_open.argtypes = [C.c_char_p]
vmc.vmc_axis_move_abs.argtypes = [C.c_void_p, C.c_char_p, C.c_double, C.c_int]
vmc.vmc_axis_position.argtypes = [C.c_void_p, C.c_char_p, C.POINTER(C.c_double)]
vmc.vmc_calib_run.argtypes = [C.c_void_p, C.c_char_p, C.c_char_p, C.c_char_p, C.c_int]
 
h = vmc.vmc_open(rb"C:\ProgramData\PreciSim\machines\demo-2axis-vision.json")
assert h, "could not open the machine"
 
vmc.vmc_axis_move_abs(h, b"axisX", 120.5, -1)      # -1 = wait for in-position
pos = C.c_double()
vmc.vmc_axis_position(h, b"axisX", C.byref(pos))
print(f"X = {pos.value:.4f} mm")
 
buf = C.create_string_buffer(8192)
rc = vmc.vmc_calib_run(h, b"C1-pixel-size", b"{}", buf, len(buf))
assert rc == 0, f"calibration failed rc={rc}"
 
result = json.loads(buf.value.decode("utf-8"))
print(json.dumps(result["verify"], indent=2))
 
vmc.vmc_close(h)

Output:

{
  "deviationMm": 0.018,
  "toleranceMm": 0.05,
  "pass": true
}

Grab a frame into numpy

import numpy as np
 
vmc.vmc_cam_grab.argtypes = [
    C.c_void_p, C.c_char_p, C.POINTER(C.c_ubyte), C.c_int,
    C.POINTER(C.c_int), C.POINTER(C.c_int), C.POINTER(C.c_int),
]
 
buf = (C.c_ubyte * (4096 * 4096))()
w, hgt, stride = C.c_int(), C.c_int(), C.c_int()
vmc.vmc_cam_grab(h, b"cam0", buf, len(buf), C.byref(w), C.byref(hgt), C.byref(stride))
 
img = np.ctypeslib.as_array(buf)[: stride.value * hgt.value]
img = img.reshape(hgt.value, stride.value)[:, : w.value]   # drop row padding

Regression tests in CI

This is what vmc.dll is really for: every change to a calibration algorithm is checked against a known answer.

import pytest
 
CASES = [
    ("C1-pixel-size",  0.05),
    ("C2-hand-eye",    0.03),
    ("C3-intrinsics",  0.15),
]
 
@pytest.mark.parametrize("proc,tol", CASES)
def test_calibration_within_tolerance(vmc_handle, proc, tol):
    result = run_calib(vmc_handle, proc)
    assert result["verify"]["pass"], result["verify"]
    assert result["verify"]["deviationMm"] <= tol

With fault injection you can also test that failures are noticed:

def test_large_distortion_is_detected(vmc_handle):
    set_fault(vmc_handle, "cam0", {"k1": -0.08})
    result = run_calib(vmc_handle, "C1-pixel-size")
    # the software should fail this, not quietly pass it
    assert not result["verify"]["pass"]

The second test matters more than the first. Most incidents are not "we computed it wrong" but "we computed it wrong and nobody noticed".

Last updated: Sep 21, 2026
Was this page helpful?