Skip to content

Commit aff54a8

Browse files
committed
Add dark/light mode to cartpole SVG and animation, use Julia colors
1 parent af03adf commit aff54a8

2 files changed

Lines changed: 237 additions & 45 deletions

File tree

Lines changed: 202 additions & 35 deletions
Loading

docs/src/tutorial-symbolics.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ This tutorial demonstrates how to combine **symbolic derivation of equations of
1111

1212
The key is to define the kinetic and potential energies and the power of the non-conservative forces, and to let `Symbolics.jl` handle the derivations of the equations of motion using the Lagrange-Euler equation.
1313

14-
1514
## The Cart-Pole System
1615

1716
The system consists of a cart of mass ``m_c`` sliding on a frictionless horizontal rail, with
@@ -99,6 +98,7 @@ motion become the first-order system:
9998
\dot{x} \\ \dot{\theta} \\ M^{-1}(q)\bigl(-C(q,\dot{q}) + \tau(q,u)\bigr)
10099
\end{pmatrix}.
101100
```
101+
102102
# Optimal Control of a Cart-Pole System using Symbolics.jl
103103

104104
This tutorial demonstrates how to use `Symbolics.jl` to automate the derivation of equations of motion (EOM) for a mechanical system and subsequently solve an optimal control problem using `OptimalControl.jl`.
@@ -284,7 +284,7 @@ Base.show(io::IO, ::MIME"text/html", h::RawHTML) = print(io, h.raw)
284284
html_anim = """
285285
<div style="display: flex; justify-content: center; margin: 20px 0;">
286286
<canvas id="cartpoleCanvas" width="600" height="300"
287-
style="border:1px solid #ddd; background:#fafafa; border-radius: 8px; max-width: 100%;">
287+
style="border:1px solid #ddd; border-radius: 8px; max-width: 100%;">
288288
</canvas>
289289
</div>
290290
@@ -298,6 +298,30 @@ html_anim = """
298298
const canvas = document.getElementById('cartpoleCanvas');
299299
const ctx = canvas.getContext('2d');
300300
301+
// Detect dark/light mode
302+
const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
303+
304+
// Color palettes
305+
const colors = isDark ? {
306+
canvas_bg: '#1e1e2e',
307+
track: '#4a4a4a',
308+
cart: '#4063D8',
309+
pole: '#CB3C33',
310+
hinge: '#ecf0f1',
311+
bob: '#CB3C33',
312+
progress_bg: '#3a3a3a',
313+
progress: '#4063D8'
314+
} : {
315+
canvas_bg: '#fafafa',
316+
track: '#999',
317+
cart: '#4063D8',
318+
pole: '#555',
319+
hinge: '#2c3e50',
320+
bob: '#CB3C33',
321+
progress_bg: '#ecf0f1',
322+
progress: '#4063D8'
323+
};
324+
301325
const scale = 50;
302326
const l_px = $(l_val) * scale;
303327
const duration = t[t.length - 1];
@@ -321,7 +345,8 @@ html_anim = """
321345
let cur_x = x[i] + alpha * (x[i+1] - x[i]);
322346
let cur_th = th[i] + alpha * (th[i+1] - th[i]);
323347
324-
ctx.clearRect(0, 0, canvas.width, canvas.height);
348+
ctx.fillStyle = colors.canvas_bg;
349+
ctx.fillRect(0, 0, canvas.width, canvas.height);
325350
326351
const cx = canvas.width / 2 + cur_x * scale;
327352
const cy = canvas.height / 2 + 40;
@@ -331,11 +356,11 @@ html_anim = """
331356
ctx.moveTo(0, cy + 15);
332357
ctx.lineTo(canvas.width, cy + 15);
333358
ctx.lineWidth = 2;
334-
ctx.strokeStyle = '#ccc';
359+
ctx.strokeStyle = colors.track;
335360
ctx.stroke();
336361
337362
// Draw Cart
338-
ctx.fillStyle = '#3498db';
363+
ctx.fillStyle = colors.cart;
339364
ctx.fillRect(cx - 30, cy - 15, 60, 30);
340365
341366
// Draw Pole
@@ -347,26 +372,26 @@ html_anim = """
347372
ctx.lineTo(px, py);
348373
ctx.lineWidth = 6;
349374
ctx.lineCap = 'round';
350-
ctx.strokeStyle = '#e74c3c';
375+
ctx.strokeStyle = colors.pole;
351376
ctx.stroke();
352377
353378
// Draw Hinge
354379
ctx.beginPath();
355380
ctx.arc(cx, cy, 6, 0, 2 * Math.PI);
356-
ctx.fillStyle = '#2c3e50';
381+
ctx.fillStyle = colors.hinge;
357382
ctx.fill();
358383
359384
// Draw Bob
360385
ctx.beginPath();
361386
ctx.arc(px, py, 8, 0, 2 * Math.PI);
362-
ctx.fillStyle = '#e74c3c';
387+
ctx.fillStyle = colors.bob;
363388
ctx.fill();
364389
365390
// Draw Progress Bar at the very bottom
366391
const bar_height = 4;
367-
ctx.fillStyle = '#ecf0f1'; // Background
392+
ctx.fillStyle = colors.progress_bg;
368393
ctx.fillRect(0, canvas.height - bar_height, canvas.width, bar_height);
369-
ctx.fillStyle = '#3498db'; // Active progress
394+
ctx.fillStyle = colors.progress; // Active progress
370395
ctx.fillRect(0, canvas.height - bar_height, canvas.width * (sim_t / duration), bar_height);
371396
372397
requestAnimationFrame(draw);

0 commit comments

Comments
 (0)