Skip to content

Commit 48b0c58

Browse files
authored
Fix a UI bug and beautify cart-pole rendering (#123)
* Fix a UI bug and beautify cart-pole rendering - Fix a UI bug in which onGameEnd() callback was not called if the game ends with maximum steps reached. - Make the rendering of the cart-pole prettier by adding - ground and tilted olines - coloring - limits on the left and right ends * Make sure that both left and right limits are rendered * Simplify logic for onGameEnd
1 parent 0e23b75 commit 48b0c58

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

cart-pole/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
display: inline-block;
5656
padding-left: 0px;
5757
padding-right: 10px;
58+
padding-top: 10px;
59+
padding-bottom: 10px;
60+
margin: 5px;
5861
vertical-align: top;
5962
border: 1px #AAA solid;
6063
}

cart-pole/index.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,10 @@ class PolicyNetwork {
134134

135135
await maybeRenderDuringTraining(cartPoleSystem);
136136

137-
if (isDone || j >= maxStepsPerGame) {
138-
if (isDone) {
139-
// When the game ends before max step count is reached, a reward of
140-
// 0 is given.
141-
gameRewards.push(0);
142-
}
143-
onGameEnd(i + 1, numGames);
137+
if (isDone) {
138+
// When the game ends before max step count is reached, a reward of
139+
// 0 is given.
140+
gameRewards.push(0);
144141
break;
145142
} else {
146143
// As long as the game doesn't end, each step leads to a reward of 1.
@@ -149,6 +146,7 @@ class PolicyNetwork {
149146
gameRewards.push(1);
150147
}
151148
}
149+
onGameEnd(i + 1, numGames);
152150
gameSteps.push(gameRewards.length);
153151
this.pushGradients(allGradients, gameGradients);
154152
allRewards.push(gameRewards);

cart-pole/ui.js

+50-2
Original file line numberDiff line numberDiff line change
@@ -145,27 +145,75 @@ function renderCartPole(cartPole, canvas) {
145145
context.clearRect(0, 0, canvas.width, canvas.height);
146146
const halfW = canvas.width / 2;
147147

148-
// 1. Draw the cart.
148+
// Draw the cart.
149149
const railY = canvas.height * 0.8;
150150
const cartW = cartPole.cartWidth * scale;
151151
const cartH = cartPole.cartHeight * scale;
152152

153153
const cartX = cartPole.x * scale + halfW;
154154

155155
context.beginPath();
156+
context.strokeStyle = '#000000';
157+
context.lineWidth = 2;
156158
context.rect(cartX - cartW / 2, railY - cartH / 2, cartW, cartH);
157159
context.stroke();
158160

159-
// 2. Draw the pole.
161+
// Draw the wheels under the cart.
162+
const wheelRadius = cartH / 4;
163+
for (const offsetX of [-1, 1]) {
164+
context.beginPath();
165+
context.lineWidth = 2;
166+
context.arc(cartX - cartW / 4 * offsetX, railY + cartH / 2 + wheelRadius,
167+
wheelRadius, 0, 2 * Math.PI);
168+
context.stroke();
169+
}
170+
171+
// Draw the pole.
160172
const angle = cartPole.theta + Math.PI / 2;
161173
const poleTopX =
162174
halfW + scale * (cartPole.x + Math.cos(angle) * cartPole.length);
163175
const poleTopY = railY -
164176
scale * (cartPole.cartHeight / 2 + Math.sin(angle) * cartPole.length);
165177
context.beginPath();
178+
context.strokeStyle = '#ffa500';
179+
context.lineWidth = 6;
166180
context.moveTo(cartX, railY - cartH / 2);
167181
context.lineTo(poleTopX, poleTopY);
168182
context.stroke();
183+
184+
// Draw the ground.
185+
const groundY = railY + cartH / 2 + wheelRadius * 2;
186+
context.beginPath();
187+
context.strokeStyle = '#000000';
188+
context.lineWidth = 1;
189+
context.moveTo(0, groundY);
190+
context.lineTo(canvas.width, groundY);
191+
context.stroke();
192+
193+
const nDivisions = 40;
194+
for (let i = 0; i < nDivisions; ++i) {
195+
const x0 = canvas.width / nDivisions * i;
196+
const x1 = x0 + canvas.width / nDivisions / 2;
197+
const y0 = groundY + canvas.width / nDivisions / 2;
198+
const y1 = groundY;
199+
context.beginPath();
200+
context.moveTo(x0, y0);
201+
context.lineTo(x1, y1);
202+
context.stroke();
203+
}
204+
205+
// Draw the left and right limits.
206+
const limitTopY = groundY - canvas.height / 2;
207+
context.beginPath();
208+
context.strokeStyle = '#ff0000';
209+
context.lineWidth = 2;
210+
context.moveTo(1, groundY);
211+
context.lineTo(1, limitTopY);
212+
context.stroke();
213+
context.beginPath();
214+
context.moveTo(canvas.width - 1, groundY);
215+
context.lineTo(canvas.width - 1, limitTopY);
216+
context.stroke();
169217
}
170218

171219
async function updateUIControlState() {

0 commit comments

Comments
 (0)