TarzanScan#

class QPolargraph.patterns.TarzanScan.TarzanScan(*args, x0=0.0, **kwargs)[source]#

Bases: QScanPattern

Geometry-native scan pattern using alternating single-motor arcs.

Overrides vertices() and trajectory() to produce a sequence of circular arcs, each driven by a single motor. Scan data are collected on all four arc segments of every cycle.

Parameters:

x0 (float, optional) – Starting x-coordinate on the top edge of the scan area [m]. Default: 0.0. Adjust until the trajectory covers the scan area satisfactorily.

Notes

All parameters inherited from QScanPattern (width, height, dx, dy, step) are also accepted.

property x0: float#

Starting x-coordinate on the top edge of the scan area [m].

property tarzan_B: float#

Key parameter of the Tarzan map [m²].

Defined as B = 4h·x_right + y_top² y_bottom² where h = ell/2. The Tarzan map T(x₀) has a closed form involving only B and its partner E = −B + 8h·dx.

When B = 0 the map is the identity and every orbit is period-1 regardless of x0; adjust dy or height until B 0.

property is_degenerate: bool#

True when the scan geometry produces a periodic Tarzan map.

Degeneracy (B 0) means every orbit is period-1: the scan repeats the same path on every cycle regardless of x0. Increase or decrease dy (or change height) to break the degeneracy.

property fixed_point: float | None#

Unique fixed point of the Tarzan map [m], or None.

Returns x0* = h + dx B / (4·dx) when B 0 and dx 0. Passing x0 = fixed_point produces a period-1 orbit (identical repeated scans); avoid it.

Returns None in two cases:

  • dx = 0 and B 0: no fixed points exist — any x0 yields an aperiodic scan.

  • B = 0: all x0 are fixed points (degenerate geometry).

vertices()[source]#

Return arc-corner waypoints for all Tarzan scan cycles.

Iterates cycles starting from (x0, y_top) until the next starting x-position leaves [x_left, x_right].

Return type:

ndarray

Returns:

numpy.ndarray(nvertices, 2) array of (x, y) waypoints [m].

trajectory()[source]#

Return the Tarzan scan path sampled along each arc.

Each segment between consecutive vertices is a true circular arc; this method samples each arc at _TRAJECTORY_PTS points for accurate display.

Return type:

ndarray

Returns:

numpy.ndarray(2, npts) array of (x, y) coordinates [m].

Mathematical background#

A Tarzan scan cycle consists of four circular arcs, each driven by a single motor. Starting from a point \(p_0 = (x_0, y_\text{top})\) on the top edge, the cycle visits the right, bottom, left, and top edges in turn before returning to \(p_4 = (x_1, y_\text{top})\).

The one-cycle advance map \(T : x_0 \mapsto x_1\) has the closed form

\[T(x_0) = -h + \sqrt{\!\left(\sqrt{(x_0 - h)^2 + B\,} - 2h\right)^2 + E\,}\]

where \(h = \ell/2\) is half the motor separation and

\[\begin{split}B &= 4h\,x_\text{right} + y_\text{top}^2 - y_\text{bot}^2, \\ E &= 4h\,x_\text{left} + y_\text{bot}^2 - y_\text{top}^2 = -B + 8h\,d_x.\end{split}\]

Periodicity#

The parameter \(B\) governs whether the scan is periodic:

  • \(B = 0\)\(T\) is the identity map; every orbit is period-1 regardless of \(x_0\). Adjust dy or height until \(B \ne 0\).

  • \(B \ne 0\), \(d_x = 0\) — no fixed points exist; any \(x_0\) yields an aperiodic scan.

  • \(B \ne 0\), \(d_x \ne 0\) — one fixed point \(x_0^* = h + d_x - B\,/\,(4\,d_x)\); avoid setting x0 to this value.

Use tarzan_B, is_degenerate, and fixed_point to inspect these conditions at runtime.