Solve leak problem + Refactoring

This commit is contained in:
Thibault Neveu committed 2018-06-14 16:22:57 +01:00
1 parent d69cf05c5a
commit e14f030442
13 files changed
+128 -120

No files matched your search

+3 -3
View File
@@ -131,7 +131,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function () {\n return this.motion.state.map(function (arr) { return arr.slice(); });\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);\n }\n }\n this.lidar.pts = lidarOptions.pts;\n this.lidar.addChild(area);\n this.lidar.x = this.core.x;\n this.lidar.y = this.core.y;\n this.lidar.pivot.y = this.lidar.height / 2;\n this.lidar.pivoLine truncated
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function (linear) {\n if (linear === void 0) { linear = false; }\n if (!linear)\n return this.motion.state.map(function (arr) { return arr.slice(); });\n else {\n var state_1 = [];\n this.motion.state.map(function (row) { state_1 = state_1.concat(row); });\n return state_1;\n }\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);Line truncated
/***/ }),
@@ -239,7 +239,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _ui_event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui_event */ \"./src/ui_event.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelToLoad) {\n this.eventList = [\"train\", \"play\", \"stop\", \"reset_env\", \"reset_agent\", \"load\"];\n if (!canvasId || this.levelToLoad) {\n console.error(\"You must specify the canvasId and the levelToLoad\");\n }\n this.canvasId = canvasId;\n this.levelToLoad = levelToLoad;\n }\n MetaCar.prototype._setEvents = function () {\n var _this = this;\n this.event = new _ui_event__WEBPACK_IMPORTED_MODULE_1__[\"UIEvent\"](this.level, this.canvasId);\n this.eventCallback = [\n function (fc) { return _this.event.onTrain(fc); },\n function (fc) { return _this.event.onPlay(fc); },\n function (fc) { return _this.event.onStop(fc); },\n function (fc) { return _this.event.onResetEnv(fc); },\n function (fc) { return _this.event.onResetAgent(fc); },\n function (fc, opt) { return _this.event.onLoad(fc, opt); }\n ];\n };\n MetaCar.prototype.load = function (level, agent) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n console.log(typeof _this.levelToLoad, _this.levelToLoad);\n if (typeof _this.levelToLoad == \"string\") {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"loadCustomURL\"](_this.levelToLoad, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n });\n }\n else {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](_this.levelToLoad, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n }\n });\n };\n MetaCar.prototype.addEvent = function (eventName, fc, options) {\n var index = this.eventList.indexOf(eventName);\n if (index == -1) {\n this.event.onCustomEvent(eventName, fc);\n return;\n }\n var event = this.eventList[index];\n if (event != \"load\") {\n this.eventCallback[index](fc);\n }\n else {\n this.eventCallback[index](fc, options);\n }\n };\n MetaCar.prototype.render = function (val) {\n this.level.render(val);\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function () {\n return this.level.agent.getState();\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype.loop = function (delta) {\n if (this.event.isPlaying()) {\n this.event.playCallback();\n }\n else {\n this.level.step(delta);\n }\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _ui_event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui_event */ \"./src/ui_event.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelToLoad) {\n this.eventList = [\"train\", \"play\", \"stop\", \"reset_env\", \"load\"];\n if (!canvasId || !levelToLoad) {\n console.error(\"You must specify the canvasId and the levelToLoad\");\n }\n this.canvasId = canvasId;\n this.levelToLoad = levelToLoad;\n }\n MetaCar.prototype.load = function () {\n var _this = this;\n return new Promise(function (resolve, reject) {\n console.log(typeof _this.levelToLoad, _this.levelToLoad);\n if (typeof _this.levelToLoad == \"string\") {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"loadCustomURL\"](_this.levelToLoad, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this._loop(delta); });\n resolve();\n });\n }\n else {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](_this.levelToLoad, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this._loop(delta); });\n resolve();\n }\n });\n };\n MetaCar.prototype.addEvent = function (eventName, fc, options) {\n var index = this.eventList.indexOf(eventName);\n if (index == -1) {\n this.event.onCustomEvent(eventName, fc);\n return;\n }\n var event = this.eventList[index];\n if (event != \"load\") {\n this.eventCallback[index](fc);\n }\n else {\n this.eventCallback[index](fc, options);\n }\n };\n MetaCar.prototype.render = function (val) {\n this.level.render(val);\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function (linear) {\n if (linear === void 0) { linear = false; }\n return this.level.agent.getState(linear);\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype._loop = function (delta) {\n if (this.event.isPlaying()) {\n this.event.playCallback();\n }\n else {\n this.level.step(delta);\n }\n };\n MetaCar.prototype._setEvents = function () {\n var _this = this;\n this.event = new _ui_event__WEBPACK_IMPORTED_MODULE_1__[\"UIEvent\"](this.level, this.canvasId);\n this.eventCallback = [\n function (fc) { return _this.event.onTrain(fc); },\n function (fc) { return _this.event.onPlay(fc); },\n function (fc) { return _this.event.onStop(fc); },\n function (fc) { return _this.event.onResetEnv(fc); },\n function (fc, opt) { return _this.event.onLoad(fc, opt); }\n ];\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?");
/***/ }),
@@ -275,7 +275,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UIEvent\", function() { return UIEvent; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\n\nvar UIEvent = (function () {\n function UIEvent(level, canvasId) {\n this.selectedItems = false;\n this.level = level;\n this.canvasId = canvasId;\n var canvas = document.getElementById(canvasId);\n var buttons = document.createElement('div');\n buttons.classList.add(\"metacar_buttons_container\");\n buttons.id = \"metacar_\" + canvasId + \"_buttons_container\";\n canvas.parentNode.insertBefore(buttons, canvas.nextSibling);\n this.buttonsContainer = buttons;\n }\n UIEvent.prototype.isPlaying = function () {\n return this.playing;\n };\n UIEvent.prototype.getEditorSize = function () {\n return { width: this.editorWidth, height: this.editorHeight };\n };\n UIEvent.prototype._createButton = function (parent, name) {\n var button = document.createElement('button');\n button.classList.add(\"metacar_button_train\");\n button.id = \"metacar_\" + this.canvasId + \"_button_\" + name;\n name = name.replace(/_/g, \" \");\n button.innerHTML = name.charAt(0).toUpperCase() + name.slice(1);\n ;\n parent.appendChild(button);\n return button;\n };\n UIEvent.prototype.onTrain = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"train\");\n button.addEventListener(\"click\", function () {\n _this.level.render(false);\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onPlay = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"play\");\n button.addEventListener(\"click\", function () {\n if (fc) {\n _this.playing = true;\n _this.playCallback = fc;\n }\n });\n };\n UIEvent.prototype.onStop = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"stop\");\n button.addEventListener(\"click\", function () {\n _this.playing = false;\n _this.playCallback = undefined;\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetEnv = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"reset_env\");\n button.addEventListener(\"click\", function () {\n _this.level.reset();\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetAgent = function (fc) {\n var button = this._createButton(this.buttonsContainer, \"reset_agent\");\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onCustomEvent = function (name, fc) {\n var button = this._createButton(this.buttonsContainer, name);\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onSaveEditor = function (fc, options) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"save\");\n button.addEventListener(\"click\", function () {\n var size = _this.getEditorSize();\n var content = _this.level.exportMap(size.width, size.height, options.name, options.download);\n if (fc)\n fc(content);\n });\n };\n UIEvent.prototype.onLoad = function (fc, options) {\n if (options === void 0) { options = Object(); }\n options.local = options.local || false;\n var button = this._createButton(this.buttonsContainer, \"load_trained_agent\");\n var input_file = document.createElement('input');\n input_file.type = \"file\";\n input_file.accept = \"*/*\";\n input_file.style.display = \"none\";\n input_file.classList.add(\"metacar_button_input_file\");\n input_file.id = \"metacar_\" + this.canvasId + \"_button_input_file\";\n this.buttonsContainer.appendChild(input_file);\n input_file.addEventListener(\"change\", function (dump) {\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"readDump\"](dump, function (content) {\n if (fc)\n fc(content);\n });\n });\n button.addEventListener(\"click\", function () {\n if (options.local) {\n input_file.click();\n }\n else {\n if (fc)\n Line truncated
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UIEvent\", function() { return UIEvent; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\n\nvar UIEvent = (function () {\n function UIEvent(level, canvasId) {\n this.selectedItems = false;\n this.level = level;\n this.canvasId = canvasId;\n var canvas = document.getElementById(canvasId);\n var buttons = document.createElement('div');\n buttons.classList.add(\"metacar_buttons_container\");\n buttons.id = \"metacar_\" + canvasId + \"_buttons_container\";\n canvas.parentNode.insertBefore(buttons, canvas.nextSibling);\n this.buttonsContainer = buttons;\n }\n UIEvent.prototype.isPlaying = function () {\n return this.playing;\n };\n UIEvent.prototype.getEditorSize = function () {\n return { width: this.editorWidth, height: this.editorHeight };\n };\n UIEvent.prototype._createButton = function (parent, name) {\n var button = document.createElement('button');\n button.classList.add(\"metacar_button_train\");\n button.id = \"metacar_\" + this.canvasId + \"_button_\" + name;\n name = name.replace(/_/g, \" \");\n button.innerHTML = name.charAt(0).toUpperCase() + name.slice(1);\n ;\n parent.appendChild(button);\n return button;\n };\n UIEvent.prototype.onTrain = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"train\");\n button.addEventListener(\"click\", function () {\n _this.level.render(false);\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onPlay = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"play\");\n button.addEventListener(\"click\", function () {\n if (fc) {\n _this.playing = true;\n _this.playCallback = fc;\n }\n });\n };\n UIEvent.prototype.onStop = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"stop\");\n button.addEventListener(\"click\", function () {\n _this.playing = false;\n _this.playCallback = undefined;\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetEnv = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"reset_env\");\n button.addEventListener(\"click\", function () {\n _this.level.reset();\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onCustomEvent = function (name, fc) {\n var button = this._createButton(this.buttonsContainer, name);\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onSaveEditor = function (fc, options) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"save\");\n button.addEventListener(\"click\", function () {\n var size = _this.getEditorSize();\n var content = _this.level.exportMap(size.width, size.height, options.name, options.download);\n if (fc)\n fc(content);\n });\n };\n UIEvent.prototype.onLoad = function (fc, options) {\n if (options === void 0) { options = Object(); }\n options.local = options.local || false;\n var button = this._createButton(this.buttonsContainer, \"load_trained_agent\");\n var input_file = document.createElement('input');\n input_file.type = \"file\";\n input_file.accept = \"*/*\";\n input_file.style.display = \"none\";\n input_file.classList.add(\"metacar_button_input_file\");\n input_file.id = \"metacar_\" + this.canvasId + \"_button_input_file\";\n this.buttonsContainer.appendChild(input_file);\n input_file.addEventListener(\"change\", function (dump) {\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"readDump\"](dump, function (content) {\n if (fc)\n fc(content);\n });\n });\n button.addEventListener(\"click\", function () {\n if (options.local) {\n input_file.click();\n }\n else {\n if (fc)\n fc();\n }\n });\n };\n UIEvent.prototype._createRangeBar = function (name) {\n var inputProgress = document.createElement('input');\n inputProgress.type = \"range\";\n inputProgress.min = \"5\";\n Line truncated
/***/ }),
-1
View File
@@ -6,7 +6,6 @@ var env = new metacar.env("canvas", levelUrl);
// Create the Policy agent
var agent = new PolicyAgent(env);
env.load().then(() => {
// The level is loaded. Add listernes
env.addEvent("train", () => agent.train());
+34 -22
View File
@@ -22,7 +22,7 @@ class PolicyAgent {
Build the Value function
@weights (Object) Weights for the layer
*/
const LEARNING_RATE = 0.01;
const LEARNING_RATE = 0.05;
const value_optimizer = tf.train.adam(LEARNING_RATE);
/*
-----------------------
@@ -59,7 +59,7 @@ class PolicyAgent {
Build the policy network
@weights (Object) Weights for the layer
*/
const LEARNING_RATE = 0.01;
const LEARNING_RATE = 0.05;
this.policy_optimizer = tf.train.adam(LEARNING_RATE);
/*
-----------------------
@@ -123,17 +123,21 @@ class PolicyAgent {
trainPolicy(states, actions, advantages, batch_size, mini_batch_size){
/*
Train the policy model
@states (Js array)
@actions (Js array)
@advantages (Js array)
@states Tensor2D
@actions Tensor2D
@advantages Tensor2D
@batch_size (Integer) Size of the batch size
@mini_batch_size (Integer) Size of each mini batch size
*/
for (var b = 0; b < batch_size; b+=mini_batch_size) {
const size = states.shape[0];
const tf_states = tf.tensor3d(states.slice(b, b+mini_batch_size)).reshape([-1, this.ttLidarPts]);
const tf_actions = tf.tensor1d(actions.slice(b, b+mini_batch_size), "int32");
const tf_advantages = tf.tensor1d(advantages.slice(b, b+mini_batch_size));
for (var b = 0; b < batch_size; b+=mini_batch_size) {
let to = (b + mini_batch_size < size) ? mini_batch_size : (size - b);
const tf_states = states.slice(b, to);
const tf_actions = actions.slice(b, to);
const tf_advantages = advantages.slice(b, to);
this.policy_optimizer.minimize(() => {
let softmaxs = this.policyPredict(tf_states);
@@ -152,7 +156,7 @@ class PolicyAgent {
// Maximum number of step per episode
this.nb_step = 800;
this.mini_batch_size = 200;
this.episodeNb = 250;
this.episodeNb = 100;
}
save(env){
@@ -211,28 +215,32 @@ class PolicyAgent {
let reward = 0;
const rewards = [];
const states = [];
const stateValues = [];
const actions = [];
console.log("---");
console.time("Exploring");
for (var step = 0; step < this.nb_step; step++) {
// Get the current state
const array_st = this.env.getState();
const array_st = this.env.getState(true);
// Convert the state into a tensor
const st = tf.tensor(array_st, [this.lidarPts, this.lidarPts]).reshape([1, this.ttLidarPts]);
//const st = tf.tensor(array_st, [this.lidarPts, this.lidarPts]).reshape([1, this.ttLidarPts]);
const st = tf.tensor2d([array_st]);
// Predict the policy
const softmax = this.policyPredict(st);
const softmax = this.policyModel.predict(st);
// Predict the value
const value = this.valueModel.predict(st);
// Get the action. Pseudo Random choice. We prefer action with
// Higher probability
const action = randomChoice(softmax.buffer().values);
// Create the next batch
rewards.push(reward);
states.push(array_st);
stateValues.push(value);
actions.push(action);
// Stop the episode if the car go out of the road or crash an
// other car
if (reward == -10){
console.log("Early stop Episode");
softmax.dispose();
st.dispose();
break;
@@ -258,24 +266,28 @@ class PolicyAgent {
G = rewards[t] + (this.gamma*G);
returns.push(G);
// Predict the value function for this state
const st = tf.tensor2d(states[t], [this.lidarPts, this.lidarPts]).reshape([1, this.ttLidarPts]);
const Vs = this.valueModel.predict(st);
const V = stateValues[t];
// Advantage
advantages.push(G - Vs.buffer().values[0]);
st.dispose();
Vs.dispose();
advantages.push(G - V.buffer().values[0]);
V.dispose();
}
returns = returns.reverse();
advantages = advantages.reverse();
// Train the value model
const tf_batch_states = tf.tensor3d(states).reshape([batch_size, this.ttLidarPts]);
const tf_batch_states = tf.tensor2d(states);
const tf_value_target = tf.tensor1d(returns);
const tf_actions = tf.tensor1d(actions, "int32");
const tf_advantages = tf.tensor1d(advantages);
await this.trainValueFc(tf_batch_states, tf_value_target, mini_batch_size);
// Train the policy model
this.trainPolicy(tf_batch_states, tf_actions, tf_advantages, batch_size, mini_batch_size);
tf_batch_states.dispose();
tf_value_target.dispose();
// Train the policy model
this.trainPolicy(states, actions, advantages, batch_size, mini_batch_size);
tf_actions.dispose();
tf_advantages.dispose();
// Set the agent on a new free road
this.env.randomRoadPosition();
//env.reset();
@@ -1 +0,0 @@
{"modelTopology":{"class_name":"Model","config":{"name":"model1","layers":[{"name":"input1","class_name":"InputLayer","config":{"batch_input_shape":[null,25],"dtype":"float32","sparse":false,"name":"input1"},"inbound_nodes":[]},{"name":"dense_Dense3","class_name":"Dense","config":{"units":9,"activation":"tanh","use_bias":true,"kernel_initializer":{"class_name":"RandomNormal","config":{"mean":0,"stddev":0.05,"seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense3","trainable":true,"batch_input_shape":[null,25],"dtype":"float32"},"inbound_nodes":[[["input1",0,0,{}]]]},{"name":"dense_Dense4","class_name":"Dense","config":{"units":3,"activation":"softmax","use_bias":true,"kernel_initializer":{"class_name":"RandomNormal","config":{"mean":0,"stddev":0.05,"seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense4","trainable":true,"batch_input_shape":[null,9],"dtype":"float32"},"inbound_nodes":[[["dense_Dense3",0,0,{}]]]}],"input_layers":[["input1",0,0]],"output_layers":[["dense_Dense4",0,0]]},"keras_version":"tfjs-layers 0.6.6","backend":"tensor_flow.js"},"weightsManifest":[{"paths":["./policy-model-policy-agent.weights.bin"],"weights":[{"name":"dense_Dense3/kernel","shape":[25,9],"dtype":"float32"},{"name":"dense_Dense3/bias","shape":[9],"dtype":"float32"},{"name":"dense_Dense4/kernel","shape":[9,3],"dtype":"float32"},{"name":"dense_Dense4/bias","shape":[3],"dtype":"float32"}]}]}
@@ -1 +0,0 @@
{"modelTopology":{"class_name":"Sequential","config":[{"class_name":"Dense","config":{"units":9,"activation":"tanh","use_bias":true,"kernel_initializer":{"class_name":"RandomNormal","config":{"mean":0,"stddev":0.05,"seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense1","trainable":true,"batch_input_shape":[null,25],"dtype":"float32"}},{"class_name":"Dense","config":{"units":1,"activation":"linear","use_bias":true,"kernel_initializer":{"class_name":"RandomNormal","config":{"mean":0,"stddev":0.05,"seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense2","trainable":true,"batch_input_shape":[null,9],"dtype":"float32"}}],"keras_version":"tfjs-layers 0.6.6","backend":"tensor_flow.js"},"weightsManifest":[{"paths":["./value-model-policy-agent.weights.bin"],"weights":[{"name":"dense_Dense1/kernel","shape":[25,9],"dtype":"float32"},{"name":"dense_Dense1/bias","shape":[9],"dtype":"float32"},{"name":"dense_Dense2/kernel","shape":[9,1],"dtype":"float32"},{"name":"dense_Dense2/bias","shape":[1],"dtype":"float32"}]}]}
+3 -3
View File
@@ -131,7 +131,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function () {\n return this.motion.state.map(function (arr) { return arr.slice(); });\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);\n }\n }\n this.lidar.pts = lidarOptions.pts;\n this.lidar.addChild(area);\n this.lidar.x = this.core.x;\n this.lidar.y = this.core.y;\n this.lidar.pivot.y = this.lidar.height / 2;\n this.lidar.pivoLine truncated
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function (linear) {\n if (linear === void 0) { linear = false; }\n if (!linear)\n return this.motion.state.map(function (arr) { return arr.slice(); });\n else {\n var state_1 = [];\n this.motion.state.map(function (row) { state_1 = state_1.concat(row); });\n return state_1;\n }\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);Line truncated
/***/ }),
@@ -239,7 +239,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _ui_event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui_event */ \"./src/ui_event.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelToLoad) {\n this.eventList = [\"train\", \"play\", \"stop\", \"reset_env\", \"reset_agent\", \"load\"];\n if (!canvasId || this.levelToLoad) {\n console.error(\"You must specify the canvasId and the levelToLoad\");\n }\n this.canvasId = canvasId;\n this.levelToLoad = levelToLoad;\n }\n MetaCar.prototype._setEvents = function () {\n var _this = this;\n this.event = new _ui_event__WEBPACK_IMPORTED_MODULE_1__[\"UIEvent\"](this.level, this.canvasId);\n this.eventCallback = [\n function (fc) { return _this.event.onTrain(fc); },\n function (fc) { return _this.event.onPlay(fc); },\n function (fc) { return _this.event.onStop(fc); },\n function (fc) { return _this.event.onResetEnv(fc); },\n function (fc) { return _this.event.onResetAgent(fc); },\n function (fc, opt) { return _this.event.onLoad(fc, opt); }\n ];\n };\n MetaCar.prototype.load = function (level, agent) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n console.log(typeof _this.levelToLoad, _this.levelToLoad);\n if (typeof _this.levelToLoad == \"string\") {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"loadCustomURL\"](_this.levelToLoad, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n });\n }\n else {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](_this.levelToLoad, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n }\n });\n };\n MetaCar.prototype.addEvent = function (eventName, fc, options) {\n var index = this.eventList.indexOf(eventName);\n if (index == -1) {\n this.event.onCustomEvent(eventName, fc);\n return;\n }\n var event = this.eventList[index];\n if (event != \"load\") {\n this.eventCallback[index](fc);\n }\n else {\n this.eventCallback[index](fc, options);\n }\n };\n MetaCar.prototype.render = function (val) {\n this.level.render(val);\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function () {\n return this.level.agent.getState();\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype.loop = function (delta) {\n if (this.event.isPlaying()) {\n this.event.playCallback();\n }\n else {\n this.level.step(delta);\n }\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _ui_event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui_event */ \"./src/ui_event.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelToLoad) {\n this.eventList = [\"train\", \"play\", \"stop\", \"reset_env\", \"load\"];\n if (!canvasId || !levelToLoad) {\n console.error(\"You must specify the canvasId and the levelToLoad\");\n }\n this.canvasId = canvasId;\n this.levelToLoad = levelToLoad;\n }\n MetaCar.prototype.load = function () {\n var _this = this;\n return new Promise(function (resolve, reject) {\n console.log(typeof _this.levelToLoad, _this.levelToLoad);\n if (typeof _this.levelToLoad == \"string\") {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"loadCustomURL\"](_this.levelToLoad, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this._loop(delta); });\n resolve();\n });\n }\n else {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](_this.levelToLoad, _this.canvasId);\n _this._setEvents();\n _this.level.load(function (delta) { return _this._loop(delta); });\n resolve();\n }\n });\n };\n MetaCar.prototype.addEvent = function (eventName, fc, options) {\n var index = this.eventList.indexOf(eventName);\n if (index == -1) {\n this.event.onCustomEvent(eventName, fc);\n return;\n }\n var event = this.eventList[index];\n if (event != \"load\") {\n this.eventCallback[index](fc);\n }\n else {\n this.eventCallback[index](fc, options);\n }\n };\n MetaCar.prototype.render = function (val) {\n this.level.render(val);\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function (linear) {\n if (linear === void 0) { linear = false; }\n return this.level.agent.getState(linear);\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype._loop = function (delta) {\n if (this.event.isPlaying()) {\n this.event.playCallback();\n }\n else {\n this.level.step(delta);\n }\n };\n MetaCar.prototype._setEvents = function () {\n var _this = this;\n this.event = new _ui_event__WEBPACK_IMPORTED_MODULE_1__[\"UIEvent\"](this.level, this.canvasId);\n this.eventCallback = [\n function (fc) { return _this.event.onTrain(fc); },\n function (fc) { return _this.event.onPlay(fc); },\n function (fc) { return _this.event.onStop(fc); },\n function (fc) { return _this.event.onResetEnv(fc); },\n function (fc, opt) { return _this.event.onLoad(fc, opt); }\n ];\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?");
/***/ }),
@@ -275,7 +275,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UIEvent\", function() { return UIEvent; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\n\nvar UIEvent = (function () {\n function UIEvent(level, canvasId) {\n this.selectedItems = false;\n this.level = level;\n this.canvasId = canvasId;\n var canvas = document.getElementById(canvasId);\n var buttons = document.createElement('div');\n buttons.classList.add(\"metacar_buttons_container\");\n buttons.id = \"metacar_\" + canvasId + \"_buttons_container\";\n canvas.parentNode.insertBefore(buttons, canvas.nextSibling);\n this.buttonsContainer = buttons;\n }\n UIEvent.prototype.isPlaying = function () {\n return this.playing;\n };\n UIEvent.prototype.getEditorSize = function () {\n return { width: this.editorWidth, height: this.editorHeight };\n };\n UIEvent.prototype._createButton = function (parent, name) {\n var button = document.createElement('button');\n button.classList.add(\"metacar_button_train\");\n button.id = \"metacar_\" + this.canvasId + \"_button_\" + name;\n name = name.replace(/_/g, \" \");\n button.innerHTML = name.charAt(0).toUpperCase() + name.slice(1);\n ;\n parent.appendChild(button);\n return button;\n };\n UIEvent.prototype.onTrain = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"train\");\n button.addEventListener(\"click\", function () {\n _this.level.render(false);\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onPlay = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"play\");\n button.addEventListener(\"click\", function () {\n if (fc) {\n _this.playing = true;\n _this.playCallback = fc;\n }\n });\n };\n UIEvent.prototype.onStop = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"stop\");\n button.addEventListener(\"click\", function () {\n _this.playing = false;\n _this.playCallback = undefined;\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetEnv = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"reset_env\");\n button.addEventListener(\"click\", function () {\n _this.level.reset();\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetAgent = function (fc) {\n var button = this._createButton(this.buttonsContainer, \"reset_agent\");\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onCustomEvent = function (name, fc) {\n var button = this._createButton(this.buttonsContainer, name);\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onSaveEditor = function (fc, options) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"save\");\n button.addEventListener(\"click\", function () {\n var size = _this.getEditorSize();\n var content = _this.level.exportMap(size.width, size.height, options.name, options.download);\n if (fc)\n fc(content);\n });\n };\n UIEvent.prototype.onLoad = function (fc, options) {\n if (options === void 0) { options = Object(); }\n options.local = options.local || false;\n var button = this._createButton(this.buttonsContainer, \"load_trained_agent\");\n var input_file = document.createElement('input');\n input_file.type = \"file\";\n input_file.accept = \"*/*\";\n input_file.style.display = \"none\";\n input_file.classList.add(\"metacar_button_input_file\");\n input_file.id = \"metacar_\" + this.canvasId + \"_button_input_file\";\n this.buttonsContainer.appendChild(input_file);\n input_file.addEventListener(\"change\", function (dump) {\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"readDump\"](dump, function (content) {\n if (fc)\n fc(content);\n });\n });\n button.addEventListener(\"click\", function () {\n if (options.local) {\n input_file.click();\n }\n else {\n if (fc)\n Line truncated
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UIEvent\", function() { return UIEvent; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\n\nvar UIEvent = (function () {\n function UIEvent(level, canvasId) {\n this.selectedItems = false;\n this.level = level;\n this.canvasId = canvasId;\n var canvas = document.getElementById(canvasId);\n var buttons = document.createElement('div');\n buttons.classList.add(\"metacar_buttons_container\");\n buttons.id = \"metacar_\" + canvasId + \"_buttons_container\";\n canvas.parentNode.insertBefore(buttons, canvas.nextSibling);\n this.buttonsContainer = buttons;\n }\n UIEvent.prototype.isPlaying = function () {\n return this.playing;\n };\n UIEvent.prototype.getEditorSize = function () {\n return { width: this.editorWidth, height: this.editorHeight };\n };\n UIEvent.prototype._createButton = function (parent, name) {\n var button = document.createElement('button');\n button.classList.add(\"metacar_button_train\");\n button.id = \"metacar_\" + this.canvasId + \"_button_\" + name;\n name = name.replace(/_/g, \" \");\n button.innerHTML = name.charAt(0).toUpperCase() + name.slice(1);\n ;\n parent.appendChild(button);\n return button;\n };\n UIEvent.prototype.onTrain = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"train\");\n button.addEventListener(\"click\", function () {\n _this.level.render(false);\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onPlay = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"play\");\n button.addEventListener(\"click\", function () {\n if (fc) {\n _this.playing = true;\n _this.playCallback = fc;\n }\n });\n };\n UIEvent.prototype.onStop = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"stop\");\n button.addEventListener(\"click\", function () {\n _this.playing = false;\n _this.playCallback = undefined;\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onResetEnv = function (fc) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"reset_env\");\n button.addEventListener(\"click\", function () {\n _this.level.reset();\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onCustomEvent = function (name, fc) {\n var button = this._createButton(this.buttonsContainer, name);\n button.addEventListener(\"click\", function () {\n if (fc)\n fc();\n });\n };\n UIEvent.prototype.onSaveEditor = function (fc, options) {\n var _this = this;\n var button = this._createButton(this.buttonsContainer, \"save\");\n button.addEventListener(\"click\", function () {\n var size = _this.getEditorSize();\n var content = _this.level.exportMap(size.width, size.height, options.name, options.download);\n if (fc)\n fc(content);\n });\n };\n UIEvent.prototype.onLoad = function (fc, options) {\n if (options === void 0) { options = Object(); }\n options.local = options.local || false;\n var button = this._createButton(this.buttonsContainer, \"load_trained_agent\");\n var input_file = document.createElement('input');\n input_file.type = \"file\";\n input_file.accept = \"*/*\";\n input_file.style.display = \"none\";\n input_file.classList.add(\"metacar_button_input_file\");\n input_file.id = \"metacar_\" + this.canvasId + \"_button_input_file\";\n this.buttonsContainer.appendChild(input_file);\n input_file.addEventListener(\"change\", function (dump) {\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"readDump\"](dump, function (content) {\n if (fc)\n fc(content);\n });\n });\n button.addEventListener(\"click\", function () {\n if (options.local) {\n input_file.click();\n }\n else {\n if (fc)\n fc();\n }\n });\n };\n UIEvent.prototype._createRangeBar = function (name) {\n var inputProgress = document.createElement('input');\n inputProgress.type = \"range\";\n inputProgress.min = \"5\";\n Line truncated
/***/ }),
+10 -3
View File
@@ -11,6 +11,7 @@ import {
CAR_IMG, Sprite, MAP, ROADSIZE, Container, Graphics
} from "./global";
import { RoadSprite } from "./asset_manager";
import { stat } from "fs";
var Global_carId = 0;
@@ -174,16 +175,22 @@ export class Car {
}
}
getState(): number[][]{
getState(linear:boolean = false): number[][]|number[]{
/*
Get the current state of the car
The state is the current value of each point
of the lidar.
*/
return this.motion.state.map(function(arr: any) { return arr.slice(); });
if (!linear)
return this.motion.state.map(function(arr: any) { return arr.slice(); });
else{
let state: number[] = [];
this.motion.state.map((row: number[]) => { state = state.concat(row);});
return state;
}
}
step(delta: number, action:number=null){
step(delta: number, action:number|number[]=null){
/*
Take one step into the environement
@delta (Float) time since the last update
+1 -1
View File
@@ -75,7 +75,7 @@ export class Level extends World {
return reward;
}
step(delta: number, action:number=null){
step(delta: number, action:number|number[]=null){
/*
Process one step into the environement
@delta (Float) time since the last update
+77 -77
View File
@@ -7,6 +7,10 @@ import {actionSpaceDescription} from "./motion_engine";
import {UIEvent} from "./ui_event";
import * as U from "./utils";
/**
* @local Chooce whether to load a file from the computer.
* A popup is open if True.
*/
export interface eventLoadOptions {
local: boolean;
}
@@ -17,44 +21,28 @@ export class MetaCar {
private level: Level;
private canvasId: string;
private levelToLoad: string|Object;
private eventList: string[] = ["train", "play", "stop", "reset_env", "reset_agent", "load"]
private eventList: string[] = ["train", "play", "stop", "reset_env", "load"]
private eventCallback: any[];
private event: UIEvent;
/**
* Class used to create a new environement.
* @canvasId: HTML canvas ID
* @levelToLoad: URL of the level or directly the level's object.
* URL format: embedded://... or http(s)://...
*/
constructor(canvasId: string, levelToLoad: string|Object) {
/**
* @canvasId: HTML canvas ID to used
* @level: URL or Local storage URL.
* localstorage://level-name
* embedded://
* http(s)://
*/
if (!canvasId || this.levelToLoad){
if (!canvasId || !levelToLoad){
console.error("You must specify the canvasId and the levelToLoad");
}
this.canvasId = canvasId;
this.levelToLoad = levelToLoad;
}
private _setEvents(){
// SetEvents callback
this.event = new UIEvent(this.level, this.canvasId);
this.eventCallback = [
(fc: any) => this.event.onTrain(fc),
(fc: any) => this.event.onPlay(fc),
(fc:any) => this.event.onStop(fc),
(fc: any) => this.event.onResetEnv(fc),
(fc: any) => this.event.onResetAgent(fc),
(fc: any, opt: eventLoadOptions) => this.event.onLoad(fc, opt)
];
}
load(level: string, agent: any): Promise<void>{
/*
Load the environement
@level (String) Name of the json level to load
@agent (Agent class)
*/
/*
Load the environement with the parameters passed in the constructor.
*/
public load(): Promise<void>{
return new Promise((resolve, reject) => {
console.log(typeof this.levelToLoad, this.levelToLoad);
@@ -62,56 +50,34 @@ export class MetaCar {
U.loadCustomURL(<string>this.levelToLoad, (content: LevelInfo) => {
this.level = new Level(content, this.canvasId);
this._setEvents();
this.level.load((delta: number) => this.loop(delta));
this.level.load((delta: number) => this._loop(delta));
resolve();
});
}
else{
this.level = new Level(<LevelInfo>this.levelToLoad, this.canvasId);
this._setEvents();
this.level.load((delta: number) => this.loop(delta));
this.level.load((delta: number) => this._loop(delta));
resolve();
}
});
/*
this.agent = agent;
this.level = new Level(level, "canvas");
this.level.load((delta: number) => this.loop(delta));
document.getElementById("train").addEventListener("click", () => {
this.level.app.ticker.stop(); // .add(delta => this.loop(delta));
this.agent.train(this);
});
document.getElementById("stop").addEventListener("click", () => {
this.isPlaying = false;
this.level.render();
this.agent.stop();
});
document.getElementById("reset").addEventListener("click", () => {
this.level.reset();
});
document.getElementById("play").addEventListener("click", () => {
this.isPlaying = true
});
document.getElementById("saveAgent").addEventListener("click", () => {
this.agent.save(this);
});
document.getElementById("dumpFile").addEventListener("change", (e) => {
//readDump(e, (content) => this.agent.restore(this, content));
});
*/
}
/**
* This method is used to add button under the canvas. When a
* This method is used to add a button under the canvas. When a
* click is detected on the window, the associated @fc is called.
* Some events are recognized by the environement, others can be custom.
* The following are recognized:
* - train: The render is stopped before to called @fc. You must called render(true) once your training is done.
* - play: Your function (@fc) will be called at each frame update.
* - stop: The last function passed to the play event will not be called anymore. Then @fc is called.
* - reset_env: Reset the environement. Then, @fc is called.
* - load: Load: @fc is called. You can set @options to {local:true} to load the content of a file from your computer.
* If @options is set, a content variable will be passed to the @fc function (the content of the selected file).
* @eventName Name of the event to listen.
* @fc Function to call each time this event is raised.
*/
addEvent(eventName: string, fc: any, options?: eventLoadOptions):void {
public addEvent(eventName: string, fc: any, options?: eventLoadOptions):void {
const index = this.eventList.indexOf(eventName);
if (index == -1){
this.event.onCustomEvent(eventName, fc);
@@ -126,14 +92,20 @@ export class MetaCar {
}
}
render(val: boolean){
/*
Choose whether to render the environement.
*/
/**
* Choose whether to render the environement.
* @val: True or False.
*/
public render(val: boolean){
this.level.render(val);
}
save(content: any, file_name: string){
/**
* Usefull method to save/download a string as file.
* @content The content of the file
* @file_name The name of the file
*/
public save(content: string, file_name: string){
/*
Save the agent
*/
@@ -142,35 +114,44 @@ export class MetaCar {
/**
* Get the action space of the environement
* @return The Description of the action space.
*/
actionSpace(): actionSpaceDescription{
public actionSpace(): actionSpaceDescription{
return this.level.agent.motion.actionSpace();
}
/**
* Return the current state of the environement.
* The size of the state depends of the size of the Lidar.
* @return The state as a 2D Array or 1D Array (linear:true)
*/
getState(): number[][]{
return this.level.agent.getState();
public getState(linear:boolean = false): number[][]|number[]{
return this.level.agent.getState(linear);
}
step(action: number){
/*
Step into the environement
@action (Integer)
*/
/**
Step into the environement
@action Action to process to step
@return Reward value
*/
public step(action: number|number[]): number{
return this.level.step(1, action);
}
reset(){
/**
* Reset the environement
*/
public reset(): void{
/*
Reset the agent position
*/
this.level.reset();
}
randomRoadPosition(){
/**
* Set the agent on a new random road on the map.
*/
randomRoadPosition(): void{
/*
This position
*/
@@ -186,7 +167,10 @@ export class MetaCar {
}
}
loop(delta: number){
/**
* @delta Time since the last update
*/
private _loop(delta: number): void{
if (this.event.isPlaying()){
this.event.playCallback();
}
@@ -195,4 +179,20 @@ export class MetaCar {
}
}
/**
* Create the UIEvent instance and set the events
* callbacks relative to the UI.
*/
private _setEvents(): void{
// SetEvents callback
this.event = new UIEvent(this.level, this.canvasId);
this.eventCallback = [
(fc: any) => this.event.onTrain(fc),
(fc: any) => this.event.onPlay(fc),
(fc:any) => this.event.onStop(fc),
(fc: any) => this.event.onResetEnv(fc),
(fc: any, opt: eventLoadOptions) => this.event.onLoad(fc, opt)
];
}
}
-8
View File
@@ -97,14 +97,6 @@ export class UIEvent {
if (fc) fc();
});
}
public onResetAgent(fc: any){
// Create the button
const button = this._createButton(this.buttonsContainer, "reset_agent");
button.addEventListener("click", () => {
if (fc) fc();
});
}
public onCustomEvent(name: string, fc: any){
// Create the button