zcartpole
zcartpole simulates a cart with one or more serial pendulum links. Describe the rail, cart, links, drive, initial state, and controller in JSON. The runner saves the validated inputs, trajectory, and a result summary. It can balance near upright or plan and track a swing-up.
The actuator interface accepts a transfer function from drive command to horizontal cart force. It can represent a motor, gearbox, drive, and transmission together. A second transfer function can account for cart speed. Command delay, command bounds, and force bounds are applied in the simulation.
Status: simulation software. Included parameter values are examples. Check the model against measurements for hardware use. The swing-up optimizer uses an ideal force input; the chosen actuator is simulated afterward.
Install
Python 3.9 or newer is required. Download the repository ZIP from GitHub, extract it, and run this in the project folder:
python -m pip install -e .
Swing-up uses CasADi/IPOPT; GIFs use Matplotlib and Pillow. The optional Numba backend speeds up mechanical steps after its first compilation:
python -m pip install -e '.[opt,viz,speed]'
In PowerShell, use py -m pip and quote the extra spec in the same way. After the PyPI release, python -m pip install 'zcartpole[opt,viz,speed]' will also work. Examples and the documentation site are in the repository; a normal wheel installation contains the Python package and command line tools.
Use from Python
The mechanical API returns NumPy arrays. Plot them in the same Python session:
import matplotlib.pyplot as plt
from zcartpole import ZNCartPole, simulate
model = ZNCartPole(m=[0.1], l=[0.4], M=1.0, u_max=80.0)
sol = simulate(model, lambda t, state: model.lqr_control(state),
th0=[0.05], t_max=3.0, dt=0.002)
plt.plot(sol.t, sol.y[0])
plt.xlabel('Time (s)')
plt.ylabel('Cart position (m)')
plt.show()
Install [viz] for this plot. This short example uses an ideal force input. For a configured actuator, use SystemConfig and run_system below, or call simulate_linear_actuator to keep its arrays in memory. The source archive contains examples/python_balance.py.
Configured run
Save this as balance.json:
{
"schema_version": 1,
"rail": {"half_travel_m": 0.5},
"cart": {"mass_kg": 1.0},
"links": [{"length_m": 0.4, "tip_mass_kg": 0.1}],
"motor": {
"type": "transfer_function",
"command_to_force": {"numerator": [20.0], "denominator": [0.05, 1.0]},
"command_unit": "V", "command_min": -4.0,
"command_max": 4.0, "force_limit_n": 80.0,
"command_delay_s": 0.01
},
"initial": {"angles_rad": [0.05]},
"simulation": {"mode": "balance", "dt_s": 0.002, "duration_s": 3.0}
}
from zcartpole import SystemConfig, run_system
config = SystemConfig.from_json('balance.json')
result = run_system(config, 'balance_run')
print(result.status, result.summary['simulation'])
The directory must be new. Read balance_run/summary.json first. status is caught, missed_catch, rail_violation, or planning_failed. Inspect trajectory.csv for the simulated force, command, cart motion, and link motion. caught means the final state meets built-in numerical tolerances; it is not a safety certificate.
The command line wrapper runs the same configuration:
python -m zcartpole balance.json -o balance_cli_run
On Windows, py -m zcartpole balance.json -o balance_cli_run works. zcartpole-run is equivalent. Use it for batch runs or shell automation.
Set simulation.mode to swingup, provide a near-hanging initial state, and install [opt] to plan a swing-up. For a complete three-link input, use examples/actuator_transfer_system.json from the source archive:
python -m zcartpole examples/actuator_transfer_system.json -o triple_run
Set simulation.animation to true and install [viz] to write simulation.gif. Planning uses a local nonlinear solver and can fail; a valid nominal plan can also fail when the drive is simulated.
Documentation
The source archive includes a MkDocs site. From the project folder, install .[docs] and run python -m mkdocs serve. It covers configuration, actuator models, LQR weights, outputs, Python API, mathematics, and release steps. For code examples with n = 1, 2, or 3, run python examples/run_links.py --links 2 --mode balance -o n2_balance from the source folder.
License
Original code and documentation: MIT (see LICENSE). A third-party DaRUS measurement CSV in some source archives has separate CC BY 4.0 terms (see DATA_LICENSE.md); it is excluded from PyPI distributions. No measured drive performance is implied by the sample models.
Release files for zcartpole 0.16.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zcartpole-0.16.0.tar.gz | 140.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zcartpole-0.16.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 191.2 kB
Release files / zcartpole-0.16.0.tar.gz
| Download URL | zcartpole-0.16.0.tar.gz |
|---|---|
| Size | 140.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ba2442cd9b9901f9c5283e849f278eca85ae199283f80ac7bbf2df93d7ac7248
|
|
BLAKE2b-256 checksum How to use checksums |
aa22ec35a614b6ffd2e0f1c2511a04d7b9b28d9fc7c3386d34973d0204d9ba54
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / zcartpole-0.16.0-py3-none-any.whl
| Download URL | zcartpole-0.16.0-py3-none-any.whl |
|---|---|
| Size | 50.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
857502d58817148e004e3ca3e636308e6847ec95f72a4a865d8e7544d8205f47
|
|
BLAKE2b-256 checksum How to use checksums |
42f4cf586b55e6af663365c6bedae6f0fabdd5c221ae6b458a26b36d3a1f46ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency log