{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "bcb89633-08ab-4829-a46b-879556ece670", "metadata": {}, "outputs": [], "source": [ "# File: belt.ipynb\n", "# Code: Claude Code and Codex\n", "# Review: Ryoichi Ando (ryoichi.ando@zozo.com)\n", "# License: Apache v2.0" ] }, { "cell_type": "code", "execution_count": null, "id": "5cfbdde8-82f4-4461-b593-89bc4095f78c", "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "import numpy as np\n", "from frontend import App\n", "\n", "# create an app\n", "app = App.create(\"belt\")\n", "\n", "# create a cylinder mesh for rollers\n", "V, F = app.mesh.cylinder(r=0.5, min_x=-0.5, max_x=0.5, n=21)\n", "app.asset.add.tri(\"cylinder\", V, F)\n", "\n", "# create 3 belt meshes with decreasing sizes\n", "N, Nb, dirs = 3, 3, []\n", "for k in range(Nb):\n", " r, hw = 1.25 + 2e-3 * k, 0.4 - 0.05 * k\n", " n = int(44 * hw)\n", " V, F = app.mesh.cylinder(r=r, min_x=-hw, max_x=hw, n=n)\n", " app.asset.add.tri(f\"belt-{k}\", V, F)\n", "\n", "# arrange rollers in triangular configuration\n", "for i in range(N):\n", " r, t = 0.65, 2 * i * np.pi / N\n", " x, y = r * np.sin(t), r * np.cos(t)\n", " dirs.append([x, y])\n", "\n", "# create a scene\n", "scene = app.scene.create()\n", "\n", "# add rollers with spinning and moving animations\n", "for x, y in dirs:\n", " s, w, axis = 0.511, 60, [0, 0, 1]\n", " target = [s * x, s * y, 0]\n", " jitter = 1e-2 * random.random()\n", " # add roller rotated to be horizontal\n", " obj = scene.add(\"cylinder\").rotate(90, \"y\").at(x, y, jitter)\n", " obj.param.set(\"friction\", 0.5)\n", " pin = obj.pin()\n", " # spin the roller and move it to target position\n", " pin.spin(t_start=1.5, t_end=3, angular_velocity=w, axis=axis).move_by(\n", " target, t_start=0.0, t_end=1.0\n", " )\n", "\n", "# add belts with strain limiting\n", "for k in range(Nb):\n", " obj = scene.add(f\"belt-{k}\").rotate(90, \"y\")\n", " obj.param.set(\"strain-limit\", 0.05)\n", "\n", "# set preview options\n", "opts = {\"eye\": [0, 1.4, 2.5], \"pin\": False, \"wireframe\": True}\n", "\n", "# compile the scene and report stats\n", "scene = scene.build().report()\n", "\n", "# preview the initial scene\n", "scene.preview(options=opts)" ] }, { "cell_type": "code", "execution_count": null, "id": "86f7d8de-f0c9-4ec1-9bc6-859258ce7b4e", "metadata": {}, "outputs": [], "source": [ "# create a new session with the compiled scene\n", "session = app.session.create(scene)\n", "\n", "# set session parameters\n", "(\n", " session.param.set(\"dt\", 0.01)\n", " .set(\"frames\", 200)\n", " .set(\"gravity\", [0, 0, 0])\n", " .set(\"min-newton-steps\", 32)\n", " .set(\"friction-mode\", \"max\")\n", ")\n", "\n", "# build this session\n", "session = session.build()" ] }, { "cell_type": "code", "execution_count": null, "id": "116cb0ef-f80b-421d-8849-1c85c4171f39", "metadata": {}, "outputs": [], "source": [ "# start the simulation and live-preview the results\n", "session.start().preview(options=opts)\n", "\n", "# also show simulation logs in realtime\n", "session.stream()" ] }, { "cell_type": "code", "execution_count": null, "id": "fa18b5d4-5743-46e8-b55c-3c91e1362eb6", "metadata": {}, "outputs": [], "source": [ "# create an animation from the simulation results\n", "session.animate(options=opts)" ] }, { "cell_type": "code", "execution_count": null, "id": "0a584b31-aff1-4c94-9bef-498266f3426b", "metadata": {}, "outputs": [], "source": [ "# export the animation to file\n", "session.export.animation()" ] }, { "cell_type": "code", "execution_count": null, "id": "beb24642-a84a-416d-ad2e-2b4cfecc009f", "metadata": {}, "outputs": [], "source": [ "# this is for CI\n", "if app.ci:\n", " assert session.finished()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }