diff --git a/.gitattributes b/.gitattributes index 755356a054893aa3dbdb5ae3fec6a00637e6e3ae..4edd5acb13dba6a9f44a206fa1b6a1789fbcc50a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,31 +1 @@ -*.7z filter=lfs diff=lfs merge=lfs -text -*.arrow filter=lfs diff=lfs merge=lfs -text *.bin filter=lfs diff=lfs merge=lfs -text -*.bz2 filter=lfs diff=lfs merge=lfs -text -*.ftz filter=lfs diff=lfs merge=lfs -text -*.gz filter=lfs diff=lfs merge=lfs -text -*.h5 filter=lfs diff=lfs merge=lfs -text -*.joblib filter=lfs diff=lfs merge=lfs -text -*.lfs.* filter=lfs diff=lfs merge=lfs -text -*.model filter=lfs diff=lfs merge=lfs -text -*.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text -*.onnx filter=lfs diff=lfs merge=lfs -text -*.ot filter=lfs diff=lfs merge=lfs -text -*.parquet filter=lfs diff=lfs merge=lfs -text -*.pb filter=lfs diff=lfs merge=lfs -text -*.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text -*.pt filter=lfs diff=lfs merge=lfs -text -*.pth filter=lfs diff=lfs merge=lfs -text -*.rar filter=lfs diff=lfs merge=lfs -text -saved_model/**/* filter=lfs diff=lfs merge=lfs -text -*.tar.* filter=lfs diff=lfs merge=lfs -text -*.tflite filter=lfs diff=lfs merge=lfs -text -*.tgz filter=lfs diff=lfs merge=lfs -text -*.wasm filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.zstandard filter=lfs diff=lfs merge=lfs -text -*tfevents* filter=lfs diff=lfs merge=lfs -text diff --git a/base_envs_set.json b/base_envs_set.json new file mode 100644 index 0000000000000000000000000000000000000000..6097e0a53b84302e8aeb7be6434793c60e48f20d --- /dev/null +++ b/base_envs_set.json @@ -0,0 +1 @@ +{"filenames": ["00_Flat_parkour_+_Bipedal_Walker.json", "01_Easy_parkour_+_Chimpanzee.json", "02_Underwater_parkour_+_Fish.json", "03_Hard_parkour.json"]} \ No newline at end of file diff --git a/base_envs_set/00_Flat_parkour_+_Bipedal_Walker.json b/base_envs_set/00_Flat_parkour_+_Bipedal_Walker.json new file mode 100644 index 0000000000000000000000000000000000000000..6cbbc8d769c1865eb7f4a84ec1c9488a5bf9c63e --- /dev/null +++ b/base_envs_set/00_Flat_parkour_+_Bipedal_Walker.json @@ -0,0 +1 @@ +{"terrain":{"ground":[{"x":9.333333333333334,"y":3.3333333333333335},{"x":9.8,"y":3.3333333333333335},{"x":10.266666666666667,"y":3.3333333333333335},{"x":10.733333333333334,"y":3.3333333333333335},{"x":11.2,"y":3.3333333333333335},{"x":11.666666666666666,"y":3.3333333333333335},{"x":12.133333333333333,"y":3.3333333333333335},{"x":12.6,"y":3.3333333333333335},{"x":13.066666666666666,"y":3.3333333333333335},{"x":13.533333333333333,"y":3.3333333333333335},{"x":14,"y":3.3333333333333335},{"x":14.466666666666667,"y":3.3333333333333335},{"x":14.933333333333334,"y":3.3333333333333335},{"x":15.4,"y":3.3333333333333335},{"x":15.866666666666667,"y":3.3333333333333335},{"x":16.333333333333332,"y":3.3333333333333335},{"x":16.8,"y":3.3333333333333335},{"x":17.266666666666666,"y":3.3333333333333335},{"x":17.733333333333334,"y":3.3333333333333335},{"x":18.2,"y":3.3333333333333335},{"x":18.666666666666668,"y":3.3333333333333335},{"x":19.133333333333333,"y":3.3333333333333335},{"x":19.6,"y":3.3333333333333335},{"x":20.066666666666666,"y":3.3333333333333335},{"x":20.533333333333335,"y":3.3333333333333335},{"x":21,"y":3.3333333333333335},{"x":21.46666666666667,"y":3.3333333333333335},{"x":21.933333333333334,"y":3.3333333333333335},{"x":22.4,"y":3.3333333333333335},{"x":22.866666666666667,"y":3.3333333333333335},{"x":23.333333333333332,"y":3.3333333333333335},{"x":23.8,"y":3.3333333333333335},{"x":24.266666666666666,"y":3.3333333333333335},{"x":24.733333333333334,"y":3.3333333333333335},{"x":25.2,"y":3.3333333333333335},{"x":25.666666666666668,"y":3.3333333333333335},{"x":26.133333333333333,"y":3.3333333333333335},{"x":26.6,"y":3.3333333333333335},{"x":27.066666666666666,"y":3.3333333333333335},{"x":27.533333333333335,"y":3.3333333333333335},{"x":28,"y":3.3333333333333335},{"x":28.46666666666667,"y":3.3333333333333335},{"x":28.933333333333334,"y":3.3333333333333335},{"x":29.400000000000002,"y":3.3333333333333335},{"x":29.866666666666667,"y":3.3333333333333335},{"x":30.333333333333332,"y":3.3333333333333335},{"x":30.8,"y":3.3333333333333335},{"x":31.266666666666666,"y":3.3333333333333335},{"x":31.733333333333334,"y":3.3333333333333335},{"x":32.2,"y":3.3333333333333335},{"x":32.666666666666664,"y":3.3333333333333335},{"x":33.13333333333333,"y":3.3333333333333335},{"x":33.6,"y":3.3333333333333335},{"x":34.06666666666667,"y":3.3333333333333335},{"x":34.53333333333333,"y":3.3333333333333335},{"x":35,"y":3.3333333333333335},{"x":35.46666666666667,"y":3.3333333333333335},{"x":35.93333333333334,"y":3.3333333333333335},{"x":36.4,"y":3.3333333333333335},{"x":36.86666666666667,"y":3.3333333333333335},{"x":37.333333333333336,"y":3.3333333333333335},{"x":37.8,"y":3.3333333333333335},{"x":38.266666666666666,"y":3.3333333333333335},{"x":38.733333333333334,"y":3.3333333333333335},{"x":39.2,"y":3.3333333333333335},{"x":39.666666666666664,"y":3.3333333333333335},{"x":40.13333333333333,"y":3.3333333333333335},{"x":40.6,"y":3.3333333333333335},{"x":41.06666666666667,"y":3.3333333333333335},{"x":41.53333333333333,"y":3.3333333333333335},{"x":42,"y":3.3333333333333335},{"x":42.46666666666667,"y":3.3333333333333335},{"x":42.93333333333334,"y":3.3333333333333335},{"x":43.4,"y":3.3333333333333335},{"x":43.86666666666667,"y":3.3333333333333335},{"x":44.333333333333336,"y":3.3333333333333335},{"x":44.8,"y":3.3333333333333335},{"x":45.266666666666666,"y":3.3333333333333335},{"x":45.733333333333334,"y":3.3333333333333335},{"x":46.2,"y":3.3333333333333335},{"x":46.666666666666664,"y":3.3333333333333335},{"x":47.13333333333333,"y":3.3333333333333335},{"x":47.6,"y":3.3333333333333335},{"x":48.06666666666667,"y":3.3333333333333335},{"x":48.53333333333333,"y":3.3333333333333335},{"x":49,"y":3.3333333333333335},{"x":49.46666666666667,"y":3.3333333333333335},{"x":49.93333333333334,"y":3.3333333333333335},{"x":50.4,"y":3.3333333333333335},{"x":50.86666666666667,"y":3.3333333333333335},{"x":51.333333333333336,"y":3.3333333333333335},{"x":51.800000000000004,"y":3.3333333333333335},{"x":52.266666666666666,"y":3.3333333333333335},{"x":52.733333333333334,"y":3.3333333333333335},{"x":53.2,"y":3.3333333333333335},{"x":53.666666666666664,"y":3.3333333333333335},{"x":54.13333333333333,"y":3.3333333333333335},{"x":54.6,"y":3.3333333333333335},{"x":55.06666666666667,"y":3.3333333333333335},{"x":55.53333333333333,"y":3.3333333333333335},{"x":56,"y":3.3333333333333335},{"x":56.46666666666667,"y":3.3333333333333335},{"x":56.93333333333334,"y":3.3333333333333335},{"x":57.4,"y":3.3333333333333335},{"x":57.86666666666667,"y":3.3333333333333335},{"x":58.333333333333336,"y":3.3333333333333335},{"x":58.800000000000004,"y":3.3333333333333335},{"x":59.266666666666666,"y":3.3333333333333335},{"x":59.733333333333334,"y":3.3333333333333335},{"x":60.2,"y":3.3333333333333335},{"x":60.666666666666664,"y":3.3333333333333335},{"x":61.13333333333333,"y":3.3333333333333335},{"x":61.6,"y":3.3333333333333335},{"x":62.06666666666667,"y":3.3333333333333335},{"x":62.53333333333333,"y":3.3333333333333335},{"x":63,"y":3.3333333333333335},{"x":63.46666666666667,"y":3.3333333333333335},{"x":63.93333333333334,"y":3.3333333333333335},{"x":64.4,"y":3.3333333333333335},{"x":64.86666666666667,"y":3.3333333333333335},{"x":65.33333333333333,"y":3.3333333333333335},{"x":65.8,"y":3.3333333333333335},{"x":66.26666666666667,"y":3.3333333333333335},{"x":66.73333333333333,"y":3.3333333333333335},{"x":67.2,"y":3.3333333333333335},{"x":67.66666666666667,"y":3.3333333333333335},{"x":68.13333333333334,"y":3.3333333333333335},{"x":68.6,"y":3.3333333333333335},{"x":69.06666666666666,"y":3.3333333333333335},{"x":69.53333333333333,"y":3.3333333333333335},{"x":70,"y":3.3333333333333335},{"x":70.46666666666667,"y":3.3333333333333335},{"x":70.93333333333334,"y":3.3333333333333335},{"x":71.4,"y":3.3333333333333335},{"x":71.86666666666667,"y":3.3333333333333335},{"x":72.33333333333333,"y":3.3333333333333335},{"x":72.8,"y":3.3333333333333335},{"x":73.26666666666667,"y":3.3333333333333335},{"x":73.73333333333333,"y":3.3333333333333335},{"x":74.2,"y":3.3333333333333335},{"x":74.66666666666667,"y":3.3333333333333335},{"x":75.13333333333334,"y":3.3333333333333335},{"x":75.6,"y":3.3333333333333335},{"x":76.06666666666666,"y":3.3333333333333335},{"x":76.53333333333333,"y":3.3333333333333335},{"x":77,"y":3.3333333333333335},{"x":77.46666666666667,"y":3.3333333333333335},{"x":77.93333333333334,"y":3.3333333333333335},{"x":78.4,"y":3.3333333333333335},{"x":78.86666666666667,"y":3.3333333333333335},{"x":79.33333333333333,"y":3.3333333333333335},{"x":79.8,"y":3.3333333333333335},{"x":80.26666666666667,"y":3.3333333333333335},{"x":80.73333333333333,"y":3.3333333333333335},{"x":81.2,"y":3.3333333333333335},{"x":81.66666666666667,"y":3.3333333333333335},{"x":82.13333333333334,"y":3.3333333333333335},{"x":82.6,"y":3.3333333333333335},{"x":83.06666666666666,"y":3.3333333333333335},{"x":83.53333333333333,"y":3.3333333333333335},{"x":84,"y":3.3333333333333335},{"x":84.46666666666667,"y":3.3333333333333335},{"x":84.93333333333334,"y":3.3333333333333335},{"x":85.4,"y":3.3333333333333335},{"x":85.86666666666667,"y":3.3333333333333335},{"x":86.33333333333333,"y":3.3333333333333335},{"x":86.8,"y":3.3333333333333335},{"x":87.26666666666667,"y":3.3333333333333335},{"x":87.73333333333333,"y":3.3333333333333335},{"x":88.2,"y":3.3333333333333335},{"x":88.66666666666667,"y":3.3333333333333335},{"x":89.13333333333334,"y":3.3333333333333335},{"x":89.6,"y":3.3333333333333335},{"x":90.06666666666666,"y":3.3333333333333335},{"x":90.53333333333333,"y":3.3333333333333335},{"x":91,"y":3.3333333333333335},{"x":91.46666666666667,"y":3.3333333333333335},{"x":91.93333333333334,"y":3.3333333333333335},{"x":92.4,"y":3.3333333333333335},{"x":92.86666666666667,"y":3.3333333333333335},{"x":93.33333333333333,"y":3.3333333333333335},{"x":93.8,"y":3.3333333333333335},{"x":94.26666666666667,"y":3.3333333333333335},{"x":94.73333333333333,"y":3.3333333333333335},{"x":95.2,"y":3.3333333333333335},{"x":95.66666666666667,"y":3.3333333333333335},{"x":96.13333333333334,"y":3.3333333333333335},{"x":96.60000000000001,"y":3.3333333333333335},{"x":97.06666666666666,"y":3.3333333333333335},{"x":97.53333333333333,"y":3.3333333333333335},{"x":98,"y":3.3333333333333335},{"x":98.46666666666667,"y":3.3333333333333335},{"x":98.93333333333334,"y":3.3333333333333335},{"x":99.4,"y":3.3333333333333335},{"x":99.86666666666667,"y":3.3333333333333335},{"x":100.33333333333333,"y":3.3333333333333335},{"x":100.8,"y":3.3333333333333335},{"x":101.26666666666667,"y":3.3333333333333335},{"x":101.73333333333333,"y":3.3333333333333335},{"x":102.2,"y":3.3333333333333335},{"x":102.66666666666667,"y":3.3333333333333335}],"ceiling":[{"x":9.333333333333334,"y":16.666666666666668},{"x":9.8,"y":16.666666666666668},{"x":10.266666666666667,"y":16.666666666666668},{"x":10.733333333333334,"y":16.666666666666668},{"x":11.2,"y":16.666666666666668},{"x":11.666666666666666,"y":16.666666666666668},{"x":12.133333333333333,"y":16.666666666666668},{"x":12.6,"y":16.666666666666668},{"x":13.066666666666666,"y":16.666666666666668},{"x":13.533333333333333,"y":16.666666666666668},{"x":14,"y":16.666666666666668},{"x":14.466666666666667,"y":16.666666666666668},{"x":14.933333333333334,"y":16.666666666666668},{"x":15.4,"y":16.666666666666668},{"x":15.866666666666667,"y":16.666666666666668},{"x":16.333333333333332,"y":16.666666666666668},{"x":16.8,"y":16.666666666666668},{"x":17.266666666666666,"y":16.666666666666668},{"x":17.733333333333334,"y":16.666666666666668},{"x":18.2,"y":16.666666666666668},{"x":18.666666666666668,"y":16.666666666666668},{"x":19.133333333333333,"y":16.666666666666668},{"x":19.6,"y":16.666666666666668},{"x":20.066666666666666,"y":16.666666666666668},{"x":20.533333333333335,"y":16.666666666666668},{"x":21,"y":16.666666666666668},{"x":21.46666666666667,"y":16.666666666666668},{"x":21.933333333333334,"y":16.666666666666668},{"x":22.4,"y":16.666666666666668},{"x":22.866666666666667,"y":16.666666666666668},{"x":23.333333333333332,"y":16.666666666666668},{"x":23.8,"y":16.666666666666668},{"x":24.266666666666666,"y":16.666666666666668},{"x":24.733333333333334,"y":16.666666666666668},{"x":25.2,"y":16.666666666666668},{"x":25.666666666666668,"y":16.666666666666668},{"x":26.133333333333333,"y":16.666666666666668},{"x":26.6,"y":16.666666666666668},{"x":27.066666666666666,"y":16.666666666666668},{"x":27.533333333333335,"y":16.666666666666668},{"x":28,"y":16.666666666666668},{"x":28.46666666666667,"y":16.666666666666668},{"x":28.933333333333334,"y":16.666666666666668},{"x":29.400000000000002,"y":16.666666666666668},{"x":29.866666666666667,"y":16.666666666666668},{"x":30.333333333333332,"y":16.666666666666668},{"x":30.8,"y":16.666666666666668},{"x":31.266666666666666,"y":16.666666666666668},{"x":31.733333333333334,"y":16.666666666666668},{"x":32.2,"y":16.666666666666668},{"x":32.666666666666664,"y":16.666666666666668},{"x":33.13333333333333,"y":16.666666666666668},{"x":33.6,"y":16.666666666666668},{"x":34.06666666666667,"y":16.666666666666668},{"x":34.53333333333333,"y":16.666666666666668},{"x":35,"y":16.666666666666668},{"x":35.46666666666667,"y":16.666666666666668},{"x":35.93333333333334,"y":16.666666666666668},{"x":36.4,"y":16.666666666666668},{"x":36.86666666666667,"y":16.666666666666668},{"x":37.333333333333336,"y":16.666666666666668},{"x":37.8,"y":16.666666666666668},{"x":38.266666666666666,"y":16.666666666666668},{"x":38.733333333333334,"y":16.666666666666668},{"x":39.2,"y":16.666666666666668},{"x":39.666666666666664,"y":16.666666666666668},{"x":40.13333333333333,"y":16.666666666666668},{"x":40.6,"y":16.666666666666668},{"x":41.06666666666667,"y":16.666666666666668},{"x":41.53333333333333,"y":16.666666666666668},{"x":42,"y":16.666666666666668},{"x":42.46666666666667,"y":16.666666666666668},{"x":42.93333333333334,"y":16.666666666666668},{"x":43.4,"y":16.666666666666668},{"x":43.86666666666667,"y":16.666666666666668},{"x":44.333333333333336,"y":16.666666666666668},{"x":44.8,"y":16.666666666666668},{"x":45.266666666666666,"y":16.666666666666668},{"x":45.733333333333334,"y":16.666666666666668},{"x":46.2,"y":16.666666666666668},{"x":46.666666666666664,"y":16.666666666666668},{"x":47.13333333333333,"y":16.666666666666668},{"x":47.6,"y":16.666666666666668},{"x":48.06666666666667,"y":16.666666666666668},{"x":48.53333333333333,"y":16.666666666666668},{"x":49,"y":16.666666666666668},{"x":49.46666666666667,"y":16.666666666666668},{"x":49.93333333333334,"y":16.666666666666668},{"x":50.4,"y":16.666666666666668},{"x":50.86666666666667,"y":16.666666666666668},{"x":51.333333333333336,"y":16.666666666666668},{"x":51.800000000000004,"y":16.666666666666668},{"x":52.266666666666666,"y":16.666666666666668},{"x":52.733333333333334,"y":16.666666666666668},{"x":53.2,"y":16.666666666666668},{"x":53.666666666666664,"y":16.666666666666668},{"x":54.13333333333333,"y":16.666666666666668},{"x":54.6,"y":16.666666666666668},{"x":55.06666666666667,"y":16.666666666666668},{"x":55.53333333333333,"y":16.666666666666668},{"x":56,"y":16.666666666666668},{"x":56.46666666666667,"y":16.666666666666668},{"x":56.93333333333334,"y":16.666666666666668},{"x":57.4,"y":16.666666666666668},{"x":57.86666666666667,"y":16.666666666666668},{"x":58.333333333333336,"y":16.666666666666668},{"x":58.800000000000004,"y":16.666666666666668},{"x":59.266666666666666,"y":16.666666666666668},{"x":59.733333333333334,"y":16.666666666666668},{"x":60.2,"y":16.666666666666668},{"x":60.666666666666664,"y":16.666666666666668},{"x":61.13333333333333,"y":16.666666666666668},{"x":61.6,"y":16.666666666666668},{"x":62.06666666666667,"y":16.666666666666668},{"x":62.53333333333333,"y":16.666666666666668},{"x":63,"y":16.666666666666668},{"x":63.46666666666667,"y":16.666666666666668},{"x":63.93333333333334,"y":16.666666666666668},{"x":64.4,"y":16.666666666666668},{"x":64.86666666666667,"y":16.666666666666668},{"x":65.33333333333333,"y":16.666666666666668},{"x":65.8,"y":16.666666666666668},{"x":66.26666666666667,"y":16.666666666666668},{"x":66.73333333333333,"y":16.666666666666668},{"x":67.2,"y":16.666666666666668},{"x":67.66666666666667,"y":16.666666666666668},{"x":68.13333333333334,"y":16.666666666666668},{"x":68.6,"y":16.666666666666668},{"x":69.06666666666666,"y":16.666666666666668},{"x":69.53333333333333,"y":16.666666666666668},{"x":70,"y":16.666666666666668},{"x":70.46666666666667,"y":16.666666666666668},{"x":70.93333333333334,"y":16.666666666666668},{"x":71.4,"y":16.666666666666668},{"x":71.86666666666667,"y":16.666666666666668},{"x":72.33333333333333,"y":16.666666666666668},{"x":72.8,"y":16.666666666666668},{"x":73.26666666666667,"y":16.666666666666668},{"x":73.73333333333333,"y":16.666666666666668},{"x":74.2,"y":16.666666666666668},{"x":74.66666666666667,"y":16.666666666666668},{"x":75.13333333333334,"y":16.666666666666668},{"x":75.6,"y":16.666666666666668},{"x":76.06666666666666,"y":16.666666666666668},{"x":76.53333333333333,"y":16.666666666666668},{"x":77,"y":16.666666666666668},{"x":77.46666666666667,"y":16.666666666666668},{"x":77.93333333333334,"y":16.666666666666668},{"x":78.4,"y":16.666666666666668},{"x":78.86666666666667,"y":16.666666666666668},{"x":79.33333333333333,"y":16.666666666666668},{"x":79.8,"y":16.666666666666668},{"x":80.26666666666667,"y":16.666666666666668},{"x":80.73333333333333,"y":16.666666666666668},{"x":81.2,"y":16.666666666666668},{"x":81.66666666666667,"y":16.666666666666668},{"x":82.13333333333334,"y":16.666666666666668},{"x":82.6,"y":16.666666666666668},{"x":83.06666666666666,"y":16.666666666666668},{"x":83.53333333333333,"y":16.666666666666668},{"x":84,"y":16.666666666666668},{"x":84.46666666666667,"y":16.666666666666668},{"x":84.93333333333334,"y":16.666666666666668},{"x":85.4,"y":16.666666666666668},{"x":85.86666666666667,"y":16.666666666666668},{"x":86.33333333333333,"y":16.666666666666668},{"x":86.8,"y":16.666666666666668},{"x":87.26666666666667,"y":16.666666666666668},{"x":87.73333333333333,"y":16.666666666666668},{"x":88.2,"y":16.666666666666668},{"x":88.66666666666667,"y":16.666666666666668},{"x":89.13333333333334,"y":16.666666666666668},{"x":89.6,"y":16.666666666666668},{"x":90.06666666666666,"y":16.666666666666668},{"x":90.53333333333333,"y":16.666666666666668},{"x":91,"y":16.666666666666668},{"x":91.46666666666667,"y":16.666666666666668},{"x":91.93333333333334,"y":16.666666666666668},{"x":92.4,"y":16.666666666666668},{"x":92.86666666666667,"y":16.666666666666668},{"x":93.33333333333333,"y":16.666666666666668},{"x":93.8,"y":16.666666666666668},{"x":94.26666666666667,"y":16.666666666666668},{"x":94.73333333333333,"y":16.666666666666668},{"x":95.2,"y":16.666666666666668},{"x":95.66666666666667,"y":16.666666666666668},{"x":96.13333333333334,"y":16.666666666666668},{"x":96.60000000000001,"y":16.666666666666668},{"x":97.06666666666666,"y":16.666666666666668},{"x":97.53333333333333,"y":16.666666666666668},{"x":98,"y":16.666666666666668},{"x":98.46666666666667,"y":16.666666666666668},{"x":98.93333333333334,"y":16.666666666666668},{"x":99.4,"y":16.666666666666668},{"x":99.86666666666667,"y":16.666666666666668},{"x":100.33333333333333,"y":16.666666666666668},{"x":100.8,"y":16.666666666666668},{"x":101.26666666666667,"y":16.666666666666668},{"x":101.73333333333333,"y":16.666666666666668},{"x":102.2,"y":16.666666666666668}],"parkourConfig":{"dim1":0,"dim2":0,"dim3":0,"smoothing":15,"waterLevel":0},"creepersConfig":{"width":0.2,"height":0.2,"spacing":5,"type":"Rigid"}},"agents":[{"morphology":"bipedal","name":"Joe","age": "adult","path":"policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1","init_pos":{"x":4.664080407626852,"y":5.7120234541018675}}],"description":{"EN": {"name":"Flat parkour + Bipedal Walker","text":"This parkour is completely flat, perfect for bipedal walkers."}, "FR": {"name":"Parkour plat + Bipède","text":"Ce parkour est totalement plat, parfait pour les agents bipèdes."}},"image":"data:image/octet-stream;base64,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QIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5ObcEYbAAAFzklEQVQVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAuLp2cOdS4AAAQIECBAgQIAAAQIECBAgQIBAExBPm5MVAQIECBAgQIAAAQIECBAgQIAAAQJnAgPdBsAyo4QHGwAAAABJRU5ErkJggg=="} diff --git a/base_envs_set/01_Easy_parkour_+_Chimpanzee.json b/base_envs_set/01_Easy_parkour_+_Chimpanzee.json new file mode 100644 index 0000000000000000000000000000000000000000..5880b776401e5a2694350ce424ebc3de4c6acf82 --- /dev/null +++ b/base_envs_set/01_Easy_parkour_+_Chimpanzee.json @@ -0,0 +1 @@ +{"terrain":{"ground":[{"x":9.333333333333334,"y":3.3333333333333335},{"x":9.8,"y":3.3044253743489587},{"x":10.266666666666667,"y":3.2732736409505208},{"x":10.733333333333334,"y":3.23781581624349},{"x":11.2,"y":3.19116640218099},{"x":11.666666666666666,"y":3.1117195027669275},{"x":12.133333333333333,"y":3.053800496419271},{"x":12.6,"y":3.024089803059896},{"x":13.066666666666666,"y":3.0113592122395834},{"x":13.533333333333333,"y":3.0505754597981776},{"x":14,"y":3.195539693196615},{"x":14.466666666666667,"y":3.317394185384115},{"x":14.933333333333334,"y":3.348000630696615},{"x":15.4,"y":3.340373738606771},{"x":15.866666666666667,"y":3.3239356282552084},{"x":16.333333333333332,"y":3.306802449544271},{"x":16.8,"y":3.290917134602865},{"x":17.266666666666666,"y":3.2767149251302086},{"x":17.733333333333334,"y":3.264265767415365},{"x":18.2,"y":3.2535096028645833},{"x":18.666666666666668,"y":3.244277791341146},{"x":19.133333333333333,"y":3.235980733235677},{"x":19.6,"y":3.226907857259115},{"x":20.066666666666666,"y":3.2116423543294275},{"x":20.533333333333335,"y":3.1743056844075523},{"x":21,"y":3.0764497273763025},{"x":21.46666666666667,"y":2.8730322774251302},{"x":21.933333333333334,"y":2.626501912434896},{"x":22.4,"y":2.464354970296224},{"x":22.866666666666667,"y":2.3901686909993494},{"x":23.333333333333332,"y":2.3599029134114584},{"x":23.8,"y":2.3457744038899744},{"x":24.266666666666666,"y":2.335790395100912},{"x":24.733333333333334,"y":2.3254619649251307},{"x":25.2,"y":2.313462056477865},{"x":25.666666666666668,"y":2.300294576009115},{"x":26.133333333333333,"y":2.287305531819662},{"x":26.6,"y":2.2746325276692714},{"x":27.066666666666666,"y":2.2597612508138023},{"x":27.533333333333335,"y":2.2405401204427084},{"x":28,"y":2.2201580098470055},{"x":28.46666666666667,"y":2.2033855489095053},{"x":28.933333333333334,"y":2.195334218343099},{"x":29.400000000000002,"y":2.1984822591145834},{"x":29.866666666666667,"y":2.2095619710286463},{"x":30.333333333333332,"y":2.2247730000813806},{"x":30.8,"y":2.2423719075520836},{"x":31.266666666666666,"y":2.2621568196614588},{"x":31.733333333333334,"y":2.28463759358724},{"x":32.2,"y":2.3103189595540368},{"x":32.666666666666664,"y":2.3392235310872396},{"x":33.13333333333333,"y":2.3705281575520836},{"x":33.6,"y":2.4027119649251305},{"x":34.06666666666667,"y":2.434004140218099},{"x":34.53333333333333,"y":2.4630680135091145},{"x":35,"y":2.48928212483724},{"x":35.46666666666667,"y":2.5126379597981776},{"x":35.93333333333334,"y":2.5335017293294273},{"x":36.4,"y":2.552472005208334},{"x":36.86666666666667,"y":2.5702991536458333},{"x":37.333333333333336,"y":2.587740681966146},{"x":37.8,"y":2.6055993245442712},{"x":38.266666666666666,"y":2.624695302327474},{"x":38.733333333333334,"y":2.6459023946126305},{"x":39.2,"y":2.670154347737631},{"x":39.666666666666664,"y":2.698420888264974},{"x":40.13333333333333,"y":2.7318249104817713},{"x":40.6,"y":2.7715180562337243},{"x":41.06666666666667,"y":2.81876064046224},{"x":41.53333333333333,"y":2.874722432454427},{"x":42,"y":2.9405371297200524},{"x":42.46666666666667,"y":3.016979634602865},{"x":42.93333333333334,"y":3.104294026692709},{"x":43.4,"y":3.202102742513021},{"x":43.86666666666667,"y":3.308980122884115},{"x":44.333333333333336,"y":3.422261433919271},{"x":44.8,"y":3.538379048665365},{"x":45.266666666666666,"y":3.6529309285481775},{"x":45.733333333333334,"y":3.761485921223959},{"x":46.2,"y":3.8606924641927085},{"x":46.666666666666664,"y":3.9484012654622402},{"x":47.13333333333333,"y":4.024060811360677},{"x":47.6,"y":4.08806972249349},{"x":48.06666666666667,"y":4.1417705281575525},{"x":48.53333333333333,"y":4.186937337239584},{"x":49,"y":4.225848714192709},{"x":49.46666666666667,"y":4.261103474934896},{"x":49.93333333333334,"y":4.295617757161459},{"x":50.4,"y":4.33269405110677},{"x":50.86666666666667,"y":4.376088216145833},{"x":51.333333333333336,"y":4.429998860677084},{"x":51.800000000000004,"y":4.497922383626302},{"x":52.266666666666666,"y":4.579456685384114},{"x":52.733333333333334,"y":4.668328755696615},{"x":53.2,"y":4.756836079915365},{"x":53.666666666666664,"y":4.84623036702474},{"x":54.13333333333333,"y":4.956061787923177},{"x":54.6,"y":5.073443745930989},{"x":55.06666666666667,"y":5.119862447102864},{"x":55.53333333333333,"y":5.139233540852865},{"x":56,"y":5.150392354329427},{"x":56.46666666666667,"y":5.157726094563802},{"x":56.93333333333334,"y":5.162798116048178},{"x":57.4,"y":5.166352193196614},{"x":57.86666666666667,"y":5.168854512532553},{"x":58.333333333333336,"y":5.170620381673178},{"x":58.800000000000004,"y":5.1718691609700524},{"x":59.266666666666666,"y":5.172753560384114},{"x":59.733333333333334,"y":5.173382344563802},{"x":60.2,"y":5.1738316853841155},{"x":60.666666666666664,"y":5.174149922688802},{"x":61.13333333333333,"y":5.174379536946615},{"x":61.6,"y":5.174543599446615},{"x":62.06666666666667,"y":5.174657124837239},{"x":62.53333333333333,"y":5.174727437337239},{"x":63,"y":5.17474355061849},{"x":63.46666666666667,"y":5.1746549275716145},{"x":63.93333333333334,"y":5.174301167805989},{"x":64.4,"y":5.173234395345052},{"x":64.86666666666667,"y":5.170262227376302},{"x":65.33333333333333,"y":5.16239345296224},{"x":65.8,"y":5.1427337849934895},{"x":66.26666666666667,"y":5.0981999715169275},{"x":66.73333333333333,"y":5.01325331624349},{"x":67.2,"y":4.890326924641927},{"x":67.66666666666667,"y":4.777250508626302},{"x":68.13333333333334,"y":4.763372578938802},{"x":68.6,"y":4.703074849446615},{"x":69.06666666666666,"y":4.669217549641927},{"x":69.53333333333333,"y":4.658348409016927},{"x":70,"y":4.657791035970052},{"x":70.46666666666667,"y":4.664238911946615},{"x":70.93333333333334,"y":4.677343037923177},{"x":71.4,"y":4.697934346516927},{"x":71.86666666666667,"y":4.727068623860678},{"x":72.33333333333333,"y":4.765190450032552},{"x":72.8,"y":4.811322041829428},{"x":73.26666666666667,"y":4.862638814290365},{"x":73.73333333333333,"y":4.914716939290365},{"x":74.2,"y":4.963077657063803},{"x":74.66666666666667,"y":5.0046938680013024},{"x":75.13333333333334,"y":5.038601704915365},{"x":75.6,"y":5.065125630696615},{"x":76.06666666666666,"y":5.085245625813802},{"x":76.53333333333333,"y":5.100006490071615},{"x":77,"y":5.110344991048177},{"x":77.46666666666667,"y":5.116965352376303},{"x":77.93333333333334,"y":5.120333028157551},{"x":78.4,"y":5.120677632649739},{"x":78.86666666666667,"y":5.11796913655599},{"x":79.33333333333333,"y":5.11188564046224},{"x":79.8,"y":5.101667622884115},{"x":80.26666666666667,"y":5.085838887532552},{"x":80.73333333333333,"y":5.061629414876302},{"x":81.2,"y":5.023682637532552},{"x":81.66666666666667,"y":4.95993446858724},{"x":82.13333333333334,"y":4.8363983357747395},{"x":82.6,"y":4.5947035115559896},{"x":83.06666666666666,"y":4.37664247639974},{"x":83.53333333333333,"y":4.311235371907552},{"x":84,"y":4.275799519856771},{"x":84.46666666666667,"y":4.237397908528646},{"x":84.93333333333334,"y":4.204511067708333},{"x":85.4,"y":4.179387349446615},{"x":85.86666666666667,"y":4.161069844563802},{"x":86.33333333333333,"y":4.148059102376302},{"x":86.8,"y":4.139013326009115},{"x":87.26666666666667,"y":4.132851826985677},{"x":87.73333333333333,"y":4.128731770833333},{"x":88.2,"y":4.12602528889974},{"x":88.66666666666667,"y":4.124276631673178},{"x":89.13333333333334,"y":4.123162434895834},{"x":89.6,"y":4.122464253743489},{"x":90.06666666666666,"y":4.122031575520834},{"x":90.53333333333333,"y":4.1217660725911465},{"x":91,"y":4.121605489095052},{"x":91.46666666666667,"y":4.12150917561849},{"x":91.93333333333334,"y":4.121451314290365},{"x":92.4,"y":4.121417805989584},{"x":92.86666666666667,"y":4.121397664388021},{"x":93.33333333333333,"y":4.12138612874349},{"x":93.8,"y":4.121379170735677},{"x":94.26666666666667,"y":4.121375508626302},{"x":94.73333333333333,"y":4.121373311360678},{"x":95.2,"y":4.121372395833333},{"x":95.66666666666667,"y":4.121371663411459},{"x":96.13333333333334,"y":4.121371297200521},{"x":96.60000000000001,"y":4.121371297200521},{"x":97.06666666666666,"y":4.121370747884114},{"x":97.53333333333333,"y":4.121371114095052},{"x":98,"y":4.1213714803059895},{"x":98.46666666666667,"y":4.1213714803059895},{"x":98.93333333333334,"y":4.121371114095052},{"x":99.4,"y":4.121371114095052},{"x":99.86666666666667,"y":4.121371114095052},{"x":100.33333333333333,"y":4.121371114095052},{"x":100.8,"y":4.121371114095052},{"x":101.26666666666667,"y":4.121371114095052},{"x":101.73333333333333,"y":4.121371114095052},{"x":102.2,"y":4.121371114095052}],"ceiling":[{"x":9.333333333333334,"y":11.333333333333334},{"x":9.8,"y":11.356242207845053},{"x":10.266666666666667,"y":11.394947224934896},{"x":10.733333333333334,"y":11.510367848714193},{"x":11.2,"y":11.89269440205892},{"x":11.666666666666666,"y":12.482396418889364},{"x":12.133333333333333,"y":12.772025914510092},{"x":12.6,"y":12.851881139119467},{"x":13.066666666666666,"y":12.876695134480794},{"x":13.533333333333333,"y":12.87921571858724},{"x":14,"y":12.87622629292806},{"x":14.466666666666667,"y":12.895386449178062},{"x":14.933333333333334,"y":12.915239430745444},{"x":15.4,"y":12.929862508138022},{"x":15.866666666666667,"y":12.942348424275718},{"x":16.333333333333332,"y":12.953920918782554},{"x":16.8,"y":12.9648880666097},{"x":17.266666666666666,"y":12.975351399739584},{"x":17.733333333333334,"y":12.985395512898762},{"x":18.2,"y":12.99509058125814},{"x":18.666666666666668,"y":13.004475285847981},{"x":19.133333333333333,"y":13.013499547322592},{"x":19.6,"y":13.021732106526692},{"x":20.066666666666666,"y":13.027541859944662},{"x":20.533333333333335,"y":13.025893086751303},{"x":21,"y":13.004786885579428},{"x":21.46666666666667,"y":12.951313771565754},{"x":21.933333333333334,"y":12.877026875813804},{"x":22.4,"y":12.799352551778156},{"x":22.866666666666667,"y":12.752219487508139},{"x":23.333333333333332,"y":12.740487256368002},{"x":23.8,"y":12.745737164815267},{"x":24.266666666666666,"y":12.757767468770346},{"x":24.733333333333334,"y":12.77269800313314},{"x":25.2,"y":12.78925137837728},{"x":25.666666666666668,"y":12.807534871419271},{"x":26.133333333333333,"y":12.828984166463215},{"x":26.6,"y":12.857071584065757},{"x":27.066666666666666,"y":12.898287434895835},{"x":27.533333333333335,"y":12.960749333699546},{"x":28,"y":13.04564412434896},{"x":28.46666666666667,"y":13.136151875813802},{"x":28.933333333333334,"y":13.21046275838216},{"x":29.400000000000002,"y":13.265758504231773},{"x":29.866666666666667,"y":13.311603902180991},{"x":30.333333333333332,"y":13.356601613362631},{"x":30.8,"y":13.405401875813801},{"x":31.266666666666666,"y":13.45967470296224},{"x":31.733333333333334,"y":13.519123189290365},{"x":32.2,"y":13.582217122395832},{"x":32.666666666666664,"y":13.646631520589192},{"x":33.13333333333333,"y":13.70963710530599},{"x":33.6,"y":13.768585072835286},{"x":34.06666666666667,"y":13.821210408528646},{"x":34.53333333333333,"y":13.866230275472006},{"x":35,"y":13.903386494954429},{"x":35.46666666666667,"y":13.933111104329427},{"x":35.93333333333334,"y":13.956131398518881},{"x":36.4,"y":13.973271993001301},{"x":36.86666666666667,"y":13.98536153157552},{"x":37.333333333333336,"y":13.993039693196614},{"x":37.8,"y":13.996782735188802},{"x":38.266666666666666,"y":13.996905415852865},{"x":38.733333333333334,"y":13.993526753743488},{"x":39.2,"y":13.986591451009115},{"x":39.666666666666664,"y":13.975883626302085},{"x":40.13333333333333,"y":13.961008229573569},{"x":40.6,"y":13.941434712727865},{"x":41.06666666666667,"y":13.916467824300131},{"x":41.53333333333333,"y":13.885348775227865},{"x":42,"y":13.84722694905599},{"x":42.46666666666667,"y":13.801358571370443},{"x":42.93333333333334,"y":13.747217946370444},{"x":43.4,"y":13.68462004597982},{"x":43.86666666666667,"y":13.614070790608725},{"x":44.333333333333336,"y":13.537022847493489},{"x":44.8,"y":13.455776021321615},{"x":45.266666666666666,"y":13.373513142903647},{"x":45.733333333333334,"y":13.293786366780601},{"x":46.2,"y":13.219707021077475},{"x":46.666666666666664,"y":13.153797566731772},{"x":47.13333333333333,"y":13.097600575764975},{"x":47.6,"y":13.05211186726888},{"x":48.06666666666667,"y":13.017841115315754},{"x":48.53333333333333,"y":12.995343358357747},{"x":49,"y":12.985308446248371},{"x":49.46666666666667,"y":12.98882233174642},{"x":49.93333333333334,"y":13.007299001057945},{"x":50.4,"y":13.041910649617513},{"x":50.86666666666667,"y":13.092317708333333},{"x":51.333333333333336,"y":13.155050832112632},{"x":51.800000000000004,"y":13.222953755696615},{"x":52.266666666666666,"y":13.288441884358726},{"x":52.733333333333334,"y":13.34849681599935},{"x":53.2,"y":13.406974202473958},{"x":53.666666666666664,"y":13.484548756917317},{"x":54.13333333333333,"y":13.662147603352864},{"x":54.6,"y":14.073355244954428},{"x":55.06666666666667,"y":14.460268269856773},{"x":55.53333333333333,"y":14.597631612141928},{"x":56,"y":14.637995381673175},{"x":56.46666666666667,"y":14.653909444173177},{"x":56.93333333333334,"y":14.66268806966146},{"x":57.4,"y":14.668412862141928},{"x":57.86666666666667,"y":14.672362263997396},{"x":58.333333333333336,"y":14.675135762532552},{"x":58.800000000000004,"y":14.677094441731771},{"x":59.266666666666666,"y":14.678482381184896},{"x":59.733333333333334,"y":14.679470235188802},{"x":60.2,"y":14.680174825032552},{"x":60.666666666666664,"y":14.680678914388022},{"x":61.13333333333333,"y":14.681041829427084},{"x":61.6,"y":14.681302571614584},{"x":62.06666666666667,"y":14.68149501546224},{"x":62.53333333333333,"y":14.681648274739583},{"x":63,"y":14.68179951985677},{"x":63.46666666666667,"y":14.68203151448568},{"x":63.93333333333334,"y":14.682548787434897},{"x":64.4,"y":14.683900105794269},{"x":64.86666666666667,"y":14.687511128743491},{"x":65.33333333333333,"y":14.696891255696613},{"x":65.8,"y":14.719654561360677},{"x":66.26666666666667,"y":14.768265950520831},{"x":66.73333333333333,"y":14.85171864827474},{"x":67.2,"y":14.959508443196615},{"x":67.66666666666667,"y":15.090086263020833},{"x":68.13333333333334,"y":15.41517097981771},{"x":68.6,"y":15.751902669270834},{"x":69.06666666666666,"y":15.817337605794272},{"x":69.53333333333333,"y":15.828682454427081},{"x":70,"y":15.829334676106772},{"x":70.46666666666667,"y":15.824558553059894},{"x":70.93333333333334,"y":15.814638631184895},{"x":71.4,"y":15.79854951985677},{"x":71.86666666666667,"y":15.774864461263022},{"x":72.33333333333333,"y":15.742573079427082},{"x":72.8,"y":15.702113362630207},{"x":73.26666666666667,"y":15.655900472005207},{"x":73.73333333333333,"y":15.60789131673177},{"x":74.2,"y":15.56214021809896},{"x":74.66666666666667,"y":15.52165303548177},{"x":75.13333333333334,"y":15.487782002766927},{"x":75.6,"y":15.460693379720052},{"x":76.06666666666666,"y":15.439794270833332},{"x":76.53333333333333,"y":15.424263631184896},{"x":77,"y":15.413275105794273},{"x":77.46666666666667,"y":15.406159627278644},{"x":77.93333333333334,"y":15.402442586263021},{"x":78.4,"y":15.401851338704429},{"x":78.86666666666667,"y":15.40432509358724},{"x":79.33333333333333,"y":15.410005940755209},{"x":79.8,"y":15.419276387532552},{"x":80.26666666666667,"y":15.432834065755209},{"x":80.73333333333333,"y":15.451710591634114},{"x":81.2,"y":15.476962666829426},{"x":81.66666666666667,"y":15.507531575520833},{"x":82.13333333333334,"y":15.528221394856772},{"x":82.6,"y":15.468403767903649},{"x":83.06666666666666,"y":15.250675801595051},{"x":83.53333333333333,"y":15.02533760579427},{"x":84,"y":14.920684590657554},{"x":84.46666666666667,"y":14.890788045247398},{"x":84.93333333333334,"y":14.88687929280599},{"x":85.4,"y":14.890650166829428},{"x":85.86666666666667,"y":14.896075215657554},{"x":86.33333333333333,"y":14.901141560872396},{"x":86.8,"y":14.90524092610677},{"x":87.26666666666667,"y":14.908305196126303},{"x":87.73333333333333,"y":14.910479024251302},{"x":88.2,"y":14.911961629231772},{"x":88.66666666666667,"y":14.912943990071614},{"x":89.13333333333334,"y":14.913578450520834},{"x":89.6,"y":14.913980733235679},{"x":90.06666666666666,"y":14.914231953938803},{"x":90.53333333333333,"y":14.914386494954428},{"x":91,"y":14.914480244954426},{"x":91.46666666666667,"y":14.914537373860679},{"x":91.93333333333334,"y":14.91457069905599},{"x":92.4,"y":14.914590291341145},{"x":92.86666666666667,"y":14.914602376302085},{"x":93.33333333333333,"y":14.91460860188802},{"x":93.8,"y":14.914612996419269},{"x":94.26666666666667,"y":14.914614827473958},{"x":94.73333333333333,"y":14.914615743001303},{"x":95.2,"y":14.914616658528647},{"x":95.66666666666667,"y":14.914617390950522},{"x":96.13333333333334,"y":14.914617207845051},{"x":96.60000000000001,"y":14.914617574055988},{"x":97.06666666666666,"y":14.914617757161459},{"x":97.53333333333333,"y":14.914617757161459},{"x":98,"y":14.914617940266925},{"x":98.46666666666667,"y":14.914617940266925},{"x":98.93333333333334,"y":14.914617940266925},{"x":99.4,"y":14.914617940266925},{"x":99.86666666666667,"y":14.914617940266925},{"x":100.33333333333333,"y":14.914617940266925},{"x":100.8,"y":14.914617940266925},{"x":101.26666666666667,"y":14.914617940266925},{"x":101.73333333333333,"y":14.914617940266925},{"x":102.2,"y":14.914617940266925}],"parkourConfig":{"dim1":1,"dim2":0.8,"dim3":0.2,"smoothing":25,"waterLevel":0.15},"creepersConfig":{"width":0.3,"height":3.5,"spacing":1.5,"type":"Swingable"}},"agents":[{"morphology":"chimpanzee","name":"Caesar","age": "adult","path":"policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2","init_pos":{"x":4.667535283883857,"y":9.627764407223937}}],"description":{"EN": {"name":"Easy parkour + Chimpanzee","text":"This parkour features creepers hanging from the ceiling which allow a chimpanzee to swing from one to another."}, "FR": {"name":"Parkour facile + Chimpanzé","text":"Ce parkour possède des lianes qui pendent du plafond, permettant aux chimpanzés de se balancer de l'une à l'autre."}},"image":"data:image/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAACHYAAAMgCAYAAABMW3cjAAAgAElEQVR4XuzdfYxdeXkf8Oe+zp3xeOy116/7Bma9rJbNsmyzbEqANCCVIP5AIQoQJCKkRhFNG7VSUSNF/YNWqvJ3lT/6T2gLEk1QX6QmpE2aFCWkgCAFAiz7yobFu4u9dmzP252ZO/etOmfGXq/t9b3XeO1nZj5HXN07c3/nnOd8nsdetPe751Y+/elPD8NGgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQTqAi2JGuJwoiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQCgh0GgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIOEIbdYAACAASURBVECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEEgqINiRtDHKIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIdpgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBSAcGOpI1RFgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBAsMMMECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSSCgh2JG2MsggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECgh1mgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVECwI2ljlEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQEOwwAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBpAKCHUkboywCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgGCHGSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIJBUQ7EjaGGURIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAQ7zAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIKmAYEfSxiiLAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDYYQYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAkkFBDuSNkZZBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAHBDjNAgAABAgQIECBAgAABAgQIECBAgAABAttPoFKJGA6333W5IgIECBAgQIAAgR0nINix41ruggkQIECAAAECBAgQIECAAAECBAgQILB1BSqVSgzHCGxUq9UYDAZb90JVToAAAQIECBAgQGBTQLDDKBAgQIAAAQIECBAgQIAAAQIECBAgQIDAlhGoVKoxHI4ObNRqtej3+yOvq1arR7/fG7nOAgIECBAgQIAAAQK3SkCw41bJOy8BAgQIECBAgAABAgQIECBAgAABAgQITCxwo+/E0Wg0o9tdn7gOOxAgQIAAAQIECBC4WQKCHTdL2nkIECBAgAABAgQIECBAgAABAgQIECBAIJ1Ac6oV6521kXWNu27kgSwgQIAAAQIECBAgMKGAYMeEYJYTIECAAAECBAgQIECAAAECBAgQIECAwM4TaE3PxNrqys67cFdMgAABAgQIECBwywUEO255CxRAgAABAgQIECBAgAABAgQIECBAgAABAttFYGbX7lhpL22Xy3EdBAgQIECAAAECCQQEOxI0QQkECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgasJCHaYCwIECBAgQIAAAQIECBAgQIAAAQIECBC49QKVSsRweOvruEkV7Nm7Lxbmz92ksznNzRSoVCoxHGeWd9jM38weOBcBAgQIENhuAoId262jrocAAQIECBAgQIAAAQIECBAgQIAAAQIECBBILzBuAGTcdekvWIEECBAgQIDAdQsIdlw3nR0JECBAgAABAgQIECBAgAABAgQIECBAgAABAtcnUK1WYzAYjNx53HUjD2QBAQIECBAgsGUFBDu2bOsUToAAAQIECBAgQIAAAQIECBAgQIAAAQKFQPEFLsudTiytr5ePtcEg5te70WxOlV+JUXx0Prj0uXi9+WjWarHa7W0epRLD8mhXbrPNZkR0Yu/UMKJS/K9SLiq+TaPYltaL41SjNhzGsFqNaqUS1WJVJaK6ua7Yp3wdEeeXl+P23bNRGRbvD6MyHEZx9uL9WqUStWq1fJxpt+Ouubmo12rRqFajXq1G45LXJmD7C9Rq9ej3ixm99jbuulHH8T4BAgQIECCQT0CwI19PVESAAAECBAgQIECAAAECBAgQIECAAAECryHw7Llz0R8MYm04jE5UY3UwiOX19Th02/44euBQ3HXkaNxx8Gg0G/W488DhMhCx8ahf8nrz53otqtUiRFHfjGm8ctLi6y8u306+/Hx87vf/9VUr++UP/Vbc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AQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBLwSINjhlXz7vD896usq9OdrWMmwjpXEk3F9uO7D1G0dzq0dfCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDA9ilAsMPjc795ysnKV0TDS4d3rCRhJfTB2g+0zyknaMp3z/N4hUyPAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAl4JEOzwSr593luOOVWRZI5GlI7oWEnSSur9te9rz+OP1rGXX+zxCpkeAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBLwSINjhlXz7vLcdd7pyYgGN7DWyYyWWbWnOmjna9WtH6MQffd/jFTI9AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCHglQLDDK/n2eW899jRFG5vlk69jJbZsOeGOSYcfopOvucLjFTI9AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCHglQLDDK/n2eW899nS1NDSod37vVJgj9WlZaog1aNxB++q066/yeIVMjwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJeCRDs8Eq+fd4PXpmtZ279ucaUj1F+Tn7qu0tqlqhJLbr2r894vDqmRwABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEvBQh2eKkv6c0/PKsXfnW/xvUep0goklrNoupFiuUkdfWzv/d4dUyPAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAl4KEOzwUl/S7Ed/p9d+84TG9x2vcCCcWs38qvlSQUg/+sPjHq+O6RFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDASwGCHV7qS/rr9Af1xtN/1qR+kxT0B1Or+bTiU4XLi/SD3830eHVMjwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJeChDs8FJf0p9+do/ee/EV7dJ/F/l9/tRqPln/iYoG9dElj8zweHVMjwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJeChDs8FJf0pM33KaP//G6dhuwW8dKPlr3kXrvMFQX3n+3x6tjegQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDwUoBgh5f6kh770U+06O05qRs7Nny8v/Z9DZ4wTufec7vHq2N6BBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPBSgGCHl/qSHrr0R1r18TxN6jepYyXvrXlPO+61u6befoPHq2N6BBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPBSgGCHl/qSZpx/qSoXrdCEvhM6VvLu6nc1/uADdNr1V3q8OqZHAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAS8FCHZ4qS/pl2ddqMZVlRrXZ1xqJUk7qffXvK/djzlKx0+7xOPVMT0CCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIeClAsMNLfUl3nv5txasbNaZ8TGol8WRcH677UPuedpKOuuhcj1fH9AgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDgpQDBDi/1Jf3spG/K15TUjmU7plYSTUT18fqPdei5U3XQ1NM9Xh3TI4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggICXAgQ7vNSXdOuxpykcD2pkr5GplbTEWzS3Yq6O+f5F2uvEYzxeHdMjgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgJcCBDu81Jd085STla+IhpcOT62kMdaoeZXzdOp1P9KEQw/0eHVMjwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJeChDs8FJf0o2Hn6jSULGGlAxJraQ+Wq8FVQt01s9/qh1239Xj1TE9AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCHgpQLDDS31JNxx6nMoj5RpUNCi1ktrWWi2qXqSLHrhHA0bt4PHqmB4BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEvBQg2OGlvqTrDz5WfQv6akDhgNRKqlqqtLRmqaY99YiK+/T2eHVMjwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJeChDs8FJf0k8OOkYDigaoX0G/1Eoqmiq0vG65rn/lTwrm5Hi8OqZHAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAS8FCHZ4qS/puoOOlk8++X3+tk+/X9FEVD/9xwser4zpEUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQMBrAYIdHp5AY3WNXp7xsKItzYq2tCrufLZGFY9FddkTD3q4MqZGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgWwQINiRDafAGhBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgTQCBDt4WyCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAlkqQLAjSw+GZSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgQ7eA8ggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJZKkCwI0sPhmUhgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIEO3gPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACWSpAsCNLD4ZlIYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACBDt4DyCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAlkqQLAjSw+GZSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgQ7eA8ggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJZKkCwI0sPhmUhgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIEO3gPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACWSpAsCNLD4ZlIYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACBDt4DyCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAlkqQLAjSw+GZSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCA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GT9O0rzce+qtExglWe9BsW+7KomtU/YA1YQAAQIECBAgQIDAGy2wb4h8310E32gsgxu0wL5rdN92gx6s4l65gGDHKyd2AwIECBAgQIAAAQIECBB4mQJNsXguyPEPWVafZTRdpZw+zniWjGYv8276+vEC+wY2yj0TOEWS9seXpQcCBAgQIECAAAECBK5WYM/d/IpinNauf1c7N+72SgT2DyntuSPmK6lSp9dFQLDjusyUOgkQIECAAAECBAgQIHBDBZrxLIvT+zm7/R9SP36U5eh+RtNlyukTQY5rsSb2DWK87HbXAkeRBAgQIECAAAECBG6OQDFK2j12/du33c2RM9LBCey3M2WRcdp4NOngpu+aFiTYcU0nTtkECPxwgbZcpmgmP7wDnyRAgAABAgQIEHilAvXkvA9yzE8/yfzkH7M6/CLVo2XKR08y/rMdOV4p/mvtfN9gx2st0s0JECBAgAABAgQIEPgXAvvuvrfvbn77tjMVBF6XwH7BjsRafl0z9Cbet/gf/r//Zef+pcv1oxRPRxlPT19osPjoy1STo4zqWy9sN1/ez+jpaUbzkxe2m/3sT5kU76aqj17cbvHHTJ68n2p58MJ201/9IYfrj1Lu+IHudP77HD76OGXd/aL8jlfRZvrr3+do8fMUbfeL8ttfbZrM5p/k6OEvUjTd/7F9R7tRndkv/pCj+S9TpPvLrO9o164zW/wxx1/+8oVjbQ6WmX/85xzPf/Hids0ii/nnOXr4sxe2q09mWX74IEeLv3lxu3qa1fRpDp98+MJ26zvnqd+d5mD53ovb1WdpzleZnL3zwnard5+kPU0mq7de2K5fy2ejjC9evJbb0Tp5r8jB4icp61up6pMU60nK9UHK+iDl9rpt64znd1O04zfx94drNablyYPMR39IsRqlKWepi2dpcpG6uEjTHf1787TFIsUH6zS3i6QtU7SX53L79dfn9tNlqvVpinaUop2kS1YWmaRsD/qvy0xStAdp36037ZpRymaUoh7119882maRarntL9ULf++4VviKJUCAAAECBAj8SIH5yaepT84zv/27zG79NvXoUapH81QPzzJ6lIye/sgb+DgBAgQIECBAgAABAgQI/ACBfcPX+7bbNwDyA0r1EQIvRWDfNbpvYGPf/l5K8Tp5wwWK//F/++92BjuaKimnuyW6PEe1x24y9SSpnu3u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"} \ No newline at end of file diff --git a/base_envs_set/02_Underwater_parkour_+_Fish.json b/base_envs_set/02_Underwater_parkour_+_Fish.json new file mode 100644 index 0000000000000000000000000000000000000000..a37178802290b75aaddd8e5994cc2fc880f4ae24 --- /dev/null +++ b/base_envs_set/02_Underwater_parkour_+_Fish.json @@ -0,0 +1 @@ +{"terrain":{"ground":[{"x":9.333333333333334,"y":3.3333333333333335},{"x":9.8,"y":3.209908743699392},{"x":10.266666666666667,"y":3.1588394006093345},{"x":10.733333333333334,"y":3.1406256635983785},{"x":11.2,"y":3.134439845879873},{"x":11.666666666666666,"y":3.1325269867976506},{"x":12.133333333333333,"y":3.132484891017278},{"x":12.6,"y":3.1344611128171285},{"x":13.066666666666666,"y":3.1416832943757376},{"x":13.533333333333333,"y":3.16580202182134},{"x":14,"y":3.245261498292287},{"x":14.466666666666667,"y":3.4983922799428306},{"x":14.933333333333334,"y":4.21616903146108},{"x":15.4,"y":5.6628646453221645},{"x":15.866666666666667,"y":6.688059957822164},{"x":16.333333333333332,"y":5.870976980527242},{"x":16.8,"y":5.668303259213765},{"x":17.266666666666666,"y":5.690506513913473},{"x":17.733333333333334,"y":5.705511053403219},{"x":18.2,"y":5.710653074582417},{"x":18.666666666666668,"y":5.712206228574117},{"x":19.133333333333333,"y":5.712642057736715},{"x":19.6,"y":5.7127561171849575},{"x":20.066666666666666,"y":5.712887533505757},{"x":20.533333333333335,"y":5.713553198178609},{"x":21,"y":5.716574247678121},{"x":21.46666666666667,"y":5.729145963986715},{"x":21.933333333333334,"y":5.7753472884496055},{"x":22.4,"y":5.890316160519918},{"x":22.866666666666667,"y":6.000197370847067},{"x":23.333333333333332,"y":6.0048846801122036},{"x":23.8,"y":5.5288730223973594},{"x":24.266666666666666,"y":1.240472181638082},{"x":24.733333333333334,"y":-0.577623407046},{"x":25.2,"y":-0.666175119082133},{"x":25.666666666666668,"y":-0.6893307129542032},{"x":26.133333333333333,"y":-0.7243610779444376},{"x":26.6,"y":-0.7855373779932657},{"x":27.066666666666666,"y":-0.895895806948344},{"x":27.533333333333335,"y":-1.0939239899317421},{"x":28,"y":-1.422100488344828},{"x":28.46666666666667,"y":-1.8699036041895551},{"x":28.933333333333334,"y":-2.323619882265727},{"x":29.400000000000002,"y":-2.6509281555811564},{"x":29.866666666666667,"y":-2.8345638672510782},{"x":30.333333333333332,"y":-2.9414425293604536},{"x":30.8,"y":-3.04517940680186},{"x":31.266666666666666,"y":-3.1426968018213906},{"x":31.733333333333334,"y":-3.325470773379008},{"x":32.2,"y":-3.974591104189555},{"x":32.666666666666664,"y":-4.6616485993067425},{"x":33.13333333333333,"y":-5.726217691103618},{"x":33.6,"y":-7.133393136660257},{"x":34.06666666666667,"y":-8.27699665228526},{"x":34.53333333333333,"y":-8.862144509951275},{"x":35,"y":-9.08290027777354},{"x":35.46666666666667,"y":-9.153085366884866},{"x":35.93333333333334,"y":-9.172618905703228},{"x":36.4,"y":-9.176883737246197},{"x":36.86666666666667,"y":-9.177011148134866},{"x":37.333333333333336,"y":-9.17624515692393},{"x":37.8,"y":-9.17544254461924},{"x":38.266666666666666,"y":-9.174776498476664},{"x":38.733333333333334,"y":-9.174247018496196},{"x":39.2,"y":-9.173851815859475},{"x":39.666666666666664,"y":-9.173944131533304},{"x":40.13333333333333,"y":-9.180862466494244},{"x":40.6,"y":-9.288385812441508},{"x":41.06666666666667,"y":-9.696114389101663},{"x":41.53333333333333,"y":-9.75365528265635},{"x":42,"y":-9.75307087103526},{"x":42.46666666666667,"y":-9.732889596621195},{"x":42.93333333333334,"y":-9.638307992617289},{"x":43.4,"y":-9.263916055361431},{"x":43.86666666666667,"y":-8.435874978701275},{"x":44.333333333333336,"y":-7.800293771425882},{"x":44.8,"y":-7.593754617373148},{"x":45.266666666666666,"y":-7.617768899599711},{"x":45.733333333333334,"y":-8.216587869326272},{"x":46.2,"y":-8.352293435732523},{"x":46.666666666666664,"y":-8.35421909491221},{"x":47.13333333333333,"y":-8.360868112246195},{"x":47.6,"y":-8.402732888857525},{"x":48.06666666666667,"y":-8.617482034365334},{"x":48.53333333333333,"y":-9.080363504091899},{"x":49,"y":-9.354827920595806},{"x":49.46666666666667,"y":-9.422508279482525},{"x":49.93333333333334,"y":-9.434505502382915},{"x":50.4,"y":-9.436425820986429},{"x":50.86666666666667,"y":-9.436451760927834},{"x":51.333333333333336,"y":-9.436096994082131},{"x":51.800000000000004,"y":-9.45681385199229},{"x":52.266666666666666,"y":-9.726277963320413},{"x":52.733333333333334,"y":-9.904393808046976},{"x":53.2,"y":-9.65846714178721},{"x":53.666666666666664,"y":-9.590531961123148},{"x":54.13333333333333,"y":-9.573213998476664},{"x":54.6,"y":-9.542654458681742},{"x":55.06666666666667,"y":-9.437410775820414},{"x":55.53333333333333,"y":-9.266098062197369},{"x":56,"y":-9.1656418244044},{"x":56.46666666666667,"y":-9.115448800722756},{"x":56.93333333333334,"y":-9.101476327578226},{"x":57.4,"y":-9.098640481630962},{"x":57.86666666666667,"y":-9.098732034365337},{"x":58.333333333333336,"y":-9.101000253359476},{"x":58.800000000000004,"y":-9.108612863222756},{"x":59.266666666666666,"y":-9.131215707461038},{"x":59.733333333333334,"y":-9.191809884707133},{"x":60.2,"y":-9.332454721132915},{"x":60.666666666666664,"y":-9.594408456484476},{"x":61.13333333333333,"y":-9.953209726015725},{"x":61.6,"y":-10.3121391693751},{"x":62.06666666666667,"y":-10.595253793398538},{"x":62.53333333333333,"y":-10.78054432074229},{"x":63,"y":-10.872232858339945},{"x":63.46666666666667,"y":-10.736898080507913},{"x":63.93333333333334,"y":-9.474282876650491},{"x":64.4,"y":-7.707264749209085},{"x":64.86666666666667,"y":-7.077321664492289},{"x":65.33333333333333,"y":-6.199675790468851},{"x":65.8,"y":-4.901987497011821},{"x":66.26666666666667,"y":-3.9802345673243202},{"x":66.73333333333333,"y":-3.6136635224024456},{"x":67.2,"y":-3.433818093935648},{"x":67.66666666666667,"y":-2.2865753571192426},{"x":68.13333333333334,"y":-2.058465234438578},{"x":68.6,"y":-2.0542183319727583},{"x":69.06666666666666,"y":-2.0530273834864294},{"x":69.53333333333333,"y":-2.0524559418360395},{"x":70,"y":-2.0519386688868204},{"x":70.46666666666667,"y":-2.050130883852641},{"x":70.93333333333334,"y":-2.036684838930766},{"x":71.4,"y":-1.9280064026514685},{"x":71.86666666666667,"y":-1.20802997748057},{"x":72.33333333333333,"y":0.6348844130833946},{"x":72.8,"y":1.4762864669164022},{"x":73.26666666666667,"y":1.6266027053197225},{"x":73.73333333333333,"y":1.702006491025289},{"x":74.2,"y":1.8946645339330037},{"x":74.66666666666667,"y":2.4382211287816364},{"x":75.13333333333334,"y":3.550568779309591},{"x":75.6,"y":4.82282768090566},{"x":76.06666666666666,"y":5.591314276059469},{"x":76.53333333333333,"y":5.893812330563863},{"x":77,"y":5.992696913083394},{"x":77.46666666666667,"y":6.023187406857808},{"x":77.93333333333334,"y":6.032496603329976},{"x":78.4,"y":6.035351904233297},{"x":78.86666666666667,"y":6.0362420638402305},{"x":79.33333333333333,"y":6.036526449521382},{"x":79.8,"y":6.036618002255757},{"x":80.26666666666667,"y":6.036650999387105},{"x":80.73333333333333,"y":6.036662634213766},{"x":81.2,"y":6.0366696914037075},{"x":81.66666666666667,"y":6.0366748412450155},{"x":82.13333333333334,"y":6.036676748593648},{"x":82.6,"y":6.036680563290914},{"x":83.06666666666666,"y":6.036682089169821},{"x":83.53333333333333,"y":6.036687620480855},{"x":84,"y":6.036692198117574},{"x":84.46666666666667,"y":6.036697729428609},{"x":84.93333333333334,"y":6.036700781186422},{"x":85.4,"y":6.036711653073629},{"x":85.86666666666667,"y":6.036722334225972},{"x":86.33333333333333,"y":6.036735113461813},{"x":86.8,"y":6.036757429440817},{"x":87.26666666666667,"y":6.036781080563863},{"x":87.73333333333333,"y":6.036812742551168},{"x":88.2,"y":6.036865003903706},{"x":88.66666666666667,"y":6.036937483151753},{"x":89.13333333333334,"y":6.037039907773336},{"x":89.6,"y":6.037188299496968},{"x":90.06666666666666,"y":6.037411840756734},{"x":90.53333333333333,"y":6.037754019101461},{"x":91,"y":6.0382819732030235},{"x":91.46666666666667,"y":6.039124639829},{"x":91.93333333333334,"y":6.040500601132711},{"x":92.4,"y":6.0427831252415976},{"x":92.86666666666667,"y":6.046648176511129},{"x":93.33333333333333,"y":6.053301008542379},{"x":93.8,"y":6.0649036010106405},{"x":94.26666666666667,"y":6.085284002621968},{"x":94.73333333333333,"y":6.12105537255605},{"x":95.2,"y":6.18308044274648},{"x":95.66666666666667,"y":6.2872756560643515},{"x":96.13333333333334,"y":6.451429327329},{"x":96.60000000000001,"y":6.684192617734274},{"x":97.06666666666666,"y":6.97951885064443},{"x":97.53333333333333,"y":7.346581228574117},{"x":98,"y":7.822168310483296},{"x":98.46666666666667,"y":8.445618017514548},{"x":98.93333333333334,"y":9.245919378598531},{"x":99.4,"y":10.011681326230367},{"x":99.86666666666667,"y":10.36552501519521},{"x":100.33333333333333,"y":10.39780040582021},{"x":100.8,"y":10.363648184140523},{"x":101.26666666666667,"y":10.347531851132711},{"x":101.73333333333333,"y":10.348792990048725},{"x":102.2,"y":10.358712728818258}],"ceiling":[{"x":9.333333333333334,"y":23.333333333333332},{"x":9.8,"y":23.807982953389487},{"x":10.266666666666667,"y":23.973135693868002},{"x":10.733333333333334,"y":24.027107175191244},{"x":11.2,"y":24.044468434651694},{"x":11.666666666666666,"y":24.050075848897297},{"x":12.133333333333333,"y":24.051957829793295},{"x":12.6,"y":24.05279115041097},{"x":13.066666666666666,"y":24.05380719502767},{"x":13.533333333333333,"y":24.056625684102375},{"x":14,"y":24.06609567006429},{"x":14.466666666666667,"y":24.100306447347005},{"x":14.933333333333334,"y":24.239140637715657},{"x":15.4,"y":24.88159097035726},{"x":15.866666666666667,"y":27.69610856374105},{"x":16.333333333333332,"y":31.303751691182455},{"x":16.8,"y":32.13945954640707},{"x":17.266666666666666,"y":32.26023896535238},{"x":17.733333333333334,"y":32.283462079366046},{"x":18.2,"y":32.28896134694418},{"x":18.666666666666668,"y":32.29000504811605},{"x":19.133333333333333,"y":32.28963197072347},{"x":19.6,"y":32.288651593526204},{"x":20.066666666666666,"y":32.287279065450036},{"x":20.533333333333335,"y":32.28569367726644},{"x":21,"y":32.28462556203206},{"x":21.46666666666667,"y":32.28736146291097},{"x":21.933333333333334,"y":32.30748322804769},{"x":22.4,"y":32.386000378926596},{"x":22.866666666666667,"y":32.53605607350667},{"x":23.333333333333332,"y":32.64560654958089},{"x":23.8,"y":33.09419663747152},{"x":24.266666666666666,"y":36.55601533253988},{"x":24.733333333333334,"y":37.484608777364095},{"x":25.2,"y":37.50573914845785},{"x":25.666666666666668,"y":37.49536317189535},{"x":26.133333333333333,"y":37.483282788594565},{"x":26.6,"y":37.46988557179769},{"x":27.066666666666666,"y":37.44814484914144},{"x":27.533333333333335,"y":37.38789094289144},{"x":28,"y":37.21680024464925},{"x":28.46666666666667,"y":36.86248353322347},{"x":28.933333333333334,"y":36.35090974171956},{"x":29.400000000000002,"y":35.778842480977374},{"x":29.866666666666667,"y":35.21154816945394},{"x":30.333333333333332,"y":34.666124280293786},{"x":30.8,"y":34.0455706914266},{"x":31.266666666666666,"y":33.03809846242269},{"x":31.733333333333334,"y":31.530382855733237},{"x":32.2,"y":30.49499543507894},{"x":32.666666666666664,"y":29.924418958028156},{"x":33.13333333333333,"y":29.513033612569174},{"x":33.6,"y":29.093512280782065},{"x":34.06666666666667,"y":28.694357617696127},{"x":34.53333333333333,"y":28.404671796162923},{"x":35,"y":28.215756543477376},{"x":35.46666666666667,"y":28.0889186223348},{"x":35.93333333333334,"y":28.00077699025472},{"x":36.4,"y":27.938692792256674},{"x":36.86666666666667,"y":27.89498551686605},{"x":37.333333333333336,"y":27.8644069035848},{"x":37.8,"y":27.843178876241048},{"x":38.266666666666666,"y":27.828547986348468},{"x":38.733333333333334,"y":27.818532117207845},{"x":39.2,"y":27.81181290944417},{"x":39.666666666666664,"y":27.809099133809408},{"x":40.13333333333333,"y":27.837865002950032},{"x":40.6,"y":28.28971818288167},{"x":41.06666666666667,"y":30.377138074239095},{"x":41.53333333333333,"y":31.248372968037923},{"x":42,"y":31.31919892628988},{"x":42.46666666666667,"y":31.318619092305504},{"x":42.93333333333334,"y":31.295710309346518},{"x":43.4,"y":31.1953639348348},{"x":43.86666666666667,"y":30.891453107198082},{"x":44.333333333333336,"y":30.549882825215658},{"x":44.8,"y":30.419692548116046},{"x":45.266666666666666,"y":30.375841840108237},{"x":45.733333333333334,"y":30.00728791554769},{"x":46.2,"y":29.254969342549643},{"x":46.666666666666664,"y":29.19689973195394},{"x":47.13333333333333,"y":29.217015393575032},{"x":47.6,"y":29.352666028340657},{"x":48.06666666666667,"y":29.971137555440265},{"x":48.53333333333333,"y":31.226073010762533},{"x":49,"y":32.01624711354574},{"x":49.46666666666667,"y":32.213012250264484},{"x":49.93333333333334,"y":32.247863324483234},{"x":50.4,"y":32.253458722432455},{"x":50.86666666666667,"y":32.25271714528402},{"x":51.333333333333336,"y":32.23581422170003},{"x":51.800000000000004,"y":32.06145051320394},{"x":52.266666666666666,"y":30.839837964375814},{"x":52.733333333333334,"y":29.452714093526204},{"x":53.2,"y":29.304491742451987},{"x":53.666666666666664,"y":29.30406220753988},{"x":54.13333333333333,"y":29.27416795094808},{"x":54.6,"y":29.125727399190268},{"x":55.06666666666667,"y":28.490151532491048},{"x":55.53333333333333,"y":26.607606824239095},{"x":56,"y":24.428346570332845},{"x":56.46666666666667,"y":23.47854913075765},{"x":56.93333333333334,"y":23.236027463277182},{"x":57.4,"y":23.18469098409017},{"x":57.86666666666667,"y":23.17469533284505},{"x":58.333333333333336,"y":23.173382504781088},{"x":58.800000000000004,"y":23.175022061665853},{"x":59.266666666666666,"y":23.180940755208333},{"x":59.733333333333334,"y":23.19765961964925},{"x":60.2,"y":23.24051316579183},{"x":60.666666666666664,"y":23.33584950764974},{"x":61.13333333333333,"y":23.4992925008138},{"x":61.6,"y":23.692253812154135},{"x":62.06666666666667,"y":23.851485951741537},{"x":62.53333333333333,"y":23.954210980733237},{"x":63,"y":24.00002778371175},{"x":63.46666666666667,"y":23.865675481160483},{"x":63.93333333333334,"y":22.73158582051595},{"x":64.4,"y":21.347505791982016},{"x":64.86666666666667,"y":21.0700893809398},{"x":65.33333333333333,"y":21.034465738137563},{"x":65.8,"y":21.053749065597852},{"x":66.26666666666667,"y":21.130604984362922},{"x":66.73333333333333,"y":21.167213280995686},{"x":67.2,"y":21.023698165019354},{"x":67.66666666666667,"y":18.50333398183187},{"x":68.13333333333334,"y":17.606333859761556},{"x":68.6,"y":17.58719170888265},{"x":69.06666666666666,"y":17.58633187611898},{"x":69.53333333333333,"y":17.58591340382894},{"x":70,"y":17.585645612080892},{"x":70.46666666666667,"y":17.585970242818195},{"x":70.93333333333334,"y":17.590872128804524},{"x":71.4,"y":17.63311150868734},{"x":71.86666666666667,"y":17.939624150594074},{"x":72.33333333333333,"y":18.904247029622397},{"x":72.8,"y":19.274834950764973},{"x":73.26666666666667,"y":19.31397031148275},{"x":73.73333333333333,"y":19.26741517384847},{"x":74.2,"y":19.093888791402183},{"x":74.66666666666667,"y":18.596391614278158},{"x":75.13333333333334,"y":17.57372430165609},{"x":75.6,"y":16.395191129048666},{"x":76.06666666666666,"y":15.68502114613851},{"x":76.53333333333333,"y":15.407248624165852},{"x":77,"y":15.316749127705892},{"x":77.46666666666667,"y":15.28888619740804},{"x":77.93333333333334,"y":15.28039582570394},{"x":78.4,"y":15.277800687154134},{"x":78.86666666666667,"y":15.277004559834799},{"x":79.33333333333333,"y":15.276756223042806},{"x":79.8,"y":15.276685269673665},{"x":80.26666666666667,"y":15.276664670308431},{"x":80.73333333333333,"y":15.276662381490071},{"x":81.2,"y":15.276667340596518},{"x":81.66666666666667,"y":15.276669629414876},{"x":82.13333333333334,"y":15.27667916615804},{"x":82.6,"y":15.276689465840658},{"x":83.06666666666666,"y":15.276697095235189},{"x":83.53333333333333,"y":15.276710828145346},{"x":84,"y":15.276726086934408},{"x":84.46666666666667,"y":15.276747830708821},{"x":84.93333333333334,"y":15.276773007710775},{"x":85.4,"y":15.27680466969808},{"x":85.86666666666667,"y":15.27684472401937},{"x":86.33333333333333,"y":15.2769011815389},{"x":86.8,"y":15.27697099049886},{"x":87.26666666666667,"y":15.277062543233235},{"x":87.73333333333333,"y":15.277189191182455},{"x":88.2,"y":15.277354367574056},{"x":88.66666666666667,"y":15.277582867940268},{"x":89.13333333333334,"y":15.277885754903158},{"x":89.6,"y":15.278304608662923},{"x":90.06666666666666,"y":15.27887986501058},{"x":90.53333333333333,"y":15.27967332204183},{"x":91,"y":15.280778821309408},{"x":91.46666666666667,"y":15.282334836324056},{"x":91.93333333333334,"y":15.284551175435384},{"x":92.4,"y":15.287746365865072},{"x":92.86666666666667,"y":15.29243958791097},{"x":93.33333333333333,"y":15.299480756123861},{"x":93.8,"y":15.310258801778158},{"x":94.26666666666667,"y":15.327096875508627},{"x":94.73333333333333,"y":15.353780301411946},{"x":95.2,"y":15.396169217427571},{"x":95.66666666666667,"y":15.462697156270345},{"x":96.13333333333334,"y":15.564569791158041},{"x":96.60000000000001,"y":15.716108640034994},{"x":97.06666666666666,"y":15.97951885064443},{"x":97.53333333333333,"y":16.346581228574117},{"x":98,"y":16.822168310483296},{"x":98.46666666666667,"y":17.445618017514548},{"x":98.93333333333334,"y":18.24591937859853},{"x":99.4,"y":19.011681326230367},{"x":99.86666666666667,"y":19.36552501519521},{"x":100.33333333333333,"y":19.39780040582021},{"x":100.8,"y":19.363648184140523},{"x":101.26666666666667,"y":19.34753185113271},{"x":101.73333333333333,"y":19.348792990048725},{"x":102.2,"y":19.358712728818258}],"parkourConfig":{"dim1":0,"dim2":-1,"dim3":0,"smoothing":10,"waterLevel":1},"creepersConfig":{"width":0.2,"height":0.2,"spacing":5,"type":"Swingable"}},"agents":[{"morphology":"fish","name":"Flipper","age": "adult","path":"policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42","init_pos":{"x":4.66681588107569,"y":4.529333333333334}},{"morphology":"fish","name":"Nemo","age": "adult","path":"policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3","init_pos":{"x":4.68006700167504,"y":17.24838193510678}},{"morphology":"fish","name":"Dorry","age": "adult","path":"policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7","init_pos":{"x":4.68006700167504,"y":12.704268032259215}},{"morphology":"fish","name":"Oscar","age": "adult","path":"policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9","init_pos":{"x":4.68006700167504,"y":8.692167529746653}}],"description":{"EN": {"name":"Underwater parkour + Fish","text":"This parkour is totally underwater, allowing fish to evolve in it. We can even organize a race between several fish!"}, "FR": {"name":"Parkour immergé + Poissons","text":"Ce parkour est totalement sous l'eau et peut donc accueillir des poissons. On peut même organiser une course entre plusieurs poissons !"}},"image":"data:image/octet-stream;base64,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BoMBJwQQQAABBBBAAAEEEEAgbAI0doSNNj4D3/LAnXrxK79UT0ZOfBZA1ggggAACCCCAAAIIIIAAAggggAACCERIYPnyJzTK0KhKrmOJkDjLIIAAAggggAACCCCQnAI0diTnvn9m1ZU71+mUD97UG//0Q1QQQAABBBBAAAEEEEAAAQQQQFpvPv4AACAASURBVAABBBBAoBeBvQc2qnXHAk0vK8QKAQQQQAABBBBAAAEEEAibAI0dYaONv8DTF/xJLUWV2jp5RvwlT8YIIIAAAggggAACCCCAAAIIIIAAAghEWMDh7NFrr/5cN46okJHrWCKsz3IIIIAAAggggAACCCSPAI0dybPXvVZ606+/qvm336fO7IJexzIAAQQQQAABBBBAAAEEEEAAAQQQQAABBKT33vuLRvjqVJXD1cY8DwgggAACCCCAAAIIIBAeARo7wuMad1Er9mzS2BXz9No/3xN3uZMwAggggAACCCCAAAIIIIAAAggggAAC0RLYV/2hmrfN1znlXMcSrT1gXQQQQAABBBBAAAEEEl2Axo5E3+Eg65v6+p/VkVeszWddFuQMhiGAAAIIIIAAAggggAACCCCAAAIIIICA02XXq/N/phuHV8hkNAKCAAIIIIAAAggggAACCIRcgMaOkJPGZ8AbHvymXr/l39WeVxKfBZA1AggggAACCCCAAAIIIIAAAggggAACURJYseIpDfMe1mCuY4nSDrAsAggggAACCCCAAAKJLUBjR2Lvb1DVle7foklLnterc34c1HgGIYAAAggggAACCCCAAAIIIIAAAggggMDHAvtrNqtx6zydy3UsPBYIIIAAAggggAACCCAQBgEaO8KAGm8hz3rzL+rJyNams2fHW+rkiwACCCCAAAIIIIAAAggggAACCCCAQNQFXG6H5r1yn24cMUhmrmOJ+n6QAAIIIIAAAggggAACiSZAY0ei7Wg/6rn+99/Roi9+T0cKy/sxO/RTMo80auiWFdo47arQByciAggggAACCCCAAAIIIIAAAggggAACYRBYufIZDXEf1JDc3DBEJyQCCCCAAAIIIIAAAggkswCNHcm8+5KKa3bIf2LHvDvujxmJS/72S9VXjtams6+MmZxIBAEEEEAAAQQQQAABBBBAAAEEEEAAgZMJHDi4RfVbXtF5XMfCg4IAAggggAACCCCAAAIhFqCxI8Sg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fK6P+kxScZeemmifZ9ymsfaupytrWdulWMMf1jYt1lDHz1uzVLdou9NHFBC122i1Yi4tlkdmitbd+VsNXveJvvjVv23ea2MPdCgu1NT35ypi1B2K7j6ksctTDwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgctSgGBHPV5beVGRijLTVZSRYfxZnJ6qoqysykqO9pKrg0lZRRb5upvqvIJfVpKGndyjL4InyTEhSTNid2rNU2+pwKeDUavbnu8UsnqhdoydoSODxtVav/2pA0aQw/pT6O55ts3KQGX6+OuWt59WUmBPVdjZaduEmbXWasoBHU4ekPXmjmVz5info1VTLkVtBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEELgsBgh02vKbykhLlxcUoOWKHKkqKVVFWZswymSQXBzu5mC1yNVv/LrmaTbK3k1ILLIrJtijY1051jXYMPLJLxY5OOtypp8Z+v0Ir2/TRsS79FThipK7fukQtU+OMWzrSfTtVu3v/43sVEBlhhDlyvNoqJihYMUEDle3te94cayuX3ttXavX03ymhU28bNJp2SP/NS+SdGK19w6cprX3npl2M6ggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCDRzAYId1byg0vw85cbGGK1V8uLjjFEuDiaVV1jU3sMkF7NJrg7Vv92GBDumbVqiTcGj1D36iMrszfq+62CVxyRpfHSEMoeM1Z5bH71gYVNFxdkWK2fCHOltAxVrhDmCldvSp9qNdj60zbi146X//NBsvqr3vThbpY4u+vSJN5vNntgIAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACl0KAYMc56kWZGcqzhjlio1WQlmo88XCyk6eTRZ5OJkVnW1RablEfH7ta31V9gx1tMlM0+PBORQZ00zWxUQobNkm9Th5UtxOHtSRgiCJadpTf9WPkEdBR5tIS+UdZW6ycCXMk+3c7ezNHsApsbGXSa0eYRi55Qx8/+bay2vjVeq6mHuAftcdox3J0wGhFjL6zqZejPgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAs1a4KoPdmQePaz85AQVZ6SrOCfHaK9iDXF4OkmeziY5nJPhOJre9MGOAcd2y6mkWJ0STur7Adfrmrjjst7GsbPXEOU6uyshrVjtkmI1yN2soIwYxXfpVxnmKHJtUecv28RF/5C1V0xCx97aP3xqnec35gSnwlxNmz9X2ybcp5iuwY1ZmloIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghclgJXXbCjICVZBcmJKkhOUkFSgirKy2VvZ1JLI8hxJtRhZ6r6XV6MYMeN3y8zFs9s4aW2GUk6FtBNxwOC5Jccpw4psWqflqCDLfy0x72Dymc/pQov73p/8dxyM3TT//6gDbf+WgM3fqFvZ/2l3rUaY6L15pBcLx9FjLyjMcpRAwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgcte4KoJdsSsC6sMcphMJrk7Sh6OUkKuRR08TGrnXk2a45xX3NTBDu/sdN34/VIVOLupzGxWfJv2cisskLU9S1xbf8X5+CnOx1/ppXY6kWlR0O0zZHZ1rfeXsHvEOrVJOKEfbnxId77+K62651nltGpX73oNmWhtCWNtwxI24w8NKcNcBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEriiBqybYcXLpl3IvyVYrF2ug40yIo7hcOphS0WyCHXeHLZJfcqxSWvmowMnVCHPEG2EOP1msPWLOfrKLLDqRKQXdNr1BwY5xn7+kY/1HKabbQIWsXqjclj46NHTSRf+Ct4k/rvGf/kvf3v+8sr3bX/T1G3vBlqlxSm/XsbHLUg8BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBA4CoUuOqCHYGePwUkmluwY+57f5HJYlGWe0vluHuqyMm5yq9kabmUXyq5t/eTyd6+Xl9b+/IytT91QLHX9JdkknN+tjwzkpTs361e9Royqd3pI0YLlvwW9W8r05D1m2Luh8/Ml84J4zTFGtREAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEELjyBa6qYIepIEceDpazbVhMKrdcuhs7Cst++nK5mM/8fdby92Vtx5Lr5qHUlm1kLi8zWq8YLVja+lfe2pFl3NjRsFYsQXs3yjf6kDbd9FjlRqa/+qiWz/6r8jxbX7RvfmjYApkqKrR18uyLtiYLIYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggcLkIXDXBjsyooypISlJBUrxKCwqM9+PiaKfCkgq19zDJ1/2nmzyqe3lH0y0qLbeoj49dre83tcCimGyLgn3tVFVlawsY640h1mfWMdbPrRu+lGdulvJc3VXi4KSE1u2V2aKV/FJi5ZORUhnwONSig47l2Cvo9hn1bsUy9otXdKL3MJ3qGVJ5lhEr3lOGT4AODx5f6/kaY8A1Bzar1/aVWj57nirs6nfzSGPsgxoIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgg0V4GrJthx7gsoyclWflKi8uJjlB8Xo4oKi+ztTPJ00pkfZ5Psq0hjNHWwY9qmJSpxcFSJ2VFFji5G6sOlqEA7ew1RkaOz/FLi1DYxVq0SE3SsdaByp8xQfJ9hKnF2rdP3y7GoQNNffUSLnn5X5WbHyrkBkbvVc9cahd39+zrVq8/gFhlJmjp/rtbe9bSS/YPqU4I5CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIXPECV2Ww4+dvNSf6hIoyMpQXG62irCzjsaeTSZ7OZ/50PHuZxMUIdkT7dpRzSbFa5mbqhN81sq8o14CjEdrZa6j2tOmik1mSu6urhvl5q3PcMQVE7VZ85z6KCRqomK7BKnJrUeuX1npThjXEseHWxy8Ye89LD+qrh19UoXvLWus0ZMCET/5l7PtgyOSGlGEuAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACV7QAwY6fvd7irEzlxcUoN/a0ClKSjafuTnbydLQoq1hN2orFemNHeJ9hunbv9/pu4GhN2BamVcMmy76iQn32bVeUfUttDL1JvqPHy97RydibfVmpAiIjjKCGNeSR7NdVsWdDHvktWlX55R311euKDQrW8T4jLnh+3bK3lewXpGPBo5vsix+86St5psXruyqCJU22KIURQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBC4DAUIdtTw0soK8pUbF6O82BjjT+vHzmSSh5PkapZcHKx/muRkvrBIaoFFMdkWBfvaWTuqXPA5mFKh4nKj24oxxvqxBjvWDRmn4fu26MA1feWRn6PApGgt6j1ecTkW3ZJ/Wj3MZQqfOEtJAd0vqGmyVJwJeETuln/UbmX6BCgmKNi4ySPXy8cYby4t0YyXH9Snv3lLJU4XtnDpeGSHuu7bZLRIaYqP3/G9Gr7yfS2bM0+Fbp5NsQQ1EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQuGIECHbY+CorysqUvGubCpISZXZxVVFGmspLSozZ9nYmuTiY5Gq2yMUsuTqYlF9a/2BHYOJpuRXla2fPIeq9Y7MSLM6KmHCf2g0JVedDWxUatlD7h92oA6E31Lh7a4jix5s8clv6GCEP66dtbKTW3fFklXPtystkbcfy+eOvq9jF3UYd24Y5FeZp6vtztX3cPUbrGD4IIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggULMAwY4GfENK83JVlJmhoox0FWemqyg9TSV5eedVdHI4cxvHzz+lZRWqsJz57Y9jHtv1tT7uM95ovTL90Dq9MegWqahYv07YoQO3PabT3Qcb4z2yUoxwR7nZwbi9o8C9Za2naH/qoBHyGLz+E2V7t9f+4VONoEeGT8AFc0cueUPxnfsqqt91tdaty4CR37ypXM/Wihh1Z12mMRYBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIGrVoBgRyO/+oKUJGUcPqCyoiKVFxfJrV17yXRhM5bs45EqLy2VyWSSV/eexi5+8/Gf9eHkR5Tu1U4z1n+g7/uOUUrX/uptLtW1y9/RstnzVODhVbnj/j8sUffd641wx+lug2o9iamiQve89At9f9OjahtzTAGRESpzcDrTriUoWGm+nY0anQ9uVacj27X+9t/UWtPWAT13rlbgsQituuePtk5hHAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAle9AMGOS/QVOL74U5Xk5xnBjh73PWDs4qlfjdBHz7ynZP/u6rd5qZyK8rRj7AzjmTXE4Z18Wutve+K8HXc4ud+4veN090HaOXp6jacJPLZL3XZv0Jrpz1SOaxN//Ey7lsgImSwWI+CR2Km3xn36oj5+6n8qdXRusFCbhBOa9NHftWzOPGW17tDgehRAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDgahEg2HGJ3nRtwQ6vlFiNWfyaFj/6cuUOx3/2f0oM7KEDoTect2vH4gKFhC2Ue3aacXtHpo9/lae6dvn/lNq+s44OHFvlc++kaCPgYQ16WEMgJ3sPU8TI25UYeOZGkfp+pr4/V0cGjlVUv+vrW4J5CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIXJUCBDsu0WuvLdhh3da09/6o8In3K8Wvq7FLj6wUTZ0/V+tvf0JJAT0u2HmPXWs1ZO0ibZs4S8cGjLrg+YyXH9KSB19QgUerWk/tlRpXGfJwzc2sbNcS37lvrXPPHRCyeqHsy8u0ZfKcOs1jMAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghIBDsu0bfAlmDHgE1fyb6iTLtG3Vm5y86HtqrflmVGW5Nye4cLdt868ZRCwhYoq42fcXtHufnMGP/je9R72yqtuuePdT6xZ0aS/M/e5OGZnng25DFQsV0H1Firy8Et6hP+rZbNnqcKe3Od12UCAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACV7sAwY5L9A2wJdhhDWlct+xtff3Qv87bZciaD2VfWqItUx6odvdD13yk9qcOGuGOpMAeGr5yvrJad9ChIRMbdGL37FSjVYv1xzvxlGKDghUTNNAIe1TY2VfWbpGZbNwusvaO3yo5oFuD1mQyAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACV6sAwY5L9OZtCXZYt3bLO7/T91MfVppvp/N2euMHf9KxAaMV2X9ktSfofChc1lYoB0OmqOeOMK2Y9WfltvRptBO75mVWhjzaxRxRTNczAQ/rz+jF/1Zix146EDql0dajEAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAlebAMGOS/TGbQ12DNrwucrtzdpz/a3n7bR14klNWTjPaMmS2cav2lO4Z6Vq/Gf/p7axx7Tw9x+owKNVk5zYuSBX/lFnbvLotWOVCtxbaePNjxk3ehQ7uzXJmhRFAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDgShcg2HGJ3nD6oQOVK3v36mP8/Ze/m6xvHvyn4rr0rXzmExel0LAPtPSBf1yw05471yjw6A6tuve5Gk9hvbWjTcJJuWenKXziTEV3H9Jkp/Y7sV/XLntb+0ZMU9vYSCPoEd+p99mWLcEqdPNssrUpjAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAwJUmQLCjGb3R2958UmH3/EF5nm3O29Vtb/1W6297Qpk+/hfs9vpv3lJ+i1baNfquak9yx39+rdV3/15uOekKDVtgtErZOebuRj+5Y1GBps5/TjvH3q3T3QYZ9e3LShVw9iYP/8gIpXboWtmuJb+Fd6PvoS4FOx3ZrlM9htZlCmMRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBC4qAIEOy4qd82LVRfsGLLuYxU7uxu3YPz8U1WY4twx7U4f0eD1n2r57L8av3YoKVRo2EJ5ZKUofOIsZfgENJpAbSETk8VS2a4lIDJCmW38K0MeuV5tG20ftRVyyctS6OqFMpcUa8uUObrUAZPa9stzBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIGrV4BgRzN699UFO4xwxoZPtfz+M+GMn386nNivEd++q2Vz5qnQveV5j8+EQty0b8RN5/2+e8Q6haz5UOETZulY8OgGK5xpC7NTq+591uZafsf3KSAqwmjXktuyjWK7BhtBj6zWHWyuUdeBgcd2ydqaJrL/KO257pa6Tmc8AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACF1WAYMdF5a55seqCHdZZP7ZTyfb2rbLIgO+/lldKrDbc9uvzntfUxsU7Kdq4vcNa03p7R5mDY700Wiec1JQP5xnBksw2fvWq0f7UISPk4R+5W8WuHoo5G/LIaBtYr3pVTRq04TN1PLLDOGt8l76NVpdCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIINJUAwY6mkq1H3ZqCHdZbJvJbtNaB0CnVVh7/6YtK7NircoxPXJSGrfpA3/ziHzXuZsjaRfI7sd8IPCR27Fnnnd/4wZ90bMBoRfYfWee5VU1oG3NUAVG7jZs8ys0OZ0MeA5XWvnO96nulxikkbKEKPLyMM5Y4u9arDpMQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBC42AIEOy62eA3r1RTs6HDygPpvXqIV9/2p2goemcmaNn+u1t7xpJIDumvQd5+rws5eu6+/rdZTdjq8zbi949DQSdo3fGqt438cYG3nYl9aoi1THrB5Tl0Gtok/XhnyMFWUn23XMlDJ/kE2lQnau9E4184x03V48Hib5jAIAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACB5iJAsKO5vAlJNQU7rNuc/tpj+nbWX5Tbsk21u+5ycIv6hH+rZbPnadp7z+qHqQ8rzbeTTad0z06T9WYQyaTwiTOV38K7xnmdD21Vvy3LjBYs5fYONq3RkEHW1jHWWzz8o3bLqShfMUHBiuk6sMpbRuzLS41bOlqlxBi3dKT51u+2j4bsl7kIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgg0VIBgR0MFG3F+bcGO4SvnK7N1Bx0eMrHGVa3hjBaZyXLPStPXD79Y5x3227xUPXeuNsId0T2GVjnfIytFU+fP1frbf6OkgO51XqOhE1qmxhkhD2vLFrecdMUEDTRatsR36at2MUcVGrbACHxsG39fQ5diPgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAApdMgGDHJaO/cOHagh3+UXvUa/sqhd3zx1p3PWfedCUF9NCKmdW3bqmpSPtThxSyeoHirumvHWNnXDB0/Gf/p8TAHjoQekOte2nqAS0ykipDHoFHd8qxuNDYszWYwgcBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIHLWYBgRzN6e7UFO6xbnfHyQ1ry4D9V4OFV487v+vcv5ZGZoi9/+aqyWneo1ynNJcUKXb1A1uCEtZ1JRttAo07/H5bIO/m01t/2RL3qNsUk19xMha5eKJf8bCUG9lTrhBNqk3Ci8iYPa9uWCntzUyxNTQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBJpMgGBHk9HWvbAtwY5rl7+j1PZddHTg2GoX8EqJ1ZjFr+rw4AkKPLZLq+55tu6bOWdG993rFRK2UNsmzlRuSx9Z97Bs9rxawyUNWrQOk623dFhDHUeDx2jvtTdXznTNy5L/2XYtvtGHZQ13WNu1xAYFq9TRuQ4rMBQBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIFLI0Cw49K4V7mqLcEOa4ih257vtGb6M9XuvN+WpXIqyNOOcTM08ps3levZWhGj7mzQSVsln9aIFfPlHxWhVTOe1cnewxpUr7EmD17/qRFesd4oEt+5T7VlnQrzzrRriYyQtaWNNdzxY9Cj2MW9sbZDHQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBpVgGBHo3I2rJgtwQ5TRYXueekX+vKXr6nI1aPKBW/84M/aOfouJQX2kFNRvqbOf07bx91jtCVpyOe6pf9Vu9hjKjc7KHzCLCV06tWQcg2aa72VxHpLR14LbyPUUerkYnM9h5IiI+ThHxmhgKjdSuzYqzLkUeje0uY6DEQAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQKCpBQh2NLVwHerbEuywlrv+mzeNMEJk/5EXVPdMT9SET17QF796vfKZ3/F9Gr5yvpbNmadCN8867OinoT12rVWnw9u08r656nhku0LDFhqtXvaNmFaveg2ZZL2xJGT1Qu0YO0NHBo1rSCnZl5edCXicbdlibXNjvckjtutA5Xl6N6g2kxFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEGioAMGOhgo24nxbgx2dD4XL+rPujicvWL1P+Aq5Z6cpfOLM854Fb/pKnmnx+u7Wx+u849aJpzRl4fNaNnueMn38jfluOelGuMNksRhr5Xm2rnPduk6wLysx1myZGmfc0pHu26muJWodb23V8mPII6t1h7M3eQxUTqu2tc5lAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAo0tQLCjsUUbUM/WYIe5tEQzXvqFPn3yvypxcj1vxckfztO+ETcpvnOfC3Yy4ZN/Gb8/GDK5Tru84YM/K6r/SB0bMOqCeX23LFPv7auMcMepniF1qluXwb6njygkbIESOvXW9vH31mVqvcf6ndh3pmVL1G7lt/A+E/IIGihr4IMPAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACF0OAYMfFULZxDVuDHdZyo7/6txEyON5nRGV1j6xU3bDgz/r0ibeqXLFFRpKmzp+rtXc9rWT/IJt2NXTNR3IoKdLmG35R7Xjf6MMKXb1AcZ37ase4e2yqW5dBfbcuV+9tK7Rt4kyd7Blal6mNNtY3+tCZmzwid6vYxc2wjw0KVnrbwEZbg0IIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgj8XIBgRzP6TtQl2HHNgc3yj9x9XmuVnjtWyys1TlumzKn2VF0ObFafbSu1bM48VdjZ13h6a7uXfpu/McaWmx1rHGu9RSRk9QK1TEs40yalXccGy7rlZigkbKHsKsqNmhej3Ystm24be8wIeLSLOaLl9//VlimMQQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAoF4CBDvqxdY0k+oS7HAsKtD01x7Voqf+Vxm6mPjxCzo0ZKJiuw6ocYOhYQtkqqjQ1smzqx3nnpWqqe/PNYIjiYE9bT5wtz0bFBq2UNvG36ujA8faPO/nAzse3WHUOTJonPaOuKnedZiIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDA5SxAsKMZvb26BDus2x77xcs60Xu4TvUMkWtupm7+3+/18W/fselEU+c/pyODxiuq33VVjh/3+UtK9u+m/cNutKneuYNapcQYN23ktWxj3LRR6uhcpxqD139i3IhhnZvQqXed5jIYAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBK0mAYEczept1DXYE7d0o3+jD2nTTo+oesV5tEo7rhxsfsulEbeKPa9LH/9Cy2X9TVuv2583pv/kbeSee0vrbf2NTreoGDV7/qQIiI2wOaLRKjlHo6oXKrWcgpEGbZTICCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAALNUIBgRzN6KXUNdjjn5+j2N3+jRU+/K+sNG8f6j9Lp7oNtPlGvHWHyj9qtsBl/rJzT/tRBXb/0v1o2Z57yPVrZXKu6gba2VOm2e4MR6mhoC5cGb5gCCCCAAAIIIIBYUt9kAAAgAElEQVQAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIINCMBgh3N6GXUNdhh3fr4T180WrGErF6oRU+9K4udXZ1ONHLJG8r18lHEyDvkUFIka4uWiFF3KLr7kDrVqWmwa26GQsMWyq6iXOETZhotWn78mEuLjWee6QnGzR7p7To22roUQgABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBA4HIXINjRjN5gfYIdPSLWqceutcpoG6CNNz1W59M4FeZp2vzntG3Cfep4ZIcK3Vpo55i761zHlgl9ty5Xn20rjHDHyV6h8o0+ZIQ64rr01Y5x99hSgjEIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghcVQIEO5rR665PsMMtJ0MP/vlWLX3gH0ZYoj4f/+N7NXHRP5TsH6Rlc/5WnxI2z2l3+ohCwxYYt3c4FeYrfOJM48YRPggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBwoQDBjmb0rahPsMOxuEC//u04ffnL1xTdfXC9TuOdFK17XnpQUX2v1cr75tarhq2T3HLSNWzl+7KGSTLb+OmHqQ8rzbeTrdMZhwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAwFUlQLCjGb3u+gQ7uhzYrMEbPlNM12BtnTy7Xqe5YcFfFNX3OnU8ukPxXfrp4NBJ9apT26ROR7YrJGyhDg+ZoH3Dpyloz3cKXb1QO8bO0JFB42qbznMEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSuOgGCHc3oldcn2DHq69eV3q6Teu4I02dPvFnn0wxZu0hORQX64cYH5ZmeqKnvz9Xq6b9Til/XOteqacKQdR8bt3SET5ylhI69Kod6pcQa4Y68Ft7aNnGWSpxcGnVdiiGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIHA5CxDsaEZvr67BDvuyEqOFyqdPvKVxn7+kPdfdooROvW0+UafD2zTg+6+1bM48lTk4GfOu2f+Deu0IM35nMdnZXKu6gd7JpxUStkA5rdoZoY4f1/n5+EEbPlPHozsVPnGm4jv3bfC6FEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQOBKECDYUcVbXPjMJCWd3P/TE5NJTs7uahPYQwMm3Kee195c53cftSNMX784R9OfX6yAXqFVzrcGOx63Nyt83cf63eL4Gtf44KlxaimT3hwyQevu+K36hH8rt5wMbZtwn017c89O09T5c/XdLb9U4jk3aFgnh676QCZJWyfdb1Ot6gZ1373eaL2ybeJMHQ0eU2utwGO7FBq2QEeDR2vvtbfUOp4BCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIXOkCBDuqeMPWYEduRpKun/EH46nFUqH8zBQd3LRYGQknNPGR/1O/MXfX6bvRFMGOtoV5euKBfyhywCh5pidowif/0he/+rdN+xr7+ctK9euqfcOnXjDeZLFo6vzndGjIRB3ve61N9c4d5FBSpJDVC9UiI8m4pSOjbaDNNVzzMhUatlD2ZaXG7R25LX1snstABBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEmlrAYlcmU4W5qZeprE+wowpqa7CjpChfv3j9+/OeFuVl6e1HQ+TVrpNmvriqTi+pKYIdARlJmvKfLSpya2Hs5cb3/6SdY+9WUkD3GvfWb8tStYk/oXV3PFntOJ+4KE345J9aNudvyvb2tfms7U8dNEIdcdf0146xM2ye9/OB1htI+m5dboQ7TvYaVu86TEQAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQKA2AYupTIXep1ThUKQKc7HK7XNVbs5Thb31J1/l5gJVmAtVYS6STlhksjjJzuIi+wpX2VvcZWdxl72lhewtHrKrsD5zVoVrsRzKvIwQyE8/9uf9vbZ9WZ8T7KhCqbpgh3Xoh7+fooKcdD381jZj5pEtS7Xs1Ud17z+Wq31QcGW1Xd++q/UL/qJH39klD29f/RjsuP3ZjxS1Y7WObVuh0uJCdeg2SON/8YJate+sylYs6z/RQ29s0Zr//UFxR3fKzmxW0JBJGjtnnhyd3Yw1Pv7VCHmXlWjif3f8dIJFf9c34St0IjNZdnb28u3aX9dO/506BA2sHFO44TNt+/gFHSwvU0lJkTx9/I3bRwbf+OAFEr22r5L/8b0KO3tzSW1fqH6bl6rnztXGLR3RPYbUNrzW5+1ijhqtWRI79tS28ba1mKm1aCMMcC7IlX/UbgVE7tb623/TCBUpgQACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBwqQSKHZKU5vaFSn1OyCHXJFNJiUylFTKVyvixs/5Zcubvxo9FqrCTLPZnf+ykCuvfjd/ZS2ZHWewdVBFgTWWYJXs7yd4ki51Jqhwnyc4kk3XiCevJ7c4e33IOw5m/E+yo4ptRXbCjvKxUbz00SL7X9Ndtf1hozKxrsMOnYy95d7hG3UKmKCctXj989n9y9/LRA//epDvefkaP25u1/bvP1dq/m7oEj1G7Ln0VcyhcESvnq/f1t2nK2VYrXzwYLCd3L017Zb2xj6idq7XkxQc0snV7tXnoX6ooL9OO5e8o/tgu3ffCt7KuW5AUrfd+fb06deqtHrf+WmZHZ50+uEXbl/5XY2b9RQMnz75AY9TX/1F2q3baPfL2av8NuWenKSRsoWQyGaGO/BatGu3fm315mULCFqhVSozCJ8xSWvvOjVa7LoVcczMVcDbM0S7miGK6DlRMULDxU+bgVJdSjEUAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQaCYCea4HlObypZwTU+SUe/E3ZQ2HGJ9z8xw/buPs7wh2VPFerMGO4oIc3fvC8jN+FRXKTU/Utm/e1ImI9Zr+/JdGuMP6qWuwo8vAMbrtDx9WrrpnzUda87/f67Y/fqTfhX9rBDvC132skfc+p6HTHqkct+zVR3Rs20o9/sFBObl66JuZPVTsF6Q7/77UGPPu49fJ0cVdX1/TX+GTZyulwzUqLS7QO48Nk3/PEE178m3pP7/WvzYt1v0vrZVPx56VtQ9u/FJObi3UdfCECzSst1NMnf+cEdiI7TrgguedDm9TaNhCHRw6SfuHT22yb3nQ3o3GOjvHTNfhweObbJ1zC7tnpVaGObwTTxkhjtigM4GOCrsf/3VdlK2wCAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBAowpYlO6xQgWWcLkkpsu+pFGLN2oxgh1VcFqDHUkn91/wxMnFw2iH0vuc2yvqGuyY9MhL6jtmemXtzKRo/e+Xw3XtXU/rleSYymDHQ29sVct2gZXj9q3/RGH/fVoz5n2tEAcnvfbCTJV06Kq7/7rYuPnjvw8P0fDbf6NH2nSQqaJCu6+/zZj77eu/Uuzh7XrzsVdUuOkrPbplqbqH3qBRM/+kFq072PRlsrYdCV39oZbNnqciV4/KOUPWLpLfif1G6MPaLqWpPy1T44xwR4GHl8InzlTJ2bY0jbmuZ0ai/CPPtFnxTE88eyvHwCpDLY25LrUQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBC6OQIlDitLcFkt5kXJJLro4izZgFYIdVeBZgx0FOWma9OgrlU+L83OUfOqgdq9eYNyAccvT78lkZ1/nGzvumPuJOvW7vrJuSVG+Xr0nyGiD8nZhfmWw46nPomVvdqgcdyJinRa/MFM3P/2uZqUn6Vff/k+W1n5GsCM+MkKL/ljzbRkHB4zWygf+ptW71mrTxy+orKRIbQK6G+1erEETL99ONX6NBm78Qh6ZKdp48y/lnRSt0LAFyvZub4Q6yhwcG/AVrPvUQRs+V8cj27Vt4kzFdelX9wI/m+GVGqeAyAgjzGFtuXKmxcpAxXfu0+DaFEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQaD4CeS6Hleb2uZwTk+WU03z2VdNOCHZUoWMNdlgDF794/fsLnh7fuUZf/et+TXr0ZfUdfVedgx23P7tInQeMqqxbUpinV+/tpoGT5+jtwrzKYMdvPz0ps4NT5bjju9bqq3/O0s1Pv6c/bVuhSdGH5ODhbQQ7EiJ366M/3qjBN/xC3YdN1cglb2jP9bcqu5WvMX/YyvlyuvZmHRs41vjvovxsWeud2rtR1sBIWWmxpj7xloKGTqrxWzvx4xdksbOTb/QhI9BxbMDoS/YtDzwWoZDVCxTZf6T2XHdrnfdhDaf8GOZwKC5UrBHmCFZiYNPfPFLnzTIBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQKDBAhnuq5Vv+kHOiWkyFze43EUrQLCjCuqagh35WSl644EBxg0bY2fP09Gty7X0lYd1z9+XqkO3QZXVrLdibFvyhh59Z5c8vH0VtSNMX784R5Mfe0V9Rt1ZOS4r6bTe+eUwXXf37/RyYnRlsOPht8Ll6RNQOW7/+k+16r9P6YnHXtUtMUd024HNcnL1NIIduRlJeuvBgRo67RGNvPc5DdrwmcrNDkbgYci6T+RUmKsfbnyoyi+V9SaSj/90iywVFZrz6oZqv3jW8MOoJf9Rv83L9M2DLyiq77UX7Uta3UIuedkKXb1A5pJi4/aOHK+2Ne7JJ/742TYrETJZLGdv5ghWil/QJT8LG0AAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQaBqBUnO60XqlouCYXJMKmmaRJqxKsKMK3JqCHYe+/0rfvv64Rt7zrIbe9KhO7dukL+bdbdykce6NFwt/N1lJJ/ZdEOzoOmSibnlmfuWqe9cu0up3fqc7536qpzZ/UxnsGHP/8xo05YHKcctfe0zHtq/UohnPqty7nZ786t+VwQ7roPeeGKnS4kI9+J/N8k06pdCwhdo3fJq2zX9OedMe1jXX3qJDmxYr5fRhjbrvT+edesV/fq3YI9v18FvbqvyqtT91wKhnvdEiq7Wfeuxao2Vz5kkyNeFX0/bSfbatUL/NSxU+caZO9B5+3sR2MUeNFiv+kREqd3CqDHOk+Xa2fQFGIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghclgJFLeKV4vCuHJKT5Jx9WR5BBDuqeG/WYIf1Foxrpz9d+bS0qECpp4/o8A9L5NKile5/aY1cPFrJeuPFmw8Gq22n3pr48P/JZGenXSvnKzFyj5JO7r8g2NEmsIf8egxR10HjlZ0ap40f/s240WP2K+t0+3+fNoId27/7XNZxPUfcJJ+OvXT64Bbj9o/+Y2dofmmxVt/1jF7758zzgh1Gi5gXZ8u/x1AFT7pfY8I+0JrEaK3ITNZNT71rhE4it6/Ukv/7hXpdf5u6DZ0kewcnJZ86oC1fvGK0ghl139wLNPpv/kY9dq01Wq9Edx9sPB+26n1ZTHbG75rLp23sMYWGLVBSQHfFBA00whwBUbtV6Nqiss1Kxjk3oDSXfbMPBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIGmE0jq+Z7KY3fJNbrp1mjqygQ7qhC2BjusoYxzPw5OrmrRpoOuGThWQ6Y+LFfP1pWPT+3dqI2L/q6M+BNG6KP/uHvl5dtJy159RD+2VDka/q2WvvyQ7v3Hcu3f8JmObVuhspIi+fcM0YQHXzDartz25pN6TBbt37lGM/+5Uqvf/b3ij+6UvdlR3YfdqLvH3q3hm77Sstl/1QdPjTsv2GHdzIndGxS++DUlRx+SU3mZOrVopaAH/6mugydU7tUaTNm1Yr4yEo6rorxMLdr4qbe1Zcu0R2Rnb64c556VqtDVC1VhZ28EOAo8vCqfmSoqNPX953Ro6GQd7zOiqb+jNtX3O75Xgcd2Kfj7r2TdX8TI23Vw6GRlt25v03wGIYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghcWQK5vgeU7fqJ3HZkXtYHI9jRjF6fNdgRds8flOfZpspdDVn3iUqcXbV3xE017rrvlmXqcmiryhyctPz+5+t8ws6HwhWyeqEOhkzR/mE3Vjm/bWykxn32opbN+ZtyWrWr8xoNnWCyVJy5lcPaZiVqtzJ9/I2bOmK6BqtdzBGjdcyuUXfq8JCfQi0NXZP5CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAKXh0C5Q6Hi+r8s1/A4mS/TFiw/ShPsaEbfudqCHbf+9yl9d+vjqqmliG/0YY36+j9aNmeepnz4V4Xd/Qdle/vafMqhaz5S+1MHjVs6kgJ71Div97aV6nByv1bf/Xub6zdkoH1ZqQIiIyrbrKT4da0Mc+S3aHVe6ZZp8Ua4o9DNU+ETZ6rYxb0hSzMXAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQOAyEkjvskLFOavkcrTsMtp11Vsl2NGMXmFNwQ6f+OMatvJ9ffOLf1S7Y3NpiabOf057rrtFp3qGKDRsgfJattGBkCm1nrJ14imFhC1QVhs/I9RRbnaodY51wKivXjfaney+/jabxtd1kGNxofytYY6oM7dzxHfuY9zKYb2do8itRa3lBn73haw3kFjDHXHX9K91PAMQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBC5vgaKWMUoJfFce36VKlsv7LNbdE+xoRu+wpmCHNaBgsbOrMUAx4tv/qcTJVTvG3WOcqsPJA+q3+RutvG9ujafssWuthqxdZAQ6IgeMqpOIS362ps6fqy2TZzdacMK5IPfsrRwR8ju+TzFBwZVhDmsrmrp+rIEQa8glqt91TRZAqeueGI8AAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg0DQCCb3/K/vIfXJMbJr6F7sqwY6LLV7DejUFO25+53f6YepDSvPtXGWFbns2qOu+7/XtrL+c93z6a49q+aznjZs7fv5xLC5QSNhCuWenGaGOTB//emlY26MMXbPIaP9S35YnrrmZlWGOtjHHFFsZ5ghWmYNTvfZ17iSX/BzjRhLrma1nzWnVrsE1KYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg0LwEcjrsVo7jZ3LbldO8NtaA3RDsaABeY0+tLtjhnRSt6795S18//GKVS7ZKiTFasCy//69Kb9fxvDHDV8xXpo+fDg+ecN7vO5zcr9CwhTrdfbB2jr6rwUex3ijikZWqjTc/ZnMt96zUs2GO3bKe8cebOayhjgo7e5vr1GVg720r1f+Hr7Vt4iwd7zOiLlMZiwACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDQjAXKnHIU1/8VuX+fJPu8ZrzROm6NYEcdwZpyeHXBjgHffyX7slLtqiaAMeXDv+pEr2E6OnDsBdvzj9qjXjvCFDbjD5XP+v+wRN13rzdurjjdbVCVRxq6dpEOhExRgYeXzUeetOgfOh00UIeHnB8iObeAZ3qiAqJ2yz9ytzwzks62WAlWbNcBNq/T0IFtYyMVsnqBUvyCDAM+CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAKXv0Bq169VmrZGLscv/7OcewKCHc3ofVYX7Jj23rMKnzjTCCL8/DN4/adyyc/W91MfrvYkM15+SEse/KcRDgldvVDlZgcj0FDg3rLKOVWFQWxhapkWr6nz52rVPc8qtUOXyileKbFGmCMgcrdc8jIV23WgcTtHfOc+tpRtkjGmigr1iFh7wU0mTbIYRRFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEmlSg0Puk0nw/kPum1CZd51IUJ9hxKdSrWbOqYIdXaqzGfPGqFj/2ygWzOh7dqYHffa5ls+ep1Mml2pNcu+wd2ZeXqsPJA9o/7EYdCL2hxlNX177FFqqu+zapR8Q6bZk0uzLM4VBSqJizYY6kwB62lGEMAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACNgvE9/u3zAePyDHF5imXzUCCHc3oVVUV7Oi3ZamcC3K1fdw95+3UNTdT0+Y/p03THlZCp5pvvpjy4Tx1PrhVX/7yVSUFdK/1xNNfe1TLZz2vvJZtah177gCf+CjjVo7B6z6RxWQyWsfEBA1Uil/XOtVhMAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAArYKZAfsUJ7lC7nuzbN1ymU1jmBHM3pdVQU7bvjgz4oYfacSA3uet9MxX76qdN9O2jvipmpP0DrhpEJXL1BmG391PhSuL371bxW5etR4YuutHv02f6OV9821SaZdzFEFREYYgY5SByfFBgUr7pr+GrZyvnEzyInew22qwyAEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQTqKlDqmqH43q/JY2OK7ArrOvvyGE+woxm9p58HOzzTEzXx4xf0+eOvn7fLvluXq23sMa2986lqd99z5xoNXv+JwifOUmT/kRq55E0ldO6tyH7X13ji0LAFxk0dB0KmVDuu/amDlWGOQjdPxQQFG4GODJ+AyjltY45p3BcvadmcvynHq20zUmYrCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJXikBKt09VnrhJzqeulBNdeA6CHc3o3f482NF72wp5ZKUa4YwfP+1OH9Hor/6tZbPnVdkqxbEoX6FhC2Vt1RI+caay2vgZU603dnQ6HK71tz9Z44nvfP1xhc34g7K9fc8b5398rxHm8I/crVyvtkaYw/qT7d2+2np9tq2Q76mDWjP9d81Ima0ggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCFwJAvltIpXReqHcN6dfCcep9gwEO5rR6/15sGPyh/O0b8Q0xXfua+zSvqxUU+c/p30jbtLJXqEX7NzvxD6FhC1UdI+h2jX6zvOem0uLdc9LD+rjJ99WqZNLlaf2PX1EgzZ8puX3Py+TpcJor3LmJ0IZbQMrwxy5LX1sVrOGUDLb+GnPdbfaPIeBCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII1CRQYVeq+H6vyWnvCTmkXdlWBDua0fs9N9jhnpWqGz/4sz79zVuVOxzx7bsqdXTW9vH3XrDrAd9/raA932nbxFk63W1glaeyhixOBw3SiT7Dq3weErZAHtlpKnFyNcIcyf7dKtus5Hu0qpeUS16Wpr4/V1umPKC4Lv3qVYNJCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIInCuQ5b5Fufafyf1k6RUPQ7CjGb3ic4MdPXeulldKrBGIsH6soY2gvRv17f3Pn7fjFpnJxi0dZY5OCp8wS4XuntWe6Jr9P8j/+B59d8vjlWMciwuMWzmsLVaGrvlIB0MmK3LAKCPQUeTaolF0Ao/t0uB1n2jZnHkqcXZrlJoUQQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBC4OgVKzRmK9/y3PE4my67syjcg2NHI77goM135CQkqLchXWX6+3HzbSyaTTasM3PiFDg6dpGIXD928+j3t7Tlc8T2GyM9cYbRgWTHrL0rz7VRZq8vBLQoNW2i0azkQMqXWNRyL8jX9tce0+NFX1OHkfiPQ0eHEPsUGDVSOl48Covbo64f+VWud+gwYtOFzueWka9NNj9ZnOnMQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAwBFJafKHyrA1yzrw6QAh2NPA9l+TmqCgjXcWZGcafRanJKi0qalBVj5JCPbZ/uf456A6jzq9yjiohdKKODBpXWTdk9UK1izmq8ImzjJYptX1cczOMIMf1S9+SySIdGThGMUEDFds1WGUOjhq04TOVmx2057pbaytV7+eTPvq7TncfrMODx9e7BhMRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBK5egUKnk0pz/EDu0alXDQLBjjq86uxTJ5QbfVJmNzcVpacZYY7y0jP9esz2dnIxW+RillwdpAqLFJNt0YB2drLtvo6fNtI1JlJtslK1te9w+e+NkH1+gbZOf0qtevRWm/gTCl29QOntOhqhjgo7+2pP4JGVqoDICKPNinfyaaO9ivVjX16mjTc9dt68W95+RpumPaL0c24EqQONTUO9UuM0df5crbhvrtLad7ZpDoMQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBD4USCh5RuyTz4ox7yrx4RgRy3vuiA5SblxMcqLOaXinBxjtJODnVzsLUaAwxrkcHEwyeln+YrUAosR7Aj2rXuwY9SuDTrhd40sJmnA0d16r89kxRabNc65RGOidxmBjqh+11e5c8/0RCPMYb2dwyMzWbFBwYrpGqzYrgOM8S752brtrd9q0VPvynK2RUzrxJO6dtk7WtJEbVjO3WjQ3o3qtnuDls/+69Xzr4yTIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgg0WCDHdY9yyj+VW8KZ/3d/tXwIdlTxpo0gR6z1J1qlhYXGbRyejhYVlUul5Rb18bGr9ftR32CHU0mxbt74lZZfN00Ttq5SeN9hyvD0Vrc9O1SRV6gto++S4/ibz1vfKyXWCHIERA8nSXMAACAASURBVEXIJS/buJnD2mIlvnOfKvc54dN/6WjwGJ3uNsh4HrxpsewqyrVr1J21nqsxBgxf8Z7KzY7aNuG+xihHDQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBK1yg3K5AcV4vyS06QfYlV/hhf3Y8gh2SyktKlBcXc/ZmjmhVlJcbt3JYwxyeTlILpzPNVI6mW5o82NEl7rh80xKNoEVmi1ZK9/TW4EM7dLp9R63162/cAuIR0FH9gzor8Phe+UdFyKGk2AhzWG/mSArsUes3uMeutfJOOqXNNzxojL3p3T9q66T7leLXtda5jTHA2gpm6vzntG/YVJ3sPawxSlIDAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQOAKFkh3X6Xi/BVySSu7gk9Z9dGu2mBHQUqycmOilX0iUmVFRYaOq+PZMIezSW4OF4JdjGDH9bs3ShaL7CwVSvdsLWvQY2evIYrz8VebrFR5xcWqVXyszM4uSrv2BsX3DqlzIMMtJ13T3ntWnzz5tlqlxGj04n9r8aMvX9Qvf7uYoxrz5StaNvtvyvXyOW/tjkd3qNTRpdobRy7qRlkMAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQOCSChQ7JCjZ7W25n0yRyXJJt3JJFr9qgh3WIEdBcpIKkhNVkJRg3MphMplksVjU2tWktm4mOZtrfgdNHexwKCvVjFUfqsTsaLRfyXdxV3T7jvLJSFGHlDiVmc1GwOOIZwdtK2+loNtnyOzqWq8vzqRFf9eBkCnyToqWU1G+doydUa86DZnUJ/xb+Z4+rDV3PVNZxjU3Q1Pnz9X30x5RQqfeDSnPXAQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBK0AgyfMDKW27nHKugMPU4whXTbDj5NIvVZydLXdHycNRxp+O9iYdTKlQBw+T2rmfabdS06epgx2d405o0tYVKrV3UKJPe5nLylTo5KK4tv6K8/FTloeXsb2sIotOZFoaFOzotX2VPNMTjWDHzrHTlRRQewuX2nzq83zM4teU3jZAe6+9xZg+5stXle7bUXtH3FyfcsxBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEELiCBPJdjijD7iO5x2RcQaeq21GuqmCHe0m2Aj1/CnAUl6tZBTuenf9X2VeUK61lG6W1bK1cNw8VOzhd8EaLyqTMIsm7Ry/ZOVTRM8aG74BjYb6C9m5UudlBRwaPt2FG0wwxFxcpaN8mxXYdIJf8bLllp+tUr5CmWewiVa0w2WntXU9fpNVYBgEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEELgyBSymCsV5vSznuBMyF16ZZ7TlVFddsMN6O4fZ7gxNcwt2PLPwBZkrypTRwlvJrdoaPymt2irPxf28d5lbYlFcjhQ4bpLsnZ1tec9Vjrnx/T8pzbejwifNrneNxpjoG31IwZsWSzLpu1t+pYKzN5M0Ru1LUcOpME+nel7e4ZRL4caaCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAwLkCWe5blF/0lVyTC65qmKso2LFYRVmZxst2cbSTh4PFaMdyMtNySVqxWFup/Pjp4nXmFpG71nwij7wc5bq3UL6zmzJatFKbrFQVOTorzsdf8W39lOnh1SitWKzrzXxhlpICu2v13b+/pP8I7MtKNeevdynVr6uWPPjPS7oXFkcAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQuPQCpeYMxXu+Jo+TKbIru/T7uZQ7uGqCHVbkkpxs5ScnqiApSQVJ8SotOJPqcXEwqZWz5Olskou5+tdxNN2i0nKL+vicvfKjhjeXWmBRTLZFwb52+qn5y08TDqZUGDeGWJ9Zx1g/0zYtkXNxocrMDkpt6aO2GUna2XOICpxd5ZcSJ7/kWJXbm3XQ00/bXDrIfdbjMru61uv745GVopvf+b2K3Froi1++Vq8ajTVpxLfvqtTRWd7Jp3Wqx1AdGTSusUpTBwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDgMhRIafGlyrPWy/nM/Q1X9eeqCnb8/E0XJCcqM+qoSrJzVJiWYjy23ubh6WiRp5PJuNHj3M/FCHake3qrws5evmkJ2tVjiHqf2K/kVu20q+dgYytlcalqnRCrfqZCuXq3VkxQsPGT4hdUpy9yrx1h8kxLUOukU9oxdoaSArrXaX5jDQ7a85267d2o5fc/L6+UWE19f65WzPyz0nw7NdYS1EEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQuIwECp1OKc3xfblHp15Gu266rV7VwY5zWSvKSpUXG6PcuBjlxZ5WeWmpHM1nQx7W2zycTLoYwY6DXfqoc/wJJXn7qlVOhjb3v1aDDu+QV06mlvgP0WFzK7UbHKpWPXvLOylaAZERCojcLYfiQsWeDXkkBvas9RszadE/dDBksryTTsmxqFA7xt5d65zGHlBVkKPbnu8UdDbo0djrUQ8BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAoPkLJLR8Q/bJB+WY1/z3ejF2SLCjGuW8+FjlxcUoNybaaNlib2eSs1lGK5bOXnZyNUumqnqsnK1X31Ys64aM06Stq7Rq2GQNObRdKa18tK9jb7kfi9KoyB2KmDRTp2+YecGuvVJjjYCHf+RuueVmnr3JY6DiO/e5YKxbboZu+t8f9fFv31ar5BiN+vp1ffXISxfj+3beGpM/+luVrVd+bM2yffy9F31PLIgAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggcOkEMjtuUm75N/LYW3jpNtHMVibYYcMLKUxNVm5sjDKPHFR5WVnlDGvbFld7i1wcJBez5OpgktnuzOOGBDv6HD+gzBZeivfx0/jNK/Rhl5E63qK9+vbtpdF71qjAw0vhE2eqxNmtyt17pifKP2q3EfSw/v1Mu5aBiu06wBjfPWKd2iSc1A83Pmj8903v/lFbJs9WaodrbNBonCGDNnxmBFA2TXvkgoL2ZaUKPLZLJ3uFNs5iVEEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQaPYCBa2jlNb+Q7n/kCrTT/9rvtnvu6k3SLCjjsKFqSmylJerKDNdRRkZKs5IVVFmpiwWi1HJ2r7FxWwxbvRIzLOoY0uTqrrYIy7HotIKGc+sY6yfu7d+o+XBY+Wdl6XesUf17YCx8ow+rWsTjyjst2/IoU07Y5w1FNHxyA5tmzhTcV361XgC96xUBZwNeXgnnjLatbSNOaqdY+5WdI8hxtzgTYtlqqhQxKg76qhRv+HW0Mbg9Z9q2Zy/qcTJpX5FmIUAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggcMUIlDlnK77Pf+SyM04O6VfMsRrlIAQ7GoVRKspIN8Ie+Ynxyj5x3AhsnIl6VP2xtnE5mwWpHPDrvUu1sMdYZTm56fe7vtAb/W5URftA3VaRJmdVaPMNv6gcaw1HhKxeqMj+I7XnulttOoVrbqa6HNys8Z+9pNT2XSpv8sj38NKwVR9oyUP/sqlOQwa55mVq6vy5xm0h8Z37NqQUcxFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEErhCBpB7vyxK/Q86nrpADNeIxCHY0Iqa1VHlxcWXF0vw8mV3dZLKmOH72ObX8K5Xk5xvPgu6813j61FNj9eETbynFL0jXr3hXyR26KnLwOJns7HTjB3/Wsf4jFTlgVGUll7wsha5eKHNJsXF7R45X21pPE7R3o3yjD2v7+Hsr27X4R+2Re3aatk6+XweHTq62xUutxW0YMHrxa8poG6C9195iw2iGIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghc6QKZgd+rwLJcrntyr/Sj1ut8BDvqxdbwSccXf6qS/Dwj2NHjvgeMgk/9aoQ+euY9Jft3N1qtdN3/vdbe+ZTxrHXiKU1Z+LyWzZ6nTB//8zbQJ3yF+m1ZqvCJM3Wi9/AaNzf2i5eNMad6hlSOcygu1LgvXpZXapwREkno1PvsbR7BKnTzbPhhz1boE/6tfE8f1pq7nmm0mhRCAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEELh8BQpaRymt/Ydy/yFVprLL9xxNuXOCHU2pW0Pt2oIdduVluuelB/X546+r2MXdqNRj11p1OrJdK+997oLKbWOOKXT1AiUFdNe2CTOrXNmxqEDTX3tUHz/1P5WZHc8b0zY20mjt8u2svyggcrcConbLPzJCqR26VoY88lt411urXcxRjfnyFS2b8zfltvSpdx0mIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAghcGQJlztlK6PMfOe+Mk0P6lXGmpjgFwY6mULWhZm3BDmuJkUveUHznvorqd11lxeuW/lf/z959gEdV5W0Af++UzGTSIY1UCCR0EEILqBRLYsOGHQ2CbddVV9d1d/3ELbKru6uurnVVEOxdQYGgSFNMKIl0JAklvdeZJNPv99ybEFqSmUwmySR57z7ZQHLO/5zzu5cYmDfnNPoFYfe8m88ZRWGzyeGOwaUnkJ68CBWRw89oM2L/j4jOzsLm6x9sc4YLXnkE39/4CGpCouTPC6Iot5dCHjHZmagJiW4NeeidOPbl5CBKmxVXLX8C+2bOx7FxM53QYRMKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFOjvAqWj34ZYtAPa4/19pV1bH4MdXfNzubczwY7hB37C0F924vsFv20dx8vUiPnLl2LXRbcgb+SUNseP37sVSWmrsHveTTg0Nbm1zbzPX0R+QiJyx5/fZr/p370Ho84fe2fNb/PzUbl7EZOTKe/ooQ8MQUH8ZLlebXBEhw6z1r4Fm8oLGcl3uOzFjhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUo0H8EamK3oRFfQ5el7z+L6qaVMNjRTbCOyjoT7FCbjbjt2Xvko1MsXtrWkpHH9uGCr9+QjzVp9A1sc6jAyiI53NHkG4D05FQ5WLHw2bvxwSOvwazRtdlnyIlDSNz8Mb6586+Opo+I4wdajmvJgknnh/yWkEd1WMwZfRP2bMHIrE34evHfHNZkAwpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIU6P8CjcG5qIxYBd8fKyBY+v96u7pCBju6Kuhif2eCHVLpiz57ASdGTcPRs44wOe+HLzC4LP+M3Tzamkri5k8QdygdeQmJ8K8px8YbH+lwxjf990GsX/g46geFO72y8PxfEC0f15IFm0rdGvKwqb1w1YqlWHf7UlRGxDldjw0pQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUKB/Cli1dSge9zK0uwugruqfa3T3qhjscLeok/WkYIfVZJRbj7rtTvn9ow+cj3cfewtl0aNaq8Tv3YbIo3ux5boHzql86Uf/QknsGOxPurLDUWOyM3HNm48jd8IFWHf7Ex22TUpbCX1gKA7MuNzJlZzZLKQoV97JQwp5xBzJxPExM7Dj0ttRFp3gUj12ogAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKECB/iNQOnolxOIMaI/1nzV190oY7Ohu4U7UbyvYoWky4Kb/PoD3Hn0TdqXqjGp+NeWYv2Ipvr/hYZTGnAqDnD2kYLcj9Z+LUDxsPKRfp6ektrsjR+TRfZi4fTXW3bG0EzM/t+mUTR9DCnmUxo6Wd/PQGBuQn5Ao7+ZRMnRMl2qzMwUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEK9D2B2tgf0YDV0GXp+97ke3HGDHb0Iv7ZQ7cV7JDaXPLxs8iZcCFOjJ52zmzjDvyEiT+tweoly84JfpxsHHtkN0ZmbcK3tzyGcRnrcN4PXyIjJRW5489vc/W3/OfX+Hrx32AICHZJJ/ZIJqZtfB+rlzwFs9ZHrhFUUYhoaRePnCz41Fe1hjyKhk9waQx2ogAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKECBviOg1+1DzaD34HuoHoKl78zbE2bKYIcn3IWWObQX7JBCGWEFR7Dt6l+1OdsZG96B0mrG9ivuavPzF3z9P1REDMcviRfLnw8ryMaMDStRHpWA9JRF5/SZtfYt1IRG49DU5E7reBtq5V1EpLkUDp/YZn//6tLmo1pyshBQWYSClp088hMmd3o8dqAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAc8WMHgfQLXXJ9AVlkNp9uy5euLsGOzwoLvSXrBDCktc//rv5eNY2ruuWvEkjkyeh+zz5pzT5Lbn7sWX9zyNRr9BrZ+TjmRJ2rASwcXHkJGyCOWRI1o/JwUuxuzcgLTb/tRpnXmfv4iakCj8fOH1TvX1ratsDXlIc5HCHfJb/OR2dyBxqjAbUYACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKBArwsYvA+iWvMxdAUMdbh6MxjscFWuG/q1F+yQhkr+4BkcnnKpHHpo65JCEVe885R8/EltSFRrk+jcnzE2Yz3SFj7eZr/4fdswI20VsubcgIPTUlrb3PbsPfjyvn+h0TfQ6ZWOz1iLiOMHsOGWPzjd5/SGOkNt83Et2ZkYknf4tJBHIqxeGpdqttdJmqcgiiiKG+/WuixGAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgALNAg3eh1Gl+bB5pw4TVVwVYLDDVblu6NdRsGP07m8xuDQPP155d7sjj9n1LWJ/2YX1t/9fa5tZ65ajNjjyjNDG2QUCqoqRlLYKRp0fMpJT5fdTNn0kByuk41qcuaSjYi75+FmsWbIM9UFhznTpsI2mydC8k0d2JqJzfpbnUiDv5JEIk7dPl+qf9+OXGLV7IzJSUnFi1LQu1WJnClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhQ4V6BB+wsqvT+Qd+pQMdTRpUeEwY4u8bm3c0fBDunIkvkrluKDh1/rcNDZX72KBv/B2D3vJrndLS/cj28W/Rn6wFCHk03c8imGH9iO9ORUFMRPctj+ZAOF3Yb5y5dif9IVODpultP9nG2oNhvlgIcU9IjOyULJ0LEtu3kkosknwNky8K2tQFLaSvmIl/SU1DOOpnG6CBtSgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoECHAg3abFR6vyfv1KEyEqurAgx2dFXQjf07CnZIw1z+7jLsmzkfhcMntDuql7FBDlnsuvg2WNVekHanWHvHk07PUgpOSLt35I4/Xz6exZlL2hXEplTJu31096W0WVqOa8lCTE4WKiKGt4Y8pEBLe1fcwXQ51LE/6Ursm3lVd0+T9SlAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQoMSIFGbQ4qdO8279TBUIdbngEGO9zC6J4ijoId43asg191GdIvu7PDAaOO7sWstW+heOhY1IZEyWGGzlzaxno53CEdh5Kesgh1g4e02z1+71aMztyINYuf6swQ7mkrinK4o/nIlizUhESiICFRDnqcfhzM9G/fRcTxA/JaSmNHu2dsVqEABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAgTMEGjW5qPB5p3mnjibiuEuAwQ53SbqhjqNgh391KS579+/4+KGXHI42advnuGDN/7DqT6s6DGZ0VGjsjvWYvPVz+diS3AkXnNM0sLJI3h1k/cL/Q0XkcIdz6u4GUqBFPq4lOwsNAYNRExKNIXmHUBozSg512FTq7p4C61OAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhQYkAJNmmMo810p79ShZqjDrc8Agx1u5exaMUfBDqn6lSv/gsw5N6Bk6NgOBwvPO4wFrz2Krdf8GvtnXOHyxEILc+QjTCoiR8jhCFEQWmtd9t4/kJeQiEPTkl2u310dZ61djqmbPoQ+IBgVkfEtx7VMRnVYbHcNyboUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFBqRAk+Y4ynzflnfqUDcOSIJuXTSDHd3K27nid//lRnzywIsd7rAx4ac18DbUYcelt3dYfNrG96Gw2TBi/w/47qZHURY9snOTOa21IIqYkbYSoUW5crijPCoeiZs/gV9tBbZce7/Ldbujo5epSQ6i+NRXIT05FTWh0QgrONJ6XItNqUJBwmQ56FER0fu7jHSHAWtSgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIU6CmBhrDDqBJWQXu8lqGObkJnsKObYF0pu+CVR5C28E8wBIS02z2wohCXfPwcPv3NfzocYsGrv8P3C36LQeX5GJ/+DdYsWQa7QunKtFr7jNj3A5I2rELBiEkIKcrFmiVPweTt26Wa7uwceWwfktJW4cSoqdg97+Y2S4cUH20JeWTKwRcp4CG9dSX44s41sBYFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKECBviJQM3QLDL4bod1TCVVdX5l135sngx0edM+cCXZI052//Al5x472wgjNx6e8jdV3/UNe3YwNq6C0WbH98iVdXm1YYTZuff4+HB89A2m3/RFGnX+Xa7qjwHk/fIFRWZvkHUXyRk5xquTgsjxEZ2chJjsTmqaG1pCHo2NunCrORhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAX6qYDNqwGVcZ/D2rQf3nv1EGz9dKEesiwGOzzkRkjTcDbYIYUY1GYTdl10S5uzn7L5Y9gVKmTNvr718/NXLMXhxIuRM3F2l1Y89/P/oi44Qq4h7eCRnpKKgvjJXarZlc5+teXy0StWlRcyUlLR6BvkUrnAiiLE5GTKu3lIx7hIa5J28igcPtGleuxEAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQoD8KGAMLUBH3EZTHj8I7tz+u0PPWxGCHB90TZ4Mdg0vzMOfLl/H5r/7d5uyv+98fsG3+fagcMqz18yFFR3HZe3+Xj0+pDY50adXjMtZBOu5kw61/lPtH5+7BjLSVODZuJjLn3OhSza50ijvwE5I2rMS+mfOxP+nKrpQ6o69/dVlryCOwsgj5csgjUQ568KIABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABSgwUAX0EXtRHfE5tHvL4VU6UBV6ft0MdvS8ebsjOhvskApc+8Yf8eOVd6MiYvgZ9YJLjuPCNa/ji3v/ec44Y3ZuQGx2JtYvfLzTqw4ryMYlH/0La5YsQ/2g8Nb+miY9ktJWQdtYj/TkRa27eXR6gE52mLHhHYTnHUJGyiKUxozqZG/nm/vWVSI6RzquJQshxUfPCHnYlSrnC7ElBShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAgT4sUBW3Do1e2+G9twpKQx9eSB+cOoMdHnTTOhPsSNzyqTzzzDk3nLGCSds+h9Jqxe55N7W5sjlfvgJ9YAgy5zq/w4Zgt0M6yuXg9MuQO/78NuuO3ZmGxC2fyOGOnIkXdptqcPEx+eiV6rAYOdRh68FwhbehFjEtIY8hJw7KIY8t1z3QbWtlYQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAK9LWDxrkFl3Kew1/wC3f7G3p7OgByfwQ4Puu2dCXZIR6vMWvsWvrrn6TNWcPVbjyM95U6UR8W3uTJNkwHzly/Fjktvd/pokZnrV0AUFEhPWdShVkhRrhy6qBwSJ7cVFQq36o7Z9S2mbPoQGcmpyD5vjltrd7aY5Cjt4tGdIZbOzontKUABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCrhTwBB8CNXDvoD6l0JoT7izMmt1RoDBjs5odXPbzgQ7pKlc/9rvsfm636A6LFaeWVB5AS767AV89uvnOpxpVO4ezFq3Qj5WpcnHv8O28fu2YfSub+W2zl5SuEM6ukUKd5RFJzjbrd12XsYG+bgXnb4GGSmpqAmJ6nJNFqAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAgbYF7IIZtT6bYfDfCG2JHupKSvWmAIMdval/1tidDXZM/f5DWLy02HPBtXKliT+uhsZowM6Lb3O4qslbP0NAZTE2X/9gu20Dqorl3T023PYnlEeOcFjz9AbD9/8ohzGkuR2YcXmn+p7eOOroXrnO8dHT2z1exuXi7EgBClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAmcINGiPoNp7NRR1hfCuNEMQCdTbAgx29PYdOG38zgY7wgqOYPq372HNkqfkKle9/SR2zbsFpbGjnVpV8gfPoChuQrvBi5T3n0ZB/CQcnJbiVL2zG/lXl8qhDLPGW95po8knoFN1Jm37HAl7tiAjeRHyRiZ2qi8bU4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCA8wJWZR2qfTbAZN8HTXkl1E3O92XLZ2q2nwAAIABJREFU7hVgsKN7fTtVvbPBDqn4DS8/jO9ufhSioIAU1PjkgRedHlMKXsxf/gS+u/mxc45MSdzyKfxqyrDl2t84Xa+9hpO2fo6EvVuRnpKK/ATHAQ3/mjJIx7lIu5GkJ6eiyTewy3NgAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUaFtAr9uDKt1X8KoohXc1lTxNgMEOD7ojrgQ7pn/7rhx8kIIdPvWVyEhO7dSKRuz/EWN3rMOaxcsgKhRy3+icn+WdNqSdQIw6v07Va69xVO5eJG1YiWNjZiBz7k3t1hx+YLsc6th7/jXYP+MKt4zNIhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUocK6ASV2KGt03sJpzoS2vhdJMJU8UYLDDg+6KK8GOiBMHMXnLp3IoY8/516IobnynVyQFKQTRjp8uWwxtYz3mL1+K9JRF8jEs7rw0TQ2YsWEldIZauX5tcOQZ5WdsWIXw/CPyzh5l0SPdOTRrUYACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKDAaQK1Pj+gTvMdNGXl0NSTxpMFGOzwoLvjSrBDmv7CZ++Gwm7HO48td3E1ohzmODz1Ukg7a9QNCkfWnBtcrOW425hdGzBl00dyuCNn4myEFB2Vd/OoCh8qf8yuUDouwhYU8BCBuqAMNITuRsSRrh9b5CFL4jQoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAX6sYAh7CBqVF9AUV4DbUUjFLZ+vNh+sjQGOzzoRroa7Lju9cegEG347FfPubya0KIc3PDywygcPhGr7/q7y3Wc7RhSfFQ+ckVtMsK3rhI/XdYc8uBFgb4mUBT4X1iGFiE8735oa2L62vQ5XwpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAgQEiYAg/iNqwbwF9KbyO1UFdNUAW3g+WyWCHB91EV4MdN7z8W3nHjo8f/K/LqwktzMENr/RcsEPTZEBS2ioMP7AdhoBgbLnmfpTF8PgVl28gO/aKQKM2F1XKFfCyVsMePwlDDtzbK/PgoBSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhRoT+BUoKMMXsdqGejog48Kgx0edNNcCXbo9DW49o0/QhQUWH3XMjT4D+70igRRxPwVS3FwajKiju6FPigMmd14FEtU7h451HFsbBIy594ohzuk3++ddTX2J13R6fmzAwV6S6A0YAWE8p3wMgAN04IQ2HAbfEvH9dZ0OC4FKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFWgUM4QdQG/YdoC+D19FaqKuJ01cFGOzwoDvnSrBjVOZGSMeaSMGOqvChODzlkk6vKGn92xAA/HTZndA26uWQR3pyKgriJ3W6lqMOk7d+hvh925CevAj5CZNbm/vVlMnhDqtag/SUVDT5Bjoqxc9ToFcFTF5FKNO+Dr/jFfI8rEGAccowRO15FIJd2atz4+AUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIDV0AOdIR/B9SXQnO0Dqo2Ah1KZQRstuKBi9THVs5ghwfdMFeCHZd++C8cmTQXokKB0bu/w4Zb/9ipFY3Y9wPG7kzDmiXLIApSvAOIzvkZSWkr5Y8ZdX6dqtdeY//qUrmmWaNDhhTc8Alos+mkbV8g4efNcpu8kVPcMjaLUKA7BCr8PoW15nto605VbxzvDR/19QjMO787hmRNClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCrQpYFaXo0HzCwxBWyCoG9oNdJzsrFSGw2YrpWYfEWCww4NuVGeDHdLuGje8/Fu8/+gbsAsKLHzuHnz+q2fbDU2cvdSAqhJ5d44NtzyG8qiEMz49ecunCKguxebrHuiy0Ij9P2JG2krsueA6HJhxucN6kUf3ySGQE6OnYfe8mx22ZwMK9LSARVWNYr8X4J9bfsbQdi2gnxuKyP0PQ90U1NPT4ngUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIDSMCirEWTNhcGdQasYhlUdVXwMtihNA0ghAGyVAY7POhGdzbYkbBnC4acOIit19wvr+LC1a+hLGYkjkya59Sqkj94BkXDJ+DA9LbDFinvP42CEefh4PTLnKrXViMpoBFamIOM5FSURZ8ZHumoqJexUQ536PTVyEhZhJqQKJfnwI4UcLdAte+3MOq/hHe1eE5p43BAFXIJQnKud/ewrEcBClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKDDABWyKBjTKYY6dMCsKoKqrg5fBBFXTAIfp58tnsMOFG7zqsctQemwfLrnr75icsuicCj9/+y6+feOPePDt/fD2G+T0CJ0Ndlz8yfM4NjZJfpOuYYd3QDpa5bubHnU45uStnyGgqhibr3uw3bbyjh7Ln5CPdymPindY8/QGoUW58i4dlRFxSE9eJB8V48o1Zte3mPr9B0hPWYTs8+a4UoJ9KOBWAZuiCQWDnoFfbhkUtrZL6+eEILTgbmhrY9w6NotRgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQoMPAGLrhr1AbtgbSiHUZULld4Atb4B6oaBZzFQV8xghwt3/mSwQ+sTgHte/vGc8EZPBDu8TE249fn78N6jb8Cq1sirUFotuO25e/DxQy/DpPVpd2XRuXuQtP5trFnyFIw6/w4FpKDI2J1pWLNkGURBcEpLai8d5ZKRkoqcCRc61aejRsElx+TdO6pDY+TdO2xKVZdrsgAFXBWo89mJBtMH8C4ztlvCHAHYR0zCkIP3ujoM+1GAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCgxAAbvSDLNfGUx+pTD6HIHJNx8wNwHV9dAcM8FLPwBRuGQw2OHCQyAFO7R+gSg8vBPjZi9A8r3/PKNKTwQ7hu//EbHZmdh0/UNnjD33i5dQOGJiu4EKTZMe85cvxY7kO5AfP9mp1c9c/zakAyfSL7uzw/baRj1mbFgF6X16SirqBkc4Vd/ZRjO+fQdDThySd+8ojRnlbLdua6fT16DRL6jb6rOwZwrkD3oaurw8KM0dz69hehACDbfBt3ScZy6Es6IABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFOhVAVGwwuhbALu3EUbfPJh8jsLsXQZlrRXK6jooa21Q1QIKU69Ok4N7gACDHS7cBCnYMShyOAYNicP2T/+DO/65FuFxE1ortRnsEEXs+uZN7N34PmrL8qDR+WPoxNmYs/Bx+A0eIvdN/uvNuGX/D0h+Zi0y161Azq4NECBgZNIVuPSeZ7Bv00fY8dWraKyrwEj/wbjppkdgmHNT67hlxw/A8sYfEX/iEJ6CiKCwoZh4yW2YcsVdrW3mfPky9IGhyJx7o9MrF0S7HAY5OC0FuRMuaLNfdM7PSEpbhaPjZyFzzg1O1+5sw7iDP8nj7Jt5FfYnXdnZ7l1u71tbgZicLMRkZ6EmNBo7LlnY5Zos0HcEDN77UWd/F7rieoeTtgYBxinDELXnUQh2pcP2bEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKND/BGyKBliV9bAq6+T3FkUJLIpyWBU1sCkMEJQmqLQ2KKoNcohDVdc1A4UyBHZbRdeKsLfHCTDY4cItkYIdAWHRuPLBl/DWQ7PhGxiKhX9fDbQcVdJWsGPTqr9i99rlmH71rzBs4mzoq4rxw8fPQRAELH5+I9QaHVKeugU3790GxYhJmHjxLYgZNwuHf/wKP3z0bwxPvBhqLy1m3vAwzLUVWPePO+AzfAJulcYFUF18DCt/n4zwkCh8ofbCizc/hoOZ30Gay/k3/g6zbnxEPlIlOjsLaQsf7/SqQwuzkfzhv7Bm8VOoawminCwiHbsyYv+P8k4aBfGTOl27sx38asvlcIdNpUZ6cmq375oRUFUihzkku4DqEuTHJyI/YXKPrLWzNmzfvQJFgS9CXXwY6ibnxmkc7w0f9QIE5s1yrgNbUYACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKeKiACLtggU06C0WpgF3VBLvaCJvK2PxeqYdNVQe7ygCbygCrWAV7mQWwW6E02yBYjBBMjVBYRSgtgEJ6s7p/qQrFINjt1e4vzIq9KsBghwv8crAjNBrXPPoGsnesx5f/vgtXPPCifCyLdJ0d7NBXleC1X03H1Cvvwtw7nmwdsfToXqz6w+W49O6nMSn5jtZgR0RKKi696x9yO9Fuw39uHwmFSo3738iUAyDDDmVg3TtP4ZvjB/Doh8cgKJRY98ojcgjkvtd2YP537+H4mOk4NnYmvvjnYuQd2I6/PvUF5n/8HNYsWYbaYNeOSBm3Yx0ij+7Dhlv/KM9NCjwkpa2EydtXPnrFqPN3QdP1Luf98CVGZX0vhzvyRk11vVAbPYPKC1p35pCOXJGCHPkJiSiKG+/WcVis7wg0anNRpVwB33zn/0No1wL6uaGI3P8w1E08tqfv3G3OlAIUoAAFKEABClCAAhSgAAUoQAEKUIAC/UFAOmRdhCjIrza0vAGi0gxBVEufOXeRrW0Bu2CCwqY5q825fewqExT2s9udW9ouGKGwaR3CWrX18GoMddjO7F0BlcnPYTupgUL6x1oHlzSuyuj4dQ6rUg+VzfG4Ni8DlGZfR8PCpmiE0q5z2E52tjp2tqkNEERVO/f21IcFm9ptu01LR0m0OeZZs5Be+HbmsimaoDY5/jd1u6qdevJzfOqSnz2r42dAqqcQnWh3Rr02/hy1DC2tV2H3bv2z197a7QojFJZT47ZX0a5uaql3dqUze9gVTVBYpHE7vmxeDQ6evea60m4TSotPa7E2v3ZAhE1jgNJ+8pk/bU7CqV9LfW3KeijlP2unvi7JX6vkEVraCiJs3kYoRU3zZ+Qaze/P/r29yQZBFCDC3tLO3tJGem+X+9mVFgj+AkSFHaJgAwQL7IIVosICUWh+g2CFdC9Qape//klvIqTPmWEXzJCec/lZl0oqrRDClVCYbYAU2DBZIJhNEOTwBqAwy0MAVkDZgOY+PXgpFIGw22t7cEQO1RMCDHa4oHx6sEPq/vHfbkZF/hHc/dI2aLz9zgl2HNj6Gda+9BBu/vPHiDwrgPDafdMQMzYJVz/yemuwY/rDr2H0rPmtM5NCIYFhMbjlL5/KH5v91at4szAbX275FL999xd5zNd/PQP+wVG49W+fIX7vVkQe248t1/4Ge757Dxv+9we8kXQlFBffhpyJF7qw4lNd5n7xkrxjR31QmBzqyJq9AAenX9alml3pLK1TmkfeyCnYddEtXSmFwSXHW8McalNT864cCYkoiR3dpbrs3D8ESgOWQyjfBS9D59bTNBxQh1yCkJzrO9eRrQesgPQXSKNXHpQm35ZvZU9+M9ryDetp37yKOjP8qs4bsFZcOAUoQAEKUIACFKAABShAAQpQgAIU6MsCFq8qSK85yi8gKppfRGx+b4RN0MMuGGAXGmDWVkERpmp5MdIGUXqFUGh+L/9a0fxrQW+DvXXn/ZYXR9t4hVihtkOMVpyia+tVZOn102orxNo2AgJnoQs6C8RwtcNbIZSZIDZ0HEwQlSLM42uhtDnxorShEZq8IAmw3bFFjR3m0fVQOgiUiFY7rBVNUNefevG6raKizg7rCCl04KCd2QZbhQkqQ8eBDbu/DfYYM1QOXoS3G60Qy61QNjkOHYhxdqjNHY9rNRkBJ05psIVZIARLOwp0fH9tehOESulF7o6fF1FtgyJCDaXNq8PnxVJvgFDn+NkTfSxQBntDYe+4rVBjgVjjxDPqbYY4pOO5SRMXyswQG5xo52eEGOz4nglFRohmJ9oFmSAGOg73CPlmiA6M5XWEWACfdlxO/7pQYAFsbbQ762uHGG2BoFShOU129idP+5JTaIHiZD2xOdJxzp9i6eMxUohC2ZzpkCqKLe3kjIfcsXmcElH+WipIH5N+f/p7uY/Y3Hew9AX35JvYHLY4lQWRfy91VdSf+rj85Vb6enh6W4df7diAAt0jwGCHC65nBzuqCnOw4ncXI/HyxZiX+udzgh0ZX7yErR880+5IUaOm4rZlX7UGO+Y8+RGGTrigtf3/fjMTYUPHyTuECKIdC/99Dx6KHY3vP30ev111GBoffzx781CMTLoKVz30EjRNetz034fw3qNvIvvnTfj8mUX400W3wv6rf7uw2jO7eDfUYclTt6ImNBrf3fg7lEfFd7lmVwt4mZowI20lfOsq5eNgpLk5e4UW5rQesyJ9wT+5M4cnrMvZNbBd9wsYvYpQoX0dvsfb/k5XgAqiFLts59LPDUFo/t3Q1sZ0/2Q5Qp8TMPtUwORfCqNvDky+x2AX62EvqodKr5G/i2z+hvb0b0abf2/XibDGqxCavxg+5Qyg9bkbzwlTgAIUoAAFKEABClCAAhSgAAUoMLAEBBEm3zKYfcth8jkGo88JWJWVUOZILyDaIdhsEGxWCDbpBVSz/CKi9EPlCumFRk3zVv2tP7De/APoZ7wg2foD7T38U+HdcROVXsNgMx93WFpUuPen4J2u18Zr1m1O1tl2DlfKBhSgAAUoQAGAwQ4XnoKzgx1SiU0r/4LM9W9j8XMbUXB4h7xLxoNv74e33yBkfPkytr7/NK588L8ICh92zohqrQ4hMaOcCnbEHtmNkVmb8DetTq55erBjxNRLcc3v3pDrX/LRv5Fz3mwcOPATXvno31jw+7cwvIs7a4QWZiMpbRUsag189dVYvWSZfAyLp1yjd3+Had+9h4yURTgyaW670wrPP4yY7Cz5zarWtIQ5JqNySJynLIXz8DCBCv9PYKveBE1dexNTSpuRtTtrcwRgHzEZQw7e42Er43R6WkDa2s3iXwaTXymafA/D5JsHwWiEotoAZXUTVLXN27I5e1kDgMZpoQguvBU+5aOc7cZ2FKAABShAAQpQgAIUoAAFKEABClCAAt0sYNFVt4Q4CmD0OQqzbwmU9TYoawxQ1BqhqgOU+m6eBMtTgAIUoAAFKNBvBBjscOFWthXsMDXp8eYDF8gBjTEXXIt1rzzSGuw49MMX+PrFB7Dg8XcxfPK8dkdMeeoW3Lx3GzraseOCr99AZUQc3s7/5Yxgx//unwldwGDc/o+v5fqjsr5HdHYWtmRuxLLjB5D6z3UIHz7RhdU2dxm3Yx0mbfsC6cmpyJ1wARK3fAK/mnL5uBdPuoJLjmPGhlWoDY6Ud++wqZq3hoo4fgAx2ZlymKPJJ6DlmJXJqA7lDgqedP88cS4WVRWK/V6Ef255B9PrONghdWyYHgRN4/kIKb5c2uDME5fKOXWDgHTenkldDJNXEZqUh2AOPQ5BKUJZXQ9ltUUOcihMXRvYGtgS7shfCJ+KhK4VY28KUIACFKAABShAAQpQgAIUoAAFKECBLgmY1CWo9v0KlpgiKGuMUNQYmkMcde7dXaJLk+ylzkpVFGzWwl4ancNSgAIU6PsCCkUA7PZ2fwq57y+QK+hQgMEOFx6QtoIdUpn9mz+WAx2jZ12Nw9tXtwY7DDXlePXeKRiVdCXmP/xq64gWUyM2Ll+KSSmpCI+b4NSOHbc9dy++uvtpfP/9B2cEO9Je+z32bfoI9722A/7BEdAZavGr/7saF3tpkFNZjPvf/BnKlpBDZ5asbaxHUtpKeBkbkZGcirrBQ1q7p7z/DxTET8bBaSmdKdkjbad/9y4S9mxFxZA4BFYWQR8U1rozR93giB6ZAwfpHwLVvhtg1H8J7+qO1iOdR9nxHoemUMCm8oPNJwj+pgvha5wAlc2/fyBxFa0ComCB0asYJlUhmlSHYFIXQNlkhbKhBqomEUpz87aZ7r6sQc3hjpATt0NX2ftHZLl7faxHAQpQgAIUoAAFKEABClCAAhSgAAX6gkCt73bUqTdAU14OTX1fmHHPzlGpjIDNVtyzg3I0CnSDAJ/lbkBlSacEBIUfRDu3e3IKqx82YrDDhZvaXrADooh3H78Kxbl7IP365FEs0hCb3/kbdq75HyZcdAsSpl8Oc5MBu75+A9VFuVj8/Eb4h0Q5DHb85ppfY3zGOqxf+Hjr8S4nj2KpKT2BlY9eCr/gCMy64WGMzt2Hids+w3/rKuG7+G9IvHxJp1cak5OFGWmr5B06smYvOKd/YGUx5q94AutvexwVkSM6Xd/dHQS7HdKcTx6zYleqEFhZKM99xyUL3T0c6w0AAZuiEQWDnoFfbjkU7Z+00rIDh3SopePL5gWYA9SwBAZBZ5kIP9MMaM2RjjuyhccIiAobbOpG2Lwa5De7VyMMOAyxsQYmVRFUTRYopCCHEVA3tZx32gOztw4CGqaFIvRYKnRVw3tgRA5BAQpQgAIUoAAFKEABClCAAhSgAAUoIAkYvfJRpVsNNOZBW25w8G+JNKMABShAAQq4JiAIPhDFTpzn7tow7OWhAgx2uHBj2g12ACjJ3YN3/nTlOcEOKeix65s3sXfj+6gty4OXtx+iRk3FBbc8Jh/fIl2OjmL515gZqAuOkHfIyPjy5TN27JD6l584KH+s6FAGRIsJtwyOwMyRU3Dst690epWJmz9B3MGfkJGyCAUjzmu3f/zebRi9+1usWbKs02O4o4PKapaPnJHDHDlZKItKaD1mpcFvEHzrKpCUtgp2hRIZKamQPsaLAs4K1PnsgMH4IXTlRme7ON1OFABTAGANDIFKES3v4uFjbP5a4NZLECFKu4kIovwm/a/51/bTfi3CqtBDafZpGfr0kErzr+X/F0RYveugsga0nCbTfpjFqqyFqinQ4VIsuhqopbNEHFwWZQ3UTUGntTptXqd91OJTBbVN+nMufV5ap/T/p37d/DERJmU5vAyDIQq25jc0v0fL++aP2dEUcQQq0R9WdQ1s6nrY1HrYVUYojIBgskEwWiCYzLBajNDlAyopyNGLl2Vw884dYbmL4F0d14sz4dAUoAAFKEABClCAAhSgAAUoQAEKUKD/C0j/hlTjsxkG1TZoyqR/b+r/a25rhQplMOy2yoG5eK66XwkolCGw2yr61Zq4GApQoP8IMNjhQfdywSuPIG3hn2AICGlzVje/cD/Wpv4Z+qDQdmetaWqQd9GQdqioDovFVSuexIenHf/iaLnSLhwz0lbC6OOP9JRUmLz9HHXBzHUrICoUSE9Z5LCtOxp4mRrlIIcc6MjJQlHceOQnJMqBDqOu7aMtzvvxK4ze/Z28phOjprljGqzR7wVE5A96Brq8PPn4jO68LD6AOSgQovcg+JtnQ60KhiAoISotsCstLe/NsCuMEBVNsCubIO0mglILpKM/RFjl93ZYAcEKu9D8Xg4rKOzAsOYQhJTnOJlxaE5qnPqYaLVAKFCftkypgXBqu4mW9qLWDEWoVzscp4IedqMFirL22p3qLvoaIQzSOqwn6k0QajTytKVZtXeJAUYI/tqWJIrY8r5lnVLEoznrAZu+EcpaqZ0IQbQD0ptdam+HINpafm+DJQrQVAEK06k3oZufh64+a5bglnBHzmJ4Vw/tajn2pwAFKEABClCAAhSgAAUoQAEKUIACFGhDoFFzFNW6r6DQF0BbYZR+jmrAXgrFINjtHZ5lPWBtuPC+JcBnuW/dL86WAgNNgMEOD7rjHQU7Io4fwKRtX2Bt6pMdznj2V6+gISAYu+feJLe7/N1l2DtzPoqGT3C4Umn3jaS0lcice6O8K4izl8Juw/zlS7F/xuU4Ov58Z7t1qp22sb71iJWoo3vlEIcc5oifDLNW51QtyVBan9R310W3OtWHjQauQH14JmqEd+F/wP27dbSnatNIu3hoIQ73BqwiBKsNsFohWK3N723Sx+RNJeT3gv5UMONkaEP+C+TJTTlOBjkG7m3s8spVqmGwWo93uU5PF7CENIc7wo8sgbYmtqeH53gUoAAFKEABClCAAhSgAAUoQAEKUKDfCkg/fFXt8x2ahJ3QlFdA3Y93xFcoAmG31/bbe8mFDRwBPssD51731ZUKgg6i2NhXp89595AAgx09BO3MMB0FO2ZseAcN/oOwP+nKdkuN2bUBsUd2Y/3C/2ttMy5jHfxqyzvcTUMKZsxIW4XgkuPyjhYVkSOcme4ZbcIKjuCSj57FmiVPoX5QeKf7t9VBp69uDXNI9U+GOQriJ8OqdrwTQFs11WajHO6QTZIXoTosxi1zZZH+J1A+8kOIJ7bCq7j/rY0r6j0BhSIEdrvjrfwUigDY7XVdmqglFGicEt4c7qiN7lItdqYABShAAQpQgAIUoAAFKEABClCAAhQAakJ/gN76I1Q1RfCulH4Cq39fgsIfor2+fy+SqxsQAnyWB8Rt7tOLFAQtRLHnftC4T2MN4Mkz2OFBN7+jYMeNLz2EDbf8AXXBEW3OOKT4KC57dxnWLF6G2pDI1jb+1aW47L2/4+MHX2qznxSYSEpbhbLohC4fpTIuYy0ijx3Ahlv/4LKqFLg4eczK4LK8M3bmkI57cdc1KnMjYrMzZVNeFDhbQDoCJW/qU/BPK4dgow8FHAsoleGw2UodNnR2Kz+Fwg92u95hPUcNzGGAcfIQhEnhjrooR835eQpQgAIUoAAFKEABClCAAhSgAAUoQIEOBArPew6Kwznw7uM/DCYofCHaDQ7vtSD4QhQdt3NYiA0o0E0CgsIHot3xtjnOPvPdNE2WpYBDAUHQQBRNDtuxwcAWYLDDg+5/e8GO8PxfMHXjB/h68d/ane1VK57EkckXIfu82ee0uXLlX5A550aUDB1zxuekIMZ5P36F9ORUtx2hMu/z/6ImOBI/z77eadmAqhLEZGciJicL/tVlLWGOySgYMcnpGq409K8pQ31QmCtd2aefCzSEZKPGdznmQ9a7AAAgAElEQVR8dndtx4R+zsTldaOA038hEXwgih3/xaUxBhDUYxFR+0A3zpilKUABClCAAhSgAAUoQAEKUIACFKBA/xaojd2OBuvn0O3r+1vlc8v//v2sDqTV8VkeSHe7b66VgY2+ed88ddYMdnjQnWkv2DFt4wcwa3XYc/41bc5WOqZFabVg+xVL2vz8hO1r4N1Yjx2XLJQ/791QJx9HIh1LIoU63HV0ysna85cvxfbLl6BwxMR2dYPKC5qPWcnJhLehTg5zSEesFMWN96A7wqkMVIGK+M9gK9wITeFAFeC6+4qAIHhDFJs6nK5NAxgjYxFV96e+sizOkwIUoAAFKEABClCAAhSgAAUoQAEKeJSA2acSJWP+C9/N5VB48A9UO7uVv7PtPOomcDIUaEOAzzIfC08XEAQviKLZ06fJ+fURAQY7POhGtRfsWPDq77BpwUOoDo05Z7bDD2zH+J++wZolT8GuVLW5mqCKQlz8yXP49P7/yDtjSKGO7IlzOrWrRmeYpDGmf/eefCyMyduntWtwyfHmY1ZyMqE2m5p35oifjNLY0Z0pz7YU6F4BwS4fw+L3fQkE/re2e61ZvcsCzvzFRVQC+mEhiK15qsvjsQAFKEABClCAAhSgAAUoQAEKUIACFBiIAmWj3oO96EdoT3j26p39yXBn23n2ajm7/izg7DPqbLv+bMW1ebqAGoDF0yfJ+fURAQY7POhGtRXsCC3Kxcx1K/DV3f84Z6bSUSJXLV+K7298BKUxozpcydXLn4A+MASDS08gPXlRh7tpuINkyuaP4VNXicNTLm3ZmSNLLnsyzFEeFe+OYViDAm4XaBx8FNWBb8FnZ43ba7MgBdwt4Gzaty4+ALE1yyCI0jeRvChAAQpQgAIUoAAFKEABClCAAhSgAAWcFWgI/QU1Qe/C56cqZ7v0Wjtn/62o1ybIgSngpIAgqCGKfDHcSS426xUB6YftrU6MrARgc6Idm1DAsQCDHY6NeqxFW8GOxM0fQ1QokTV7wTnzuPTDf6Fk6BjsT7qywzkGVhThmrceh0WtwWf3/+eMXTS6Y3HheYcRk5OFmevfRt3gIfIRMtIxK5VDhnXHcKxJAbcKVI5YDWvJemjy3VqWxSjQqwL6oX4Y0vQ41NagXp0HB6cABShAAQpQgAIUoAAFKEABClCAAn1JQFRYUXje89BkHoO6uhdnLqgBZ17kFlSA6MwLjb24Fg49sAWcfUadbTewNbn6XhVwNrChAGDv1Zly8P4jwGCHB93LtoId1/7vD/hh/r2oHBJ3xkwnbfsCQeX52LTgtx2uIGHPVszYsBJHJs1D5LF9+OK+f3fLiiOP7Ud0Tpa8O0eTbwDy4xNRGxyB2atfxfrbn0BFxPBuGZdFKeBugfypf4fPlgIojO6uzHoU6D0BQ5QOIbaHoTVH994kODIFKEABClCAAhSgAAUoQAEKUIACFOhjAjVDN6PJtBreB3r7Hwv5k+F97NHhdNsVcPbFcGfbkZoCvSXAwEZvyQ/kcRns8KC7f3awQzo2ZfZXr+KL+/51xiyjju7D+d+8gTVLlqHRN7DNFShsViSlrcKgsjxkpKTKwYpr3/gjfrjyHlRGnBkScZUgOudneWcOKcxRPyhMDnNIR61Iu3ScvKRgycis7/H14r+5Ogz7UaDHBJqCTqAy5A34pvdm/L7HlsuBBpBAQ5gXglS/ho+x42O7BhAJl0oBClCAAhSgAAUoQAEKUIACFKAABToUMPmVojThVfhtLofQbSdCOPvitbPteFMp0FsCzr7I7Wy73loHx6WAs8+oAEAkFwV6VIDBjh7l7niws4Mdk7Z9DqXVgt3zbm7t6GVsxPwVT2DXRbcib+SUNguG5/+CGWmrUBo7GhnJd7S2Sdz8CUSFgKzZN7i0aoXdhujsrNYwR1V4rBzmKEiYDH1gSLs1Z61dDptKhYzkVJfGZScK9JRAVdx6mCtWQ3uip0bkOBToGYGmwQJ8fZbAv6Ht/270zCw4CgUoQAEKUIACFKAABShAAQpQgAIU6DsCpaPfBvJ2QFPQnXN29gVEZ9t151xZmwIdCTj7Irez7ahNgd4ScPYZdbZdb62D4/ZHAQY7POiunh3suPqt/0N6SirKoxJaZykdbdLgN+iMsMfpSxif/g0mbF8j79JxdNysM1YXUpSLWeuW46u7n3Z61SqLSd6R4+QxK2XRI+VdOfITEtHoF+RUHWn3kPkrlmJ/0pXnzMmpAmxEgR4SyE98BrofT0DZ2EMDchgK9JCAKQBQB16DwYaUHhqRw1CAAhSgAAUoQAEKUIACFKAABShAgb4rYAg/iFq/9+CTUdPNi3A2sMEXELv5RrB8uwLOPnvubsdbQoHeEnD2We6t+XHcgSzAYIcH3f3Tgx1BFYW46JPn8dn9z7fOcMzubzH08E6su/2Jc2atM9RiRtpKqCxmOdRRHxTW5squf+1RbL7uQVSHxbS7cmlXkJicTDnQIb0VDp/YGuYw6vxcEpN2Ebn4k+exeslT0LczN5cKsxMF3CRgDChExZDX4Lu9yk0VWYYCniNg8QEQeiFC62/1nElxJhSgAAUoQAEKUIACFKAABShAAQpQwAMF7CoTCic+D++deVDVdvcE+QJidwuzPgUoQAEKUKC/CDDY4UF38vRgx8Ttq6Fp1GPnJQvlGQYXH8MV7/wNa5YsQ01I1Bmzjj2yG0lpK3Fk0jz8fOF1Ha5o6sYPYNF4Y88F157RTttQ33LESiYij+1Hfry0K8dkFCQkwqzxdouStJvIkBOH8O0tj7mlHotQwJ0C1cO+h6nmU2iPnqoqCBqIosmNwzibwHfjkCxFAQBWDWCJGo+I2vvpQQEKUIACFKAABShAAQpQgAIUoAAFKNCBQPWwDTA2fAPvwxY6UYACFKAABShAAY8RYLDDY24FcHqw46q3/4zd825CSewYeYbS749Mmovs8+acMeMpmz7C0F92IiN5EQqHT3C4GmnnjGkb38eaxU/Bp75aDnNEZ2chrCC7ZVeO5kCHTeXlsJYrDeZ99gJqQmMcBlBcqc0+FOiKQOGkZ6HNyIXScKqKIKghiu78CxwT+F25R+zruoBdCTTExSKm+k+uF2FPClCAAhSgAAUoQAEKUIACFKAABSjQzwVMAUUoi/sffDeXQ7B1ZbH8d8Cu6LEvBShAAQpQgALnCjDY4canwm6xoCxzB5rKy2GzmCFarfAObftIlLaGvWfTcnw84wYoRRtuSv8Ur118DwLjR+KSQ1uhspjw4xV3tXaTjmqRdulo8B+E9ORFMGt1Tq3Er6YcN794Pyoi4+FTX4X8hMTWQIcoSLsJdO8lHRkzf/lS/HDl3ShyIojSvbNhdQo0C5j8S1Ae/Qp8t1WeQSIIKoii1Y1M/AudGzFZqpMCdQmhiK3+MwRR2cmebE4BClCAAhSgAAUoQAEKUIACFKAABQaGQMnYNyEczYSmaGCsl6ukAAUoQAEKUKDvCDDY4eK9sjQ2wFRdBWNNNYzVVTBVVcKkr2+tplEBNjugU0sv5Dp33bP7K3w87mKMrMqHv9GAjcOnIbb4OJJtVdjw8EuwqdRyoYQ9W+RQx66Lb8WhKZc6LB5QWdxyzEoW/GrKoLDbUDx0LLZc94DDvt3RQDo6Zur3H2DN4mVOB1K6Yx6sSYGTAjWx29Ck/xDeOeJZKNIL4F2K5hOZAh4hIB0rVD/MHxGGR6GyBXjEnDgJClCAAhSgAAUoQAEKUIACFKAABSjgSQL6IXtRp/sQPjtrPWlanAsFKEABClCAAhSQBRjscPJBMBQVoGJPlrwLh9XYCKvRKPdUKAR4qwXolCK81YBOJf0eOF4rwi4C8YOcD3ZcvfVLbJx2CWbu3Y4DI8ZDr/PHhVvX4t24C9E49yqEjRqDpA2rEFRegPTkVFRGxLU7+0Hl+YjJbj5mxbuhrnVnjuJh4xBx/AAmbfsca1P/7OTq3d9MOkLGR1+NrVf/2v3FWZECnRQonPgCNJm/QFXXyY5sToE+IiAdK6SP9kOo5TfQmCP6yKw5TQpQgAIUoAAFKEABClCAAhSgAAUo0DMCNq9GFE58Dj4/FUF56uc3e2ZwjkIBClCAAhSgAAWcEGCwowMkfUE+DIX5MOSfgMXYJLf0VgkI0Ervm3fj0KraLnC0xrVgx08TZuLCrG34/KIbMHf3JpQPCsWG4LHwLinFdfVHUTt1HjIuvb3NQYNLjslhDulNOrrl5DErpTGjzml/84u/wdo7noQ+KNSJx6R7mlz+7jKcGD3NqV1HumcGrEoBwOxbjtJhL8FvSwU5KNB/BQQVGsO1CFTcAx9jQv9dJ1dGAQpQgAIUoAAFKEABClCAAhSgAAVcEKj13Yba4A8RkHn2jr4uFGMXClCAAhSgAAUo0A0CDHachmozm+Ugh74gD4aCPNhtNmjUCgR4iQjQADnVIoJ1AmIDHO/C4Wqw48SQYdCam9Co9UFQfTW2TZ6DsccOIC77ID6PmoqCaZcg4vw5rbMOLcxuDXOIgoD8hMkoSEhEeeSIDh+XmetXoG7QEBycflk3PFbOlQyqKMT85U9gbeqTqBzS/u4jzlVjKwq4JlAXswMNTe/C+xerawXYiwJ9QkCJpmABvt6L4d84uU/MmJOkAAUoQAEKUIACFKAABShAAQpQgAI9JVAY9Cy0BblQmnpqRI5DAQpQgAIUoAAFOicw4IMdxspKNFaWy0EOQ3GhrKfzaglzaAX4qJtBbSKwp9Te7cEOk1qDkuAIDC/MxZbEuRh3dD+Udjt2jZmGPMEHJ2pFjNECUwO8EHt0LywabznMIe3OURU+1Om7H5W7B+Mz1mL9wv9zuk93NEzYswUjf96Mr+/8a3eUZ00KOBQoHv8y1HsPQFXjsCkbUKBPCxgDAU3AAgwyXNyn18HJU4ACFKAABShAAQpQgAIUoAAFKEABdwoYvfJRoX4dvvnV7izLWhSgAAUoQAEKUMCtAgMu2GFtakJjWQkay0qhzzsGS1PzESt+GgUCNNLOHG0fr9ITwY7rNn0Gb1MT9Do/FIdEIqY0DzkxCdg/YgKGVBYjqqwQoaUFKBG9cSx6NIw334eakCiXH4hbn78Pq+/6Oxr8B7tcwx0dz1/7FqxqL2Rceoc7yrEGBZwWsOiqURL/Avw2lTvdhw0p0FcFzL6AEDIXofU39dUlcN4UoAAFKEABClCAAhSgAAUoQAEKUMDtApV+a2CpXQdtrdtLsyAFKEABClCAAhRwm8CACHZYGxtRuX8PGkuLYKxt/u7MS62An0pEVZOICWEKqBUdm/ZEsOP2tasgneCn9/GDKCiQN2SofCyLFOio9/FHYVg0ikKjsN/qB4NXIOKuXtClB+H8b95AVfgwHJ5ySZfqdLWz0mrB/BVLsXfWfBwbO7Or5difAk4L1EdlQm95B7pD3GPRaTQ27LMCVi1giTwPEbX39dk1cOIUoAAFKEABClCAAhSgAAUoQAEKUMCdAqJgQ/6gZfA9WgKFzZ2VWYsCFKAABShAAQq4V2DABDuyP30fg70F+HoBfl4CNCqgvEFEQb2IxCEOUh09dBTLw+8/K9/d0sFDYFcqUBkQjMLQaBSGRaHB27f1zufViW4JdsQe2Y1Rmd9jw61/cO9T5UK18LzDuOizF7BmyVPQB4a6UIFdKNB5geJxr0N1YA/UVZ3vyx4U6GsCdhXQODQO0TWP9bWpc74UoAAFKEABClCAAhSgAAUoQAEKUKBbBBq8D6NGfBs+RfXdUp9FKUABClCAAhSggLsEBlSwY3iQgECt0GrnScGOuOKjuP2bVbAplGj01qFJo4Nd0XbgxGwDbIISmoDALj8Hg8rzURscCbtC2eVaXS3g3VAHldkIfVBYV0v1av+9s67G1mt+3atz4OCOBazaOhSNeQ7+3/EYFsdabNFfBOpGhmJo5V8BnPpvYX9ZG9dBAQpQgAIUoAAFKEABClCAAhSgAAU6K1Dm/w5Q8RO8DJ3tyfYUoAAFKEABClCgZwUGVLAj3Ld5xw5fLwFKwfN27Fj61l/QoPVBafAQOeAhHb1SGBol79phU54KXrhrxw7pUZu9+lWUxozGkUlze/bJa2e0iz79D6rCh2LPBdd6xHxcmYTKaoZV5eVKV/bpQQF9xB7UYxV0+5t6cFQORYHeFdAPD0Wk/vdQ2vx6dyIcnQIUoAAFKEABClCAAhSgAAUoQAEK9LKAValHUcC/4Z/DH/zq5VvB4SlAAQpQgAIUcEJgwAQ7Snelo7GkCFaTSWbx0SjgpxZRauj5o1hMVuBQpV2eh59GwIig5p+c/tPby1AcHIl6X3+Y1BoUh0QgwFCHiIpi+TgWKeBRFBaFnAa1W45ikcYcdmgHhu//ERtv+p0Tj0v3N9HpazB/xVL8cNW9KIob3/0DcoQBK1A6ZjkUv+yCumLAEnDhA1DAEDsYoaYHoLGED8DVc8kUoAAFKEABClCAAhSgAAUoQAEKUOCUQL1PJgymd+FdZiQLBShAAQpQgAIU8HiBARHsOP0uGGuq0VhWgsbSEjQUFcBmtUKhEBCgAQI1QIBGgLKNE1BsIrCn1I5gnYDYAMdb2B+tEWEXgfhB57aVgh0HKpqDHQHaU8GOP6x6GgVh0XKoIz88BiMKcpE5egqORw5DVFkhosoLEF5aiP2+ETgaMRLm1Idg1Pl36SFTWi1Y+Ow9+PC3L8Os9elSLXd1HvrLLoze/R2+v+FhmDXe7irLOhRoFbB5GVA44V/w38A0Ph+LgSXQGOGPIOEe6IwjBtbCuVoKUIACFKAABShAAQpQgAIUoAAFKHCWQHHgy1AXH4CKG/ry2aAABShAAQpQoA8IDLhgx9n3pO5YLsz1tdDnn4Cxpkb+tL9GQKC2OeTh1XICSk8EOx5752kcjBuH4pBIRJUVIH38TEw6koUGb1/sGjsNFVYVCqptGGerx1Q/FYaeOICy6JHIT5iMgoTJaPAb5NIjN/eLl1Aw4jzkTrjApf7sRIG+JmAI34869Sro9vDwzL527zjfrgk0hXjBT7sYfo3nda0Qe1OAAhSgAAUoQAEKUIACFKAABShAgT4sYFKXotz7Ffge53a+ffg2cuoUoAAFKECBASUw4IMdp99tc30d9AX5MBScQENZqfwp6ciWQC9RDnlIx6d0544dUrBj47RLobTbYFMooTEbkT5hFib9komQ4gJ8EjEV5eOmI2r2RRCUKgh2O2JyshCTnYmY7CxUhcXKAQ8p6KEPDHX6QR6+fztij+zGpgUPOd2HDSnQlwXKRr8D5P4Er+Y/5rwoMGAEjEGA1v9mBBnmDJg1c6EUoAAFKEABClCAAhSgAAUoQAEKUOBsgRrf79Gk/xTe1bShAAUoQAEKUIACfUOAwY527pO1qQmGwnzoC/NgKMiHKIpyS18vAUFawFsN6FRtH9sitXPlKBYp2PHOFXdixr6f8NXc63BpRhqOR8Thh0Hx8M/LwzVVR5CXfAv2XHBtm7OOzt0jhzyis7OgDwqTAx7SW93giA6fRrWpCbc9fy/ee/RNWNWavvHkcpYUcFHArjIif/I/EJBWDjT/seZFgQEjYPYDFIMvRoh+wYBZMxdKAQpQgAIUoAAFKEABClCAAhSgAAXOFsgf9Ax0eSegNNOGAhSgAAUoQAEK9A0BBjucuE+izYb6E8dQsTcLos0KS2Njay+NWgFvpQidGvBWSYEPARql68GOV254ABf8vA0/j0qEWeWFOdvW4pVRKbBMn4uhCfFISlsJhc2KjJRF0AeGtDv7iOMHWnfyaPIJaAl5JKImNLrNPhd9+h8cHzMDx8YmOSHCJhTouwI1Ptug9/kSfod5eGbfvYucuasCVm/AOiQRQ+rudrUE+1GAAhSgAAUoQAEKUIACFKAABShAgT4t0KQ5hirlm/ApaD6anRcFKEABClCAAhToCwIMdrhwl0S7Haaaahirq2CsqZLfm6qrYLNY5GpKAdCpBRitIvw0wjkj2ESgzti8VYBaCfh5Nbd5+atn8HjKbzCm/Dg0VjO2xiUiLi8bSYpGfP+7l1vrTPjpa4xP/wbpKYucCmKE5x+Wj2qR3ixeGhTESzt5JKJyyLDWmgl7tyLi2AFsufZ+F0TYhQJ9Q8CkLkap7+vwO14OwdY35sxZUsCdAnY10BQ7AlE1j7qzLGtRgAIUoAAFKEABClCAAhSgAAUoQIE+I1Dh9xlsNRuhqeszU+ZEKUABClCAAhSgABjscONDYNbXo2JPJhpKiyFarZBOb9EEBJwzgrQDiLGm+fA+pZcXvPyb2yz/4DE8cu1SaGxmXLdnPV4/fyEGjRqLKw9tgsnbFzsvvq21VnjeYSRtWIXioWOx49LbnV5FaGEOYnKy5ONaBIjIj0+Ud/OoHxSOG196CO/9/k3YFUqn67EhBfqSQHHg61BU7IGmvi/NmnOlgBsFBKAuIRxDK//ixqIsRQEKUIACFKAABShAAQpQgAIUoAAF+oaAXTAhf/Df4Z9TDsHeN+bMWVKAAhSgAAUoQAFJgMGOXngOzPV1yP3yE3lkv+gYRM9Lln/95J3j8PwLm2EICME1bz6Ony67E+VR8VBZTJi//An8PHsBjo+e3jpjpdUihzuCyguQnpKKyiFxnVrN4JLjcshD2slDbW6Cb20l9s28CllzbuhUHTamQF8QqPPZBYP1U+iKmeroC/eLc+w+gfoRoYiq+yOUdl33DcLKFKAABShAAQpQgAIUoAAFKEABClDAAwUM3gdQZ1sJXYnBA2fHKVGAAhSgAAUoQIH2BRjs6IWnw5lgx+Stn0Fht2H33JvkGUacOIjZX76MNYuXoSFg8BmzTtizBUlpK7Hz4ltxeMqlLq1ICofM+PYdxB7JRHVoFApadvIoihvvUj12ooAnCZjVFSj2fwl+x8qhsHrSzDgXCvS8gGFoMMKMD8LLEtrzg3NEClCAAhSgAAUoQAEKUIACFKAABSjQiwKlAcuhKNsFdUMvToJDU4ACFKAABShAARcEGOxwAa2rXZwJdgSXHMcFa17Hl/f+s3W4idtXI6QoFxtv/N05UwiqKJTDHQ3+g5CesghmTed/Elunr8G1//sDvrnzr/IuHtE5WQioLpWPasmPn4yC+EldXTr7U6BXBEoDVgBVO3luZq/oc1BPE2iIDMBg8V54mzq3y5OnrYPzoQAFKEABClCAAhSgAAUoQAEKUIACnRGwqGpQ4vcf+OWWd6Yb21KAAhSgAAUoQAGPEGCwoxdugzPBDmla173+GLZd/StUDhnWOsuLP3kOFZEjsHfW1W3OfMqmjzD0l11IT05F0fAJnV5dyvtP4+C0lNYQh29thRzyiMnJxODSvFMhj4TJsCuUna7PDhToaQG97mfUiR/Dp7C2p4fmeBTwSIHGUC38NUvg18gdmTzyBnFSFKAABShAAQpQgAIUoAAFKEABCnSLQJ3PDjQ0vQfvCku31GdRClCAAhSgAAUo0J0CDHZ0p247tZ0NdkghDZtKjZ8vvL61km9dJeavWIrN1/4GJUPHtjlC7JHd8u4dRybNw88XXtepFY7ZtQHSsSzbr7jrnH7Sjh4nQx5h+UdQ0LKTh7Sjh1Wt6dQ4bEyBnhCQUvhFgS/A93gZlOaeGJFjUMDzBYxBgLffQgQ2nO/5k+UMKUABClCAAhSgAAUoQAEKUIACFKCAmwQKA/8DTdERqIxuKsgyFKAABShAAQpQoAcFGOzoQeyTQzkb7AgtzJEDGqvv+vsZsxx2aAcmbfsca5Y81W6gQmeoxYy0lVBZzPLRLPqgUKdWKu3QcdXbf8aHD7/aYXttox4x2ZmIyclCVO7e1p088hMSYdZ2/hgYpybHRhTopEC5//uw1f4/e3ceZ3la14f+c5aqU3tVb9V79+xswwDDEhABN66oIXoTlyhBFo3GfXldYzCJud5rNBqjRo1bAHEXb5KLioqgICow7AzrMHvv3dXVXV37es7Jq7qHYYCZ7urpWs45v3e9OK+q7np+z/P9vJ8H/pj58vz+Pj0TV/mg4QQ6WGBxMKnueEl2Tn9dB6cUjQABAgQIECBAgAABAgQIECDwWYGF7hM5W/u1DDw4joUAAQIECBAg0JYCGju2YNvW2tixWtrX/+oP52++/ocyMXrwcyp9ztt+P7WF2fz9S7/jsgme+p4357Z3/WnueMkrc9+tX7SmtF/9O/9v7vzir8uJG9Z2TX/34nwOPtTksXqjx+pzq7d4HLv5mZnvH1rTmgYRWG+Bmd6P50L5D9J/9Px6T20+Am0tsNybNPY+J3smX93WORRPgAABAgQIECBAgAABAgQIEFirwLmBv8zS1J/4P4CtFcw4AgQIECBAoOUENHZswZasNnaMffgDD6984EVffvHnH3/Vrfn5X3xHZoZ3Pfy71QaOxb6B3Pn8r/2CSv/xG34i99z2gnz69i+7bIo9R+/Kc9/y2zl9+Em54yu/9YqJb73jzzN44ezFmz6u9quysnzpJo+7P3TxNo+xAzdn9RaPozffntmh7Vc7nfEEHpdAvTKd4yO/mL6jJx71asVSqT/N5uzjmttDBNpdoN6dLBx6Qg5M/FC7R1E/AQIECBAgQIAAAQIECBAgQGBNAkd2/GQG7j+e8sqahhtEgAABAgQIEGg5AY0dLbQlj9bYsefIp/Lst/9R/uxVP/EFle44/WBe+vofv/hKlvO7D182Sbm+kue95bez/cyR3PGSV+Tsvhsfc/zwuVN5ye//dN74/b90TTqlZuNSg8fdH8rBez508daRzzR5rPXVMNdUgIcLK3B28H9keeqv0/sYl3WUSr1pNucL6yN4sQWa5WT6pn05fO7Hiw0hPQECBAgQIECAAAECBAgQIFAIgbmee3K+9Lr0H79QiLxCEiBAgAABAp0poLGjhfb10Ro7Vsv7xl/+/vzVt7wmkzv2fkG1T/zgX+fGj787f/6Ktf0Luls+8s4896/ekA982T/PJ5/9lY+Z/qW/9R/ygS/7ppw6/OR1Ezpw70cevsljemTXw00ek2tamjoAACAASURBVDv3rdsaJiIw23NXzld/LwNHHvt9maVST5rNBVgECiswddNoDk7+WMqNnsIaCE6AAAECBAgQIECAAAECBAgUQ2Bs6A/TGH9natPFyCslAQIECBAg0JkCGjtaaF8fq7Fj9aaNmeGd+djzvuZRq33hn/56FvqG8r6v+JY1pRk5eyLP+6s3ZG5gJHe85JVZ7On/gue6F2az9Ch/v6YF1jBo3wMff7jJY75vKMduuT1Hb7k950cPreFpQwg8ukCjvJDjI7+Q3uNHUr3MhRylUneazSWMBAorMH3dzuyd/8F0rewsrIHgBAgQIECAAAECBAgQIECAQOcL1MtzObbtP2X4nrGk2fl5JSRAgAABAgQ6V0BjRwvt7WM1duy//2N52j+8KX/xrf/+UavtWlrIP3ndv88Hv+Qb8uCTnrPmRM96xxtz/Sffm/e85BU5fuPT1vzceg/cc/Suh1/XUq92X2zwWP2M771hvZcyX4cLjA/+WZZm/iq9416W2eFbLd41CsweGMmOxneld/Hyr/G6xmU8ToAAAQIECBAgQIAAAQIECBDYUoHzB96ZmcX/lcG7Fre0DosTIECAAAECBK5VQGPHtQqu4/OP1dixusQ3/+J3582v/ImsvsLk0b5Wb8B40Z/8av701T+Z2aHta67q0N0fzPPe8obc/fQvyYdf+M/W/NxGDdx14t5LN3nc/cGUms2HmzzGDtyyUUuatwMEVnqmcmH/2zM/8Z4M3DPZAYlEILCxAnO7ezPc9e0ZmH/Kxi5kdgIECBAgQIAAAQIECBAgQIDAFgqceNovpvvDd6U6sYVFWJoAAQIECBAgsA4CGjvWAXG9prhcY8fz//x1mdh1IJ98zlc+5nJP/4c3Zeep+/PX3/DDV1VS7+zkxeaO1Zs/3vOVr8zU9t1X9fxGDd5x+sGHmzy6Fucffl3LqcNP3qglzdtmAo3KUiYPvDeTe96W7nvOpuf+Zkr1NguhXAJbIDC/PekffGWGZ567BatbkgABAgQIECBAgAABAgQIECCw8QLz2x/IuV2vTf+7z238YlYgQIAAAQIECGywgMaODQa+mukv19hx8J4P5ynv+8u85WU/dtkpX/zGn8uZg7fko1/0T65m6Ytjb73jz7PaHLLa3HHfU59/1c9v5APbzh6/eIvHwbs/lP7piYdv8jhxw20buay5W1hgav+Hc2HvX6Ry4mx67l1IeaGFi1UagRYTWBxKurZ/TXZMv7TFKlMOAQIECBAgQIAAAQIECBAgQGB9BMae8AdpHP271I6vz3xmIUCAAAECBAhspUDpu9/z5uaVClgunUt5pieVpf7LDl0aOZNqeSTlZu2y4xZLJ9N1YTTlRvWy4xZ2HUttZX9KKV923Hz5wfSeu+5KMTK/54H0Ll5/xXFz5fvTd+6GK4/be1/6Fm688rjyfek7d+VxP/vN35Rf+uX/lOM3P3qN3/5vfzp/+K+/J2e3jT9mfYMXLuQbf+038pZ//o2557lJ39KV886XHkzv+Ut+e48czQvf/OacOnw4f/ePv+az2UrNzI8eS+/SocvmbWYli40z6Zncf9lxja7FLI9cSG3l8reD1EtzqS/Op3t2x8PzjZw7l+vvuivX3fXpbBsfzwNPfGLe9dJnZ3a0L1314cuuu3qWSzM9qV7hLK9OUuqvpm/i5pRXeq64xwZsnsDs7k9lYu9fpjRxKrV7plOZ3ry1rUSgUwSW+5LGnudlz+QrOiWSHAQIECBAgAABAgQIECBAgACBhwWWeydy8km/kKG3jVEhQIAAAQIECHSEQOnl7/y6KzZ2rFSaKU0nlfnSZUOvjDZSLpVSXrn8uOVKI5UL5ZSXLm+4vL+R6nL5iq9WWKo20jW+hnGHG+maK6fUuPy6q/N1n7l8M8nqDEvXNdI9vYZxa5zvS957X/72qx+7AWT4/GImt9eyWG2kdpn6nviJ8dz11J1ZPNBIbfby9TVLyXKpme6zn92zcqOZ/cemc+zw0MNQze5keXcz3XOX39uL8zWa6T5/+XGN1X+puL2Z6hXOVKOcNBabqU49+nzDFxZz493n8/4X70n6k8riFc7o6lmeSSpXyFEfbKY5OpDmSE+65velb/rW9EwevtSw0rzynnfE/zq0WIjVqxMn9v1VGgtH0n3vRLrcoNhiO6ScdhKodyeLB5+U/Rd+oJ3KVisBAgQIECBAgAABAgQIECBAYE0CE4ffmfnZP07vp723eU1gBhEgQIAAAQItL1D6jt946RUbO1o+hQIJbKDAyvZkeXsp9V3bUt/WnZ6p6x9q9DiQ7unL3ziygWV1/NQrleksV85npXo+U9e/K43m6XTfM57u0x0fXUACGy6w2p82fdOBHD737zZ8LQsQIECAAAECBAgQIECAAAECBDZVoNTM0Wf+VPr+4Vgqs5u6ssUIECBAgAABAhsmoLFjw2ivfuJK9VDqK0ev/kFPbJpAs5qsNnqs7OhKfddwmpXudB3Zm2pjW6rNXak2RlKp96fSGEi1MZBKfWDTamvXherluSxXz1/8LJVPZKlyPMvVsaS+mPLicsqLM6kPL2fg3nZNqG4CrSkwdfNoDk78u5RXr2TyRYAAAQIECBAgQIAAAQIECBDoEIGZ3Z/Ihd7fTv8HpzokkRgECBAgQIAAgURjh1NA4BoEVvqTNJJG9dKnWe1Os6snja6uNKuVi3+32uRRqpXTNTyaUrOWcr07pUYt5WYtpUZPyo1aSvVqSo1qljOR2oU9SUpJs5RSVl/7Ukrp4utfVl8zU06pWcrS4Hi6l0cvVr46Khfv3fnMa2g+++fVGy+65rZfNuHqU8t9E6nWt+XiRBen+cxFPpf+3Hzoz0uVs+me25Hmaug00iytjmtc+nNpddSlv1/YdSTd9T1pVJbSKM+nUZlL8+L31c9CGuWFNCqLaZy6kOZyM5WllZQW5lJZXEhlKRc/JbckXsPJ9CiBKwtMX78re+d+KF2r3Wq+CBAgQIAAAQIECBAgQIAAAQIdInDy1l9P9ZMfSdfZDgkkBgECBAgQIEBg9d8EexVL+52DSmVP6nXvo2iXnVtt7ljamVRWkmYlSeXS94d/LpeS6moHSCXLlUaqY91JabW7opTm6veLjRaX/nyp36OU5uBSSiO1zyW4+Mwj+jtW2zOmF1K60HNFqubwfEpDvZ8d9/ALmpoXG0wuNnqs/mdyLqXp3tUejqS52sSx+n31F83Vai/9nGZW9iyma7GcLC+ntNK82KRRWrn0ySN+Xh1enbtieWseUC6PpNG4sObxBhIossDsgW3ZWf/u9CwdLDKD7AQIECBAgAABAgQIECBAgEAHCSwOn8jYwV/PwDt1dXTQtopCgAABAgQIaOxozzNQroymUR9rz+JVTWADBUrlwTQb0xu4gqkJdI7A3J7+jFS/Pf3zT+qcUJIQIECAAAECBAgQIECAAAEChRYYv+lNWT7zlvQ8WGgG4QkQIECAAIEOFHBjRwdu6mcilcs70mic6+CEohH4XIFSqT/N5iwWAgTWIDC/o5T+/ldnePbZaxhtCAECBAgQIECAAAECBAgQIECgtQXq3bM59oyfydBbxy7dHOyLAAECBAgQINBBAho7OmgzPz9KubwtjcZEBycUrd0FKpV9qddPtnsM9RNoS4HF4aRr5GuzY+ar2rJ+RRMgQIAAAQIECBAgQIAAAQIEHikwefADmV35vfR+fAEMAQIECBAgQKDjBDR2dNyWXn2gcnk4jcbk1T/oCQLXKFCu7E6jfuaKs7h95opEBhC4aoHl/qQ5+oLsnnrZVT/rAQIECBAgQIAAAQIECBAgQIBAqwkcf8bPpfb+e1P1j7pbbWvUQ4AAAQIECKyDgMaOdUBs9ylKpcE0m9PtHkP9HSxQLo+k0bjQwQlFI7D5AvVasnTg1uy78L2bv7gVCRAgQIAAAQIECBAgQIAAAQLrKDC3896c3/a69N/hBut1ZDUVAQIECBAg0EICGjtaaDO2qpRSqT/N5uwVly+V+tJszl1xnAEECBAg0PoCjUoye8OhHDr/Y61frAoJECBAgAABAgQIECBAgAABApcROP2k307p/vek21ufnRMCBAgQIECgQwU0dnToxm5ErFKpN83m/EZMbU4CBAgQ2AKByVtGc/j8j6fUrG7B6pYkQIAAAQIECBAgQIAAAQIECFy7wFL/eE7f/EsZ/Juxa5/MDAQIECBAgACBFhXQ2NGiG9OKZZVKtTSbi61YmpoIECBA4HEITN+wK/tm/q9U68OP42mPECBAgAABAgQIECBAgAABAgS2XuD89W/LwoX/md57t74WFRAgQIAAAQIENkpAY8dGyXbgvKVSd5rNpSsmW+u4K05kAAECBAhsqMDMoe0ZXf6e1Jb2b+g6JidAgAABAgQIECBAgAABAgQIbIRAs7ySo8/6qQy842TKCxuxgjkJECBAgAABAq0hoLGjNfaho6oolbrSbC53VCZhCBAg0IkCc3sHMlL+l+lfeEInxpOJAAECBAgQIECAAAECBAgQ6HCB6b0fzVTX76TvwzMdnlQ8AgQIECBAoOgCGjuKfgI2JH8lSX0NM6913BqmMoQAAQIErlpgfmc1A32vztDs7Vf9rAcIECBAgAABAgQIECBAgAABAlstcPK2X0n1ox9P17mtrsT6BAgQIECAAIGNFdDYsbG+BZ29nKSxhuxrHbeGqQwhQIAAgasWWBhJasP/LNtnXnzVz3qAAAECBAgQIECAAAECBAgQILCVAgvbjubsnt/MwD+Mb2UZ1iZAgAABAgQIbIqAxo5NYbbIowustbGjlKQJkQABAgTWWWBpICnt/JKMTv/zdZ7ZdAQIECBAgAABAgQIECBAgACBjRU4e8sfp37i7akd3dh1zE6AAAECBAgQaAUBjR2tsAuFrWGtDRtrHVdYSMEJECDwuARWepLlfU/LvsnvelzPe4gAAQIECBAgQIAAAQIECBAgsBUCi31jOf3kX8nQ28bWdnn0VhRpTQIECBAgQIDAOgpo7FhHTFNtlIDGjo2SNS8BAsUWaFSTueuvz8HzP1psCOkJECBAgAABAgQIECBAgACBthI4PfxbWckH0n9/va3qViwBAgQIECBA4PEKaOx4vHKeI0CAAAECHSAw+YTRXDf+fydZfT2WLwIECBAgQIAAAQIECBAgQIBAawuMD/5pFuf/Nn1n5lq7UNURIECAAAECBNZRQGPHOmKaigABAgQItJvA9I2j2Tf9I6nWB9utdPUSIECAAAECBAgQIECAAAECBRO4MPDuzNT/LP3HJwqWXFwCBAgQIECg6AIaO4p+AuQnQIAAgUILzB7akV1L35va8t5COwhPgAABAgQIECBAgAABAgQItLbATO/HMlH94/QfO5uSN7C09mapjgABAgQIEFh3AY0d605qQgIECBAg0D4Cc/sGs630HelbuLl9ilYpAQIECBAgQIAAAQIECBAgUCiB+doDGev/rfQfGUtlqVDRhSVAgAABAgQIXBTQ2OEgECBAgACBAgvM7+rKYM+3ZXDu6QVWEJ0AAQIECBAgQIAAAQIECBBoVYGlrrM5NfRr6T1+Ml1zrVqluggQIECAAAECGyugsWNjfc1OgAABAgRaWmBhJOkZ/qZsm/nSlq5TcQQIECBAgAABAgQIECBAgEDxBOrluZwa/o1Uxz6d2lTx8ktMgAABAgQIEPiMgMYOZ4EAAQIECBRYYGkgKe/88uya/oYCK4hOgAABAgQIECBAgAABAgQItKLA6aHXpzH5vvSeb8Xq1ESAAAECBAgQ2DwBjR2bZ20lAgQIECDQcgIrPcnKvtuzd/I7Wq42BREgQIAAAQIECBAgQIAAAQLFFRgffFMW59+ZvjPzxUWQnAABAgQIECDwkIDGDkeBAAECBAgUWKDRlcwfvjEHJn6kwAqiEyBAgAABAgQIECBAgAABAq0kcKH/XZlp/Fn6j19opbLUQoAAAQIECBDYMgGNHVtGb2ECBAgQINACAqVk8pbduW78J1qgGCUQIECAAAECBAgQIECAAAECRReY7vtYLlTemP6j4yk1iq4hPwECBAgQIEDgkoDGDieBAAECBAgUXGDqptEcmPzRVBr9BZcQnwABAgQIECBAgAABAgQIENgqgeXeiUyO3pHZmXel/8HxVJa2qhLrEiBAgAABAgRaT0BjR+vtiYoIECBAgMCmCswc3pndi9+X7uXdm7quxQgQIECAAAECBAgQIECAAAECczvuz8zO92S+/9PpOno+XSdXUp3mQoAAAQIECBAg8EgBjR3OAwECBAgQKLjA7P6hbG/+q/Qt3lBwCfEJECBAgAABAgQIECBAgACBzRCod89mdvRTmdr5d2nOjV9s6Kid2IyVrUGAAAECBAgQaE8BjR3tuW+qJkCAAAEC6yYwN1rLUO3bMjh327rNaSICBAgQIECAAAECBAgQIECAwOcLLAwfz8yu92dmx4fTfXQqXccWUp3kRIAAAQIECBAgcCUBjR1XEvJ7AgQIECDQ4QIL25KeoZdl28wLOjypeAQIECBAgAABAgQIECBAgMBmCdTLs1muTlz6lE9l9sYPJSszqR4Zv3g7R2llsyqxDgECBAgQIECg/QU0drT/HkpAgAABAgSuSWBpMKns+MrsnP4/r2keDxMgQIAAAQIECBAgQIAAAQLFE1jqGUu9OZ+VyvksVU5mqXwiy5XxNJsLKS+tpLI4l9LiQpoDSe/x4vlITIAAAQIECBBYDwGNHeuhaA4CBAgQINDGAsu9SWPvs7Nn8tvaOIXSCRAgQIAAAQIECBAgQIAAgc0SWBo8k7nt92V2+AOpnz6R8nQ55cXZlJeWUllKyquf+mZVYx0CBAgQIECAQOcLaOzo/D2WkAABAgQIXFag3pUsHL4lByZ+mBQBAgQIECBAgAABAgQIECBA4FEFFodPZG7b3Zkd+XCaKxOpnD6frjP1VC8AI0CAAAECBAgQ2GgBjR0bLWx+AgQIECDQ4gLNUjJ9894cPvcfWrxS5REgQIAAAQIECBAgQIAAAQKbKbAwcjRz2z6V2W13JgtTqZwaT/dYUpnazCqsRYAAAQIECBAgoLHDGSBAgAABAgQyddNoDk6+JuVGLw0CBAgQIECAAAECBAgQIECg4ALL1Ymcvu4XU6qspHLqXLpWmzlmC44iPgECBAgQIEBgCwU0dmwhvqUJECBAgECrCMxctzO7538g3Su7WqUkdRAgQIAAAQIECBAgQIAAAQJbJDA++KYsLr4lfae2qADLEiBAgAABAgQIfI6Axg4HggABAgQIEMjsgeHsaHxXehevo0GAAAECBAgQIECAAAECBAgUWGCx+0TO9P5GBu8fK7CC6AQIECBAgACB1hLQ2NFa+6EaAgQIECCwJQLzu3sz1PVtGZi/dUvWtygBAgQIECBAgAABAgQIECDQGgKnh9+QjN+R2lRr1KMKAgQIECBAgACBRGOHU0CAAAECBAhkfnvSP/iKDM88jwYBAgQIECBAgAABAgQIECBQUIG5nntyrvKGDBw9V1ABsQkQIECAAAECrSmgsaM190VVBAgQIEBgUwXm9ifN/U/Ogfu+f1PXtRgBAgQIECBAgAABAgQIECDQOgInRn4pXac/ma7Z1qlJJQQIECBAgAABAm7scAYIECBAgACBJPWBZP45h3PwztfwIECAAAECBAgQIECAAAECBAooMN33kUw2/iD9J7yDpYDbLzIBAgQIECDQ4gJu7GjxDVIeAQIECBDYLIGpL9+W/Xf9m1QXhjdrSesQIECAAAECBAgQIECAAAECLSDQKC3l+LafS+/Ro6kutkBBSiBAgAABAgQIEPgcAY0dDgQBAgQIECBwUWDu6T0ZXvqODJx5MhECBAgQIECAAAECBAgQIECgQAITA3+X+fn/ld6xhQKlFpUAAQIECBAg0D4CGjvaZ69USoAAAQIENlRg8UBS3f+S7Lz36zZ0HZMTIECAAAECBAgQIECAAAECrSOwUrmQ4yM/n8H7x1JeaZ26VEKAAAECBAgQIPBZAY0dTgMBAgQIECBwUaDel8w//4Yc/NC/JkKAAAECBAgQIECAAAECBAgURGB88E+yNPWX6T1fkMBiEiBAgAABAgTaUEBjRxtumpIJECBAgMBGCUx/6a7svfeH0jW3faOWMC8BAgQIECBAgAABAgQIECDQIgKL3Sdzpu/XM3jfWItUpAwCBAgQIECAAIFHE9DY4VwQIECAAAECDwvM3daX4fqrMnD6qVQIECBAgAABAgQIECBAgACBDhc4Pfzbyfh7Upvq8KDiESBAgAABAgTaXEBjR5tvoPIJECBAgMB6CizuTyqHvjy77v6G9ZzWXAQIECBAgAABAgQIECBAgECLCcz13JNz1Tdk4Mi5FqtMOQQIECBAgAABAp8voLHDmSBAgAABAgQeFmj0JrMvOJxDH3wNFQIECBAgQIAAAQIECBAgQKCDBU6M/HK6Tn8iXbMdHFI0AgQIECBAgECHCGjs6JCNFIMAAQIECKyXwMyLdmX3A9+f7tld6zWleQgQIECAAAECBAgQIECAAIEWEpjuuzOTjT9I/4nJFqpKKQQIECBAgAABAo8loLHD2SBAgAABAgQ+R2D+1p4Mll6ZwZNPJ0OAAAECBAgQIECAAAECBAh0mECztJxj234uvUePpLrYYeHEIUCAAAECBAh0qIDGjg7dWLEIECBAgMDjFVjam5Suf1FGP/3Nj3cKzxEgQIAAAQIECBAgQIAAAQItKnCh/x8yt/g/0ntmoUUrVBYBAgQIECBAgMDnC2jscCYIECBAgACBzxFo1JLZLz2QQ+//d2QIECBAgAABAgQIECBAgACBDhJY6ZrOye0/lf67J1Je6aBgohAgQIAAAQIEOlxAY0eHb7B4BAgQIEBgrQKlUleazeWLw2desDOjx743tek9a33cOAIECBAgQIAAAQIECBAgQKDFBea3P5Czwz+TwQ+0eKHKI0CAAAECBAgQ+BwBjR0OBAECBAgQIPCQQDXJpf+7zvyTujPQ/coMHb+dDgECBAgQIECAAAECBAgQINAhAhPX/W0WLvxReu7rkEBiECBAgAABAgQKIqCxoyAbLSYBAgQIELiyQCVJ/eKwpd1Jbnp+dt/18is/ZgQBAgQIECBAgAABAgQIECDQFgInb/3VdH30o6lOtEW5iiRAgAABAgQIEHhIQGOHo0CAAAECBAg8JFBO0rj4c7Mrmf6KfTn8vh+nQ4AAAQIECBAgQIAAAQIECHSAQKO6kGPP+KkMvWWsA9KIQIAAAQIECBAoloDGjmLtt7QECBAgQOAyAqXVlo6Hfz/z/B0ZPfk9qU3to0aAAAECBAgQIECAAAECBAi0ucD8jvtzbuQ30/++C22eRPkECBAgQIAAgeIJaOwo3p5LTIAAAQIE1iQw/8Rq+ntekeFjz17TeIMIECBAgAABAgQIECBAgACB1hWYuP7tWTj/x+m5v3VrVBkBAgQIECBAgMCjC2jscDIIECBAgACBRxVY3pU0nvCc7PnUqwkRIECAAAECBAgQIECAAAECbS5w8qn/LV0f+ViqLuxo851UPgECBAgQIFBEAY0dRdx1mQkQIECAwBoEmpVk6iW7c/i9/yGlZnkNTxhCgAABAgQIECBAgAABAgQItKJAvWs+x5/20xn6q7FWLE9NBAgQIECAAAECVxDQ2OGIECBAgAABAo8pMPO87dk19l3puXCQEgECBAgQIECAAAECBAgQINCmAnM77835odem//2u62jTLVQ2AQIECBAgUHABjR0FPwDiEyBAgACBywnM31xK/+DLM3zki0ARIECAAAECBAgQIECAAAECbSpw/vq3ZfHc/0zPA20aQNkECBAgQIAAgYILaOwo+AEQnwABAgQIXE5geUdSf8rt2fuJ7wBFgAABAgQIECBAgAABAgQItKnAidt+Od0f+kSqk20aQNkECBAgQIAAgYILaOwo+AEQnwABAgQIXFaglEx+1WgOf+Dfp1TvgkWAAAECBAgQIECAAAECBAi0mUC9ezbHn/ozGXrrWJtVrlwCBAgQIECAAIHPCGjscBYIECBAgACBywrM/qNt2XHuO9M7cR0pAgQIECBAgAABAgQIECBAoM0E5nbek/ODr03/B1zX0WZbp1wCBAgQIECAwMMCGjscBgIECBAgQOCyAvM3Jr3D35xtR15EigABAgQIECBAgAABAgQIEGgzgfM3/FUWz/7/6XmwzQpXLgECBAgQIECAwMMCGjscBgIECBAgQOCyAivbkuXbnpZ9H/8uUgQIECBAgAABAgQIECBAgECbCZx42n9N7QOfSmWqzQpXLgECBAgQIECAwMMCGjscBgIECBAgQOCKAlMvGc3BD/9Yyis9VxxrAAECBAgQIECAAAECBAgQINAaAvXaTI4/5Wcz9Lax1ihIFQQIECBAgAABAo9LQGPH42LzEAECBAgQKJbA7LNHsn3yX6bv3I3FCi4tAQIECBAgQIAAAQIECBBoY4HZXXfnQt9r0/ch13W08TYqnQABAgQIECAQjR0OAQECBAgQIHBFgYXrk9qOr8/2B77iimMNIECAAAECBAgQIECAAAECBFpD4NwNf5GlsT9Nz5HWqEcVBAgQIECA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gMaOYu671AQIECBAgACBDhaoJln5nHwr25Olpz8p++/8gQ7OLRoBAgQIECBAgECRBC4cflfmZv8gvZ+uFym2rAQIECBAgAABAgQKKaCxo5DbLjQBAgQIECBAoJMFVl+38oX/cHvmi7Zn5/i3p/fcDZ0cXjYCBAgQIECAAIGCCBx/+s+n9v67U50qSGAxCRAgQIAAAQIECBRYQGNHgTdfdAIECBAgQIBAZwqUkjS/INrSviTXf1F23/WtnRlbKgIECBAgQIAAgcIILAwfz9n9v5aBvz9XmMyCEiBAgAABAgQIECiygMaOIu++7AQIECBAgACBgglMf9mu7Lnv+9I9M1qw5OISIECAAAECBAh0ksC5G/4yS+N/kp4HOimVLAQIECBAgAABAgQIPJaAxg5ngwABAgQIECBAoDACCzck3Ttfmh33fU1hMgtKgAABAgQIECDQeQJHn/Uf0/93x1Ke77xsEhEgQIAAAQIECBAg8IUCGjucCgIECBAgQIAAgcIINLuSqReP5uCH/k0qy32FyS0oAQIECBAgQIBA5wjM7bw350dem/73XuicUJIQIECAAAECBAgQIHBZAY0dDggBAgQIECBAgEChBOZu7clA9WUZPvbsQuUWlgABAgQIECBAoDMExm754zSOvT21452RRwoCBAgQIECAAAECBK4soLHjykZGECBAgAABAgQIdJBAfTCZf+71OfihH+2gVKIQIECAAAECBAgUQaBRXczRZ/7HDL11LKWVIiSWkQABAgQIECBAgACBVQGNHc4BAQIECBAgQIBA4QRmnz2ckZmXZWDstsJlF5gAAQIECBAgQKB9BWb2fDyT3W9I34dn2jeEygkQIECAAAECBAgQuGoBjR1XTeYBAgQIECBAgACBdheYP5CUup6RvVPf2e5R1E+AAAECBAgQIFAggdNPfn1Kd78v3WcKFFpUAgQIECBAgAABAgTc2OEMECBAgAABAgQIFFNg8uYdOXjhx1Jp9BcTQGoCBAgQIECAAIG2EljpmcyJJ/+XDL1trK3qViwBAgQIECBAgAABAtcu4MaOazc0AwECBAgQIECAQBsKzO3pzXD11RmYf2obVq9kAgQIECBAgACBoglMHfhAppd/N32fXCxadHkJECBAgAABAgQIFF5AY0fhjwAAAgQIECBAgEAxBZYGkuboc7Nn8pXFBJCaAAECBAgQ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"} \ No newline at end of file diff --git a/base_envs_set/03_Hard_parkour.json b/base_envs_set/03_Hard_parkour.json new file mode 100644 index 0000000000000000000000000000000000000000..f66b9fac97dc94d766b8a021c553920d7695f64e --- /dev/null +++ b/base_envs_set/03_Hard_parkour.json @@ -0,0 +1 @@ +{"terrain":{"ground":[{"x":9.01243644198215,"y":3.333333333333334},{"x":9.113870729455217,"y":3.333333333333334},{"x":9.113870729455217,"y":3.333333333333334},{"x":9.215305016928285,"y":3.333333333333334},{"x":9.316739304401354,"y":3.231899045860265},{"x":9.418173591874423,"y":3.231899045860265},{"x":9.519607879347491,"y":3.231899045860265},{"x":9.62104216682056,"y":3.231899045860265},{"x":9.722476454293629,"y":3.1304647583871965},{"x":9.925345029239766,"y":3.1304647583871965},{"x":10.128213604185904,"y":3.029030470914128},{"x":10.331082179132041,"y":3.029030470914128},{"x":10.635385041551247,"y":3.029030470914128},{"x":10.838253616497385,"y":3.029030470914128},{"x":11.14255647891659,"y":3.029030470914128},{"x":11.345425053862728,"y":3.029030470914128},{"x":11.446859341335797,"y":3.029030470914128},{"x":11.548293628808866,"y":3.029030470914128},{"x":11.548293628808866,"y":3.029030470914128},{"x":11.649727916281934,"y":3.029030470914128},{"x":11.751162203755003,"y":3.029030470914128},{"x":11.852596491228072,"y":3.029030470914128},{"x":11.95403077870114,"y":3.029030470914128},{"x":11.95403077870114,"y":3.029030470914128},{"x":12.156899353647276,"y":2.927596183441059},{"x":12.359767928593413,"y":2.927596183441059},{"x":12.461202216066482,"y":2.927596183441059},{"x":12.56263650353955,"y":2.927596183441059},{"x":12.66407079101262,"y":2.927596183441059},{"x":12.765505078485688,"y":2.927596183441059},{"x":12.765505078485688,"y":2.927596183441059},{"x":12.866939365958757,"y":2.927596183441059},{"x":12.968373653431826,"y":2.927596183441059},{"x":13.069807940904894,"y":2.927596183441059},{"x":13.171242228377963,"y":2.927596183441059},{"x":13.171242228377963,"y":2.927596183441059},{"x":13.272676515851032,"y":2.927596183441059},{"x":13.47554509079717,"y":2.927596183441059},{"x":13.576979378270238,"y":2.8261618959679904},{"x":13.678413665743307,"y":2.8261618959679904},{"x":13.881282240689444,"y":2.8261618959679904},{"x":13.982716528162513,"y":2.8261618959679904},{"x":14.084150815635581,"y":2.8261618959679904},{"x":14.18558510310865,"y":2.8261618959679904},{"x":14.287019390581719,"y":2.8261618959679904},{"x":14.388453678054788,"y":2.8261618959679904},{"x":14.388453678054788,"y":2.7247276084949217},{"x":14.388453678054788,"y":2.7247276084949217},{"x":14.489887965527856,"y":2.7247276084949217},{"x":14.591322253000925,"y":2.7247276084949217},{"x":14.692756540473994,"y":2.7247276084949217},{"x":14.794190827947062,"y":2.7247276084949217},{"x":14.794190827947062,"y":2.623293321021853},{"x":14.895625115420131,"y":2.623293321021853},{"x":14.9970594028932,"y":2.623293321021853},{"x":15.098493690366267,"y":2.623293321021853},{"x":15.199927977839335,"y":2.5218590335487843},{"x":15.199927977839335,"y":2.5218590335487843},{"x":15.301362265312404,"y":2.5218590335487843},{"x":15.402796552785473,"y":2.5218590335487843},{"x":15.504230840258542,"y":2.5218590335487843},{"x":15.60566512773161,"y":2.5218590335487843},{"x":15.60566512773161,"y":2.5218590335487843},{"x":15.707099415204679,"y":2.5218590335487843},{"x":15.808533702677748,"y":2.5218590335487843},{"x":15.909967990150816,"y":2.4204247460757156},{"x":16.011402277623887,"y":2.4204247460757156},{"x":16.112836565096956,"y":2.4204247460757156},{"x":16.315705140043093,"y":2.4204247460757156},{"x":16.41713942751616,"y":2.4204247460757156},{"x":16.721442289935364,"y":2.4204247460757156},{"x":16.822876577408433,"y":2.4204247460757156},{"x":16.9243108648815,"y":2.4204247460757156},{"x":17.02574515235457,"y":2.4204247460757156},{"x":17.12717943982764,"y":2.4204247460757156},{"x":17.228613727300708,"y":2.4204247460757156},{"x":17.330048014773777,"y":2.4204247460757156},{"x":17.532916589719914,"y":2.318990458602647},{"x":17.634350877192983,"y":2.318990458602647},{"x":17.83721945213912,"y":2.318990458602647},{"x":17.93865373961219,"y":2.318990458602647},{"x":18.040088027085257,"y":2.217556171129578},{"x":18.141522314558326,"y":2.217556171129578},{"x":18.242956602031395,"y":2.217556171129578},{"x":18.344390889504464,"y":2.217556171129578},{"x":18.445825176977532,"y":2.1161218836565094},{"x":18.445825176977532,"y":2.1161218836565094},{"x":18.5472594644506,"y":2.1161218836565094},{"x":18.75012803939674,"y":2.1161218836565094},{"x":18.851562326869807,"y":2.1161218836565094},{"x":19.054430901815945,"y":2.1161218836565094},{"x":19.257299476762082,"y":2.1161218836565094},{"x":19.46016805170822,"y":2.1161218836565094},{"x":19.663036626654357,"y":2.1161218836565094},{"x":19.764470914127426,"y":2.0146875961834407},{"x":19.967339489073563,"y":2.0146875961834407},{"x":20.1702080640197,"y":1.913253308710372},{"x":20.27164235149277,"y":1.913253308710372},{"x":20.373076638965838,"y":1.913253308710372},{"x":20.474510926438906,"y":1.8118190212373033},{"x":20.474510926438906,"y":1.8118190212373033},{"x":20.575945213911975,"y":1.7103847337642346},{"x":20.778813788858113,"y":1.7103847337642346},{"x":20.88024807633118,"y":1.7103847337642346},{"x":20.88024807633118,"y":1.7103847337642346},{"x":20.98168236380425,"y":1.7103847337642346},{"x":21.08311665127732,"y":1.7103847337642346},{"x":21.184550938750387,"y":1.7103847337642346},{"x":21.285985226223456,"y":1.7103847337642346},{"x":21.387419513696525,"y":1.7103847337642346},{"x":21.590288088642662,"y":1.7103847337642346},{"x":21.69172237611573,"y":1.608950446291166},{"x":21.89459095106187,"y":1.608950446291166},{"x":22.097459526008006,"y":1.608950446291166},{"x":22.300328100954143,"y":1.608950446291166},{"x":22.50319667590028,"y":1.608950446291166},{"x":22.50319667590028,"y":1.608950446291166},{"x":22.60463096337335,"y":1.608950446291166},{"x":22.706065250846414,"y":1.608950446291166},{"x":22.807499538319483,"y":1.608950446291166},{"x":22.908933825792552,"y":1.608950446291166},{"x":22.908933825792552,"y":1.608950446291166},{"x":23.01036811326562,"y":1.608950446291166},{"x":23.11180240073869,"y":1.608950446291166},{"x":23.213236688211758,"y":1.5075161588180972},{"x":23.314670975684827,"y":1.5075161588180972},{"x":23.314670975684827,"y":1.5075161588180972},{"x":23.416105263157895,"y":1.5075161588180972},{"x":23.517539550630964,"y":1.5075161588180972},{"x":23.618973838104033,"y":1.5075161588180972},{"x":23.7204081255771,"y":1.5075161588180972},{"x":23.7204081255771,"y":1.5075161588180972},{"x":23.82184241305017,"y":1.5075161588180972},{"x":23.92327670052324,"y":1.4060818713450285},{"x":24.024710987996308,"y":1.4060818713450285},{"x":24.126145275469376,"y":1.4060818713450285},{"x":24.227579562942445,"y":1.4060818713450285},{"x":24.329013850415514,"y":1.4060818713450285},{"x":24.430448137888582,"y":1.4060818713450285},{"x":24.53188242536165,"y":1.4060818713450285},{"x":24.53188242536165,"y":1.4060818713450285},{"x":24.63331671283472,"y":1.3046475838719598},{"x":24.73475100030779,"y":1.3046475838719598},{"x":24.836185287780857,"y":1.3046475838719598},{"x":24.937619575253926,"y":1.3046475838719598},{"x":25.039053862726995,"y":1.3046475838719598},{"x":25.241922437673132,"y":1.3046475838719598},{"x":25.3433567251462,"y":1.203213296398891},{"x":25.3433567251462,"y":1.203213296398891},{"x":25.44479101261927,"y":1.203213296398891},{"x":25.54622530009234,"y":1.1017790089258224},{"x":25.647659587565407,"y":1.1017790089258224},{"x":25.749093875038476,"y":1.1017790089258224},{"x":25.749093875038476,"y":1.0003447214527537},{"x":25.850528162511544,"y":1.0003447214527537},{"x":25.951962449984613,"y":1.0003447214527537},{"x":26.053396737457685,"y":0.898910433979685},{"x":26.154831024930754,"y":0.898910433979685},{"x":26.35769959987689,"y":0.898910433979685},{"x":26.56056817482303,"y":0.898910433979685},{"x":26.56056817482303,"y":0.898910433979685},{"x":26.662002462296098,"y":0.7974761465066162},{"x":26.763436749769166,"y":0.7974761465066162},{"x":26.864871037242235,"y":0.7974761465066162},{"x":26.966305324715304,"y":0.7974761465066162},{"x":26.966305324715304,"y":0.7974761465066162},{"x":27.067739612188372,"y":0.6960418590335475},{"x":27.16917389966144,"y":0.6960418590335475},{"x":27.27060818713451,"y":0.6960418590335475},{"x":27.37204247460758,"y":0.6960418590335475},{"x":27.37204247460758,"y":0.6960418590335475},{"x":27.473476762080647,"y":0.5946075715604788},{"x":27.574911049553712,"y":0.5946075715604788},{"x":27.67634533702678,"y":0.5946075715604788},{"x":27.77777962449985,"y":0.5946075715604788},{"x":27.77777962449985,"y":0.5946075715604788},{"x":27.87921391197292,"y":0.5946075715604788},{"x":27.980648199445987,"y":0.5946075715604788},{"x":28.183516774392125,"y":0.4931732840874101},{"x":28.183516774392125,"y":0.4931732840874101},{"x":28.284951061865193,"y":0.4931732840874101},{"x":28.48781963681133,"y":0.4931732840874101},{"x":28.5892539242844,"y":0.3917389966143414},{"x":28.690688211757468,"y":0.3917389966143414},{"x":28.893556786703606,"y":0.3917389966143414},{"x":28.994991074176674,"y":0.2903047091412727},{"x":29.19785964912281,"y":0.2903047091412727},{"x":29.40072822406895,"y":0.188870421668204},{"x":29.603596799015087,"y":0.188870421668204},{"x":29.806465373961224,"y":0.188870421668204},{"x":29.806465373961224,"y":0.0874361341951353},{"x":29.907899661434293,"y":0.0874361341951353},{"x":30.00933394890736,"y":0.0874361341951353},{"x":30.11076823638043,"y":0.0874361341951353},{"x":30.2122025238535,"y":0.0874361341951353},{"x":30.313636811326568,"y":0.0874361341951353},{"x":30.617939673745774,"y":0.0874361341951353},{"x":30.719373961218842,"y":0.0874361341951353},{"x":31.02367682363805,"y":0.0874361341951353},{"x":31.125111111111117,"y":0.0874361341951353},{"x":31.429413973530323,"y":0.188870421668204},{"x":31.530848261003392,"y":0.188870421668204},{"x":31.73371683594953,"y":0.2903047091412727},{"x":31.835151123422598,"y":0.2903047091412727},{"x":31.936585410895667,"y":0.3917389966143414},{"x":32.038019698368736,"y":0.3917389966143414},{"x":32.24088827331487,"y":0.4931732840874101},{"x":32.34232256078794,"y":0.4931732840874101},{"x":32.64662542320715,"y":0.4931732840874101},{"x":32.849493998153285,"y":0.4931732840874101},{"x":33.05236257309942,"y":0.4931732840874101},{"x":33.4580997229917,"y":0.4931732840874101},{"x":33.660968297937835,"y":0.4931732840874101},{"x":33.86383687288397,"y":0.4931732840874101},{"x":34.06670544783011,"y":0.4931732840874101},{"x":34.26957402277625,"y":0.4931732840874101},{"x":34.371008310249316,"y":0.4931732840874101},{"x":34.57387688519545,"y":0.4931732840874101},{"x":34.77674546014159,"y":0.4931732840874101},{"x":34.97961403508773,"y":0.4931732840874101},{"x":35.0810483225608,"y":0.4931732840874101},{"x":35.182482610033865,"y":0.4931732840874101},{"x":35.38535118498,"y":0.4931732840874101},{"x":35.48678547245307,"y":0.4931732840874101},{"x":35.48678547245307,"y":0.4931732840874101},{"x":35.68965404739921,"y":0.4931732840874101},{"x":35.892522622345346,"y":0.4931732840874101},{"x":36.095391197291484,"y":0.4931732840874101},{"x":36.29825977223762,"y":0.4931732840874101},{"x":36.60256263465683,"y":0.4931732840874101},{"x":36.80543120960296,"y":0.4931732840874101},{"x":37.109734072022164,"y":0.4931732840874101},{"x":37.21116835949523,"y":0.4931732840874101},{"x":37.3126026469683,"y":0.4931732840874101},{"x":37.41403693444137,"y":0.4931732840874101},{"x":37.51547122191444,"y":0.4931732840874101},{"x":37.51547122191444,"y":0.4931732840874101},{"x":37.61690550938751,"y":0.4931732840874101},{"x":37.718339796860576,"y":0.3917389966143414},{"x":37.819774084333645,"y":0.3917389966143414},{"x":37.92120837180671,"y":0.2903047091412727},{"x":38.12407694675285,"y":0.2903047091412727},{"x":38.32694552169899,"y":0.2903047091412727},{"x":38.631248384118194,"y":0.2903047091412727},{"x":38.73268267159126,"y":0.2903047091412727},{"x":38.9355512465374,"y":0.2903047091412727},{"x":39.13841982148354,"y":0.2903047091412727},{"x":39.13841982148354,"y":0.2903047091412727},{"x":39.23985410895661,"y":0.2903047091412727},{"x":39.442722683902744,"y":0.2903047091412727},{"x":39.54415697137581,"y":0.2903047091412727},{"x":39.54415697137581,"y":0.2903047091412727},{"x":39.64559125884888,"y":0.2903047091412727},{"x":39.74702554632195,"y":0.2903047091412727},{"x":39.94989412126809,"y":0.2903047091412727},{"x":40.051328408741156,"y":0.2903047091412727},{"x":40.152762696214225,"y":0.2903047091412727},{"x":40.35563127116036,"y":0.3917389966143414},{"x":40.35563127116036,"y":0.3917389966143414},{"x":40.45706555863343,"y":0.3917389966143414},{"x":40.5584998461065,"y":0.4931732840874101},{"x":40.65993413357957,"y":0.4931732840874101},{"x":40.76136842105264,"y":0.4931732840874101},{"x":40.76136842105264,"y":0.4931732840874101},{"x":40.964236995998775,"y":0.4931732840874101},{"x":41.06567128347184,"y":0.4931732840874101},{"x":41.16710557094491,"y":0.5946075715604788},{"x":41.26853985841798,"y":0.5946075715604788},{"x":41.47140843336412,"y":0.6960418590335475},{"x":41.57284272083719,"y":0.6960418590335475},{"x":41.674277008310256,"y":0.7974761465066162},{"x":41.87714558325639,"y":0.7974761465066162},{"x":41.97857987072946,"y":0.7974761465066162},{"x":42.08001415820253,"y":0.898910433979685},{"x":42.1814484456756,"y":0.898910433979685},{"x":42.38431702062174,"y":0.898910433979685},{"x":42.38431702062174,"y":0.898910433979685},{"x":42.485751308094805,"y":1.0003447214527537},{"x":42.587185595567874,"y":1.1017790089258224},{"x":42.68861988304094,"y":1.1017790089258224},{"x":42.89148845798708,"y":1.1017790089258224},{"x":43.09435703293322,"y":1.203213296398891},{"x":43.195791320406286,"y":1.203213296398891},{"x":43.50009418282549,"y":1.3046475838719598},{"x":43.70296275777163,"y":1.3046475838719598},{"x":43.8043970452447,"y":1.3046475838719598},{"x":43.90583133271777,"y":1.4060818713450285},{"x":44.007265620190836,"y":1.4060818713450285},{"x":44.007265620190836,"y":1.4060818713450285},{"x":44.108699907663905,"y":1.4060818713450285},{"x":44.21013419513697,"y":1.4060818713450285},{"x":44.41300277008311,"y":1.4060818713450285},{"x":44.61587134502925,"y":1.4060818713450285},{"x":44.71730563250232,"y":1.4060818713450285},{"x":44.920174207448454,"y":1.4060818713450285},{"x":45.22447706986766,"y":1.4060818713450285},{"x":45.32591135734073,"y":1.4060818713450285},{"x":45.52877993228687,"y":1.4060818713450285},{"x":45.630214219759935,"y":1.4060818713450285},{"x":45.630214219759935,"y":1.4060818713450285},{"x":45.731648507233004,"y":1.4060818713450285},{"x":45.83308279470607,"y":1.4060818713450285},{"x":45.93451708217914,"y":1.4060818713450285},{"x":46.03595136965221,"y":1.4060818713450285},{"x":46.03595136965221,"y":1.4060818713450285},{"x":46.23881994459835,"y":1.4060818713450285},{"x":46.340254232071416,"y":1.4060818713450285},{"x":46.441688519544485,"y":1.3046475838719598},{"x":46.543122807017554,"y":1.3046475838719598},{"x":46.74599138196369,"y":1.3046475838719598},{"x":46.84742566943676,"y":1.3046475838719598},{"x":46.94885995690983,"y":1.3046475838719598},{"x":47.151728531855966,"y":1.203213296398891},{"x":47.3545971068021,"y":1.1017790089258224},{"x":47.65889996922131,"y":1.1017790089258224},{"x":47.76033425669438,"y":1.1017790089258224},{"x":47.963202831640515,"y":1.1017790089258224},{"x":48.064637119113584,"y":1.1017790089258224},{"x":48.26750569405972,"y":1.1017790089258224},{"x":48.47037426900586,"y":1.1017790089258224},{"x":48.47037426900586,"y":1.203213296398891},{"x":48.57180855647893,"y":1.203213296398891},{"x":48.673242843951996,"y":1.203213296398891},{"x":48.774677131425065,"y":1.203213296398891},{"x":48.87611141889813,"y":1.203213296398891},{"x":48.87611141889813,"y":1.203213296398891},{"x":48.977545706371195,"y":1.203213296398891},{"x":49.078979993844264,"y":1.203213296398891},{"x":49.2818485687904,"y":1.203213296398891},{"x":49.2818485687904,"y":1.3046475838719598},{"x":49.48471714373654,"y":1.3046475838719598},{"x":49.58615143120961,"y":1.3046475838719598},{"x":49.687585718682676,"y":1.3046475838719598},{"x":49.687585718682676,"y":1.3046475838719598},{"x":49.789020006155745,"y":1.3046475838719598},{"x":49.890454293628814,"y":1.3046475838719598},{"x":49.99188858110188,"y":1.3046475838719598},{"x":50.09332286857495,"y":1.3046475838719598},{"x":50.19475715604802,"y":1.3046475838719598},{"x":50.39762573099416,"y":1.4060818713450285},{"x":50.499060018467226,"y":1.4060818713450285},{"x":50.499060018467226,"y":1.4060818713450285},{"x":50.600494305940295,"y":1.4060818713450285},{"x":50.70192859341336,"y":1.4060818713450285},{"x":50.80336288088643,"y":1.5075161588180972},{"x":50.9047971683595,"y":1.5075161588180972},{"x":51.10766574330564,"y":1.5075161588180972},{"x":51.310534318251776,"y":1.608950446291166},{"x":51.411968605724844,"y":1.608950446291166},{"x":51.61483718067098,"y":1.608950446291166},{"x":51.71627146814405,"y":1.7103847337642346},{"x":51.91914004309019,"y":1.7103847337642346},{"x":52.02057433056326,"y":1.7103847337642346},{"x":52.122008618036325,"y":1.7103847337642346},{"x":52.223442905509394,"y":1.7103847337642346},{"x":52.32487719298246,"y":1.7103847337642346},{"x":52.5277457679286,"y":1.8118190212373033},{"x":52.62918005540167,"y":1.8118190212373033},{"x":52.73061434287474,"y":1.8118190212373033},{"x":52.933482917820875,"y":1.8118190212373033},{"x":53.034917205293944,"y":1.913253308710372},{"x":53.23778578024008,"y":2.0146875961834407},{"x":53.33922006771315,"y":2.0146875961834407},{"x":53.54208864265929,"y":2.0146875961834407},{"x":53.744957217605425,"y":2.0146875961834407},{"x":53.744957217605425,"y":2.1161218836565094},{"x":54.04926008002463,"y":2.1161218836565094},{"x":54.25212865497077,"y":2.1161218836565094},{"x":54.454997229916906,"y":2.1161218836565094},{"x":54.556431517389974,"y":2.1161218836565094},{"x":54.75930009233611,"y":2.1161218836565094},{"x":54.96216866728225,"y":2.1161218836565094},{"x":54.96216866728225,"y":2.1161218836565094},{"x":55.06360295475532,"y":2.1161218836565094},{"x":55.16503724222839,"y":2.1161218836565094},{"x":55.266471529701455,"y":2.1161218836565094},{"x":55.367905817174524,"y":2.1161218836565094},{"x":55.367905817174524,"y":2.1161218836565094},{"x":55.46934010464759,"y":2.1161218836565094},{"x":55.57077439212066,"y":2.1161218836565094},{"x":55.67220867959373,"y":2.1161218836565094},{"x":55.7736429670668,"y":2.1161218836565094},{"x":55.7736429670668,"y":2.1161218836565094},{"x":55.87507725453987,"y":2.1161218836565094},{"x":55.976511542012936,"y":2.1161218836565094},{"x":56.179380116959074,"y":2.1161218836565094},{"x":56.179380116959074,"y":2.1161218836565094},{"x":56.48368297937828,"y":2.1161218836565094},{"x":56.58511726685135,"y":2.1161218836565094},{"x":56.58511726685135,"y":2.1161218836565094},{"x":56.68655155432442,"y":2.1161218836565094},{"x":56.68655155432442,"y":2.0146875961834407},{"x":56.68655155432442,"y":2.0146875961834407},{"x":56.787985841797486,"y":2.1161218836565094},{"x":56.787985841797486,"y":1.913253308710372},{"x":56.889420129270555,"y":2.1161218836565094},{"x":56.889420129270555,"y":1.913253308710372},{"x":56.99085441674362,"y":1.8118190212373033},{"x":56.99085441674362,"y":1.8118190212373033},{"x":57.09228870421669,"y":1.8118190212373033},{"x":57.19372299168976,"y":1.8118190212373033},{"x":57.29515727916283,"y":1.7103847337642346},{"x":57.3965915666359,"y":1.7103847337642346},{"x":57.3965915666359,"y":1.7103847337642346},{"x":57.49802585410897,"y":1.7103847337642346},{"x":57.599460141582036,"y":1.608950446291166},{"x":57.700894429055104,"y":1.608950446291166},{"x":57.80232871652817,"y":1.608950446291166},{"x":57.80232871652817,"y":1.608950446291166},{"x":57.90376300400124,"y":1.608950446291166},{"x":58.10663157894738,"y":1.608950446291166},{"x":58.20806586642045,"y":1.608950446291166},{"x":58.20806586642045,"y":1.5075161588180972},{"x":58.30950015389352,"y":1.5075161588180972},{"x":58.410934441366585,"y":1.5075161588180972},{"x":58.512368728839654,"y":1.5075161588180972},{"x":58.61380301631272,"y":1.5075161588180972},{"x":58.61380301631272,"y":1.5075161588180972},{"x":58.71523730378579,"y":1.4060818713450285},{"x":58.81667159125886,"y":1.4060818713450285},{"x":58.91810587873193,"y":1.4060818713450285},{"x":59.019540166205,"y":1.4060818713450285},{"x":59.019540166205,"y":1.3046475838719598},{"x":59.120974453678066,"y":1.3046475838719598},{"x":59.222408741151135,"y":1.3046475838719598},{"x":59.323843028624204,"y":1.3046475838719598},{"x":59.42527731609727,"y":1.3046475838719598},{"x":59.42527731609727,"y":1.3046475838719598},{"x":59.52671160357034,"y":1.3046475838719598},{"x":59.62814589104341,"y":1.3046475838719598},{"x":59.72958017851648,"y":1.3046475838719598},{"x":59.83101446598955,"y":1.3046475838719598},{"x":59.83101446598955,"y":1.3046475838719598},{"x":59.932448753462616,"y":1.3046475838719598},{"x":60.033883040935685,"y":1.203213296398891},{"x":60.13531732840875,"y":1.203213296398891},{"x":60.23675161588182,"y":1.1017790089258224},{"x":60.23675161588182,"y":1.1017790089258224},{"x":60.33818590335489,"y":1.1017790089258224},{"x":60.43962019082796,"y":1.0003447214527537},{"x":60.54105447830103,"y":1.0003447214527537},{"x":60.6424887657741,"y":1.0003447214527537},{"x":60.6424887657741,"y":1.0003447214527537},{"x":60.743923053247165,"y":1.0003447214527537},{"x":60.845357340720234,"y":1.0003447214527537},{"x":60.946791628193296,"y":1.0003447214527537},{"x":61.048225915666364,"y":1.0003447214527537},{"x":61.048225915666364,"y":0.898910433979685},{"x":61.14966020313943,"y":0.898910433979685},{"x":61.2510944906125,"y":0.898910433979685},{"x":61.35252877808557,"y":0.898910433979685},{"x":61.45396306555864,"y":0.898910433979685},{"x":61.45396306555864,"y":0.898910433979685},{"x":61.55539735303171,"y":0.898910433979685},{"x":61.65683164050478,"y":0.898910433979685},{"x":61.758265927977845,"y":0.898910433979685},{"x":61.859700215450914,"y":0.898910433979685},{"x":61.96113450292398,"y":0.898910433979685},{"x":62.06256879039705,"y":0.898910433979685},{"x":62.16400307787012,"y":0.898910433979685},{"x":62.26543736534319,"y":0.898910433979685},{"x":62.26543736534319,"y":0.898910433979685},{"x":62.36687165281626,"y":0.898910433979685},{"x":62.468305940289326,"y":0.898910433979685},{"x":62.569740227762395,"y":0.898910433979685},{"x":62.671174515235464,"y":0.898910433979685},{"x":62.671174515235464,"y":0.898910433979685},{"x":62.671174515235464,"y":0.898910433979685},{"x":62.77260880270853,"y":0.898910433979685},{"x":62.77260880270853,"y":0.898910433979685},{"x":62.8740430901816,"y":0.898910433979685},{"x":62.8740430901816,"y":0.898910433979685},{"x":62.97547737765467,"y":0.898910433979685},{"x":63.07691166512774,"y":0.898910433979685},{"x":63.07691166512774,"y":0.898910433979685},{"x":63.07691166512774,"y":0.898910433979685},{"x":63.07691166512774,"y":0.898910433979685},{"x":63.17834595260081,"y":0.898910433979685},{"x":63.279780240073876,"y":0.898910433979685},{"x":63.279780240073876,"y":0.898910433979685},{"x":63.381214527546945,"y":0.898910433979685},{"x":63.381214527546945,"y":0.898910433979685},{"x":63.48264881502001,"y":0.898910433979685},{"x":63.48264881502001,"y":0.898910433979685},{"x":63.48264881502001,"y":0.898910433979685},{"x":63.48264881502001,"y":0.898910433979685},{"x":63.58408310249308,"y":0.898910433979685},{"x":63.58408310249308,"y":0.898910433979685},{"x":63.68551738996615,"y":0.898910433979685},{"x":63.68551738996615,"y":0.898910433979685},{"x":63.68551738996615,"y":0.898910433979685},{"x":63.78695167743922,"y":0.898910433979685},{"x":63.78695167743922,"y":0.898910433979685},{"x":63.88838596491229,"y":0.898910433979685},{"x":63.88838596491229,"y":0.898910433979685},{"x":63.88838596491229,"y":0.898910433979685},{"x":63.88838596491229,"y":0.898910433979685},{"x":63.88838596491229,"y":0.898910433979685},{"x":63.98982025238536,"y":0.898910433979685},{"x":63.98982025238536,"y":0.898910433979685},{"x":64.09125453985843,"y":0.898910433979685},{"x":64.09125453985843,"y":0.898910433979685},{"x":64.09125453985843,"y":0.898910433979685},{"x":64.1926888273315,"y":1.0003447214527537},{"x":64.29412311480456,"y":1.0003447214527537},{"x":64.29412311480456,"y":1.0003447214527537},{"x":64.39555740227763,"y":1.0003447214527537},{"x":64.4969916897507,"y":1.0003447214527537},{"x":64.69986026469684,"y":1.0003447214527537},{"x":64.69986026469684,"y":1.1017790089258224},{"x":64.8012945521699,"y":1.1017790089258224},{"x":64.90272883964298,"y":1.1017790089258224},{"x":65.00416312711604,"y":1.203213296398891},{"x":65.10559741458911,"y":1.203213296398891},{"x":65.20703170206218,"y":1.203213296398891},{"x":65.30846598953525,"y":1.203213296398891},{"x":65.51133456448139,"y":1.203213296398891},{"x":65.51133456448139,"y":1.203213296398891},{"x":65.61276885195446,"y":1.203213296398891},{"x":65.71420313942753,"y":1.203213296398891},{"x":65.8156374269006,"y":1.203213296398891},{"x":65.91707171437366,"y":1.203213296398891},{"x":65.91707171437366,"y":1.203213296398891},{"x":66.01850600184673,"y":1.203213296398891},{"x":66.1199402893198,"y":1.203213296398891},{"x":66.22137457679287,"y":1.203213296398891},{"x":66.32280886426594,"y":1.203213296398891},{"x":66.32280886426594,"y":1.203213296398891},{"x":66.424243151739,"y":1.203213296398891},{"x":66.52567743921207,"y":1.203213296398891},{"x":66.62711172668514,"y":1.203213296398891},{"x":66.72854601415821,"y":1.203213296398891},{"x":66.72854601415821,"y":1.203213296398891},{"x":66.82998030163128,"y":1.203213296398891},{"x":66.93141458910435,"y":1.203213296398891},{"x":67.03284887657742,"y":1.203213296398891},{"x":67.13428316405049,"y":1.203213296398891},{"x":67.13428316405049,"y":1.203213296398891},{"x":67.23571745152356,"y":1.203213296398891},{"x":67.33715173899662,"y":1.203213296398891},{"x":67.4385860264697,"y":1.203213296398891},{"x":67.54002031394276,"y":1.203213296398891},{"x":67.64145460141583,"y":1.203213296398891},{"x":67.7428888888889,"y":1.203213296398891},{"x":67.84432317636197,"y":1.203213296398891},{"x":67.94575746383504,"y":1.203213296398891},{"x":67.94575746383504,"y":1.203213296398891},{"x":68.0471917513081,"y":1.203213296398891},{"x":68.14862603878117,"y":1.203213296398891},{"x":68.25006032625424,"y":1.203213296398891},{"x":68.35149461372731,"y":1.203213296398891},{"x":68.35149461372731,"y":1.203213296398891},{"x":68.45292890120038,"y":1.203213296398891},{"x":68.55436318867345,"y":1.203213296398891},{"x":68.65579747614652,"y":1.203213296398891},{"x":68.75723176361959,"y":1.203213296398891},{"x":68.75723176361959,"y":1.203213296398891},{"x":68.85866605109265,"y":1.203213296398891},{"x":68.96010033856572,"y":1.203213296398891},{"x":69.06153462603879,"y":1.203213296398891},{"x":69.16296891351186,"y":1.203213296398891},{"x":69.16296891351186,"y":1.203213296398891},{"x":69.26440320098493,"y":1.203213296398891},{"x":69.365837488458,"y":1.203213296398891},{"x":69.46727177593107,"y":1.203213296398891},{"x":69.56870606340414,"y":1.203213296398891},{"x":69.56870606340414,"y":1.203213296398891},{"x":69.6701403508772,"y":1.203213296398891},{"x":69.77157463835027,"y":1.203213296398891},{"x":69.87300892582334,"y":1.203213296398891},{"x":69.97444321329641,"y":1.203213296398891},{"x":69.97444321329641,"y":1.203213296398891},{"x":70.07587750076948,"y":1.203213296398891},{"x":70.17731178824255,"y":1.203213296398891},{"x":70.27874607571562,"y":1.203213296398891},{"x":70.38018036318869,"y":1.203213296398891},{"x":70.38018036318869,"y":1.203213296398891},{"x":70.48161465066175,"y":1.203213296398891},{"x":70.58304893813482,"y":1.203213296398891},{"x":70.68448322560789,"y":1.203213296398891},{"x":70.78591751308096,"y":1.203213296398891},{"x":70.78591751308096,"y":1.203213296398891},{"x":70.88735180055403,"y":1.203213296398891},{"x":70.9887860880271,"y":1.203213296398891},{"x":71.09022037550017,"y":1.1017790089258224},{"x":71.19165466297324,"y":1.1017790089258224},{"x":71.19165466297324,"y":1.1017790089258224},{"x":71.2930889504463,"y":1.1017790089258224},{"x":71.39452323791937,"y":1.1017790089258224},{"x":71.49595752539244,"y":1.1017790089258224},{"x":71.59739181286551,"y":1.1017790089258224},{"x":71.59739181286551,"y":1.1017790089258224},{"x":71.69882610033858,"y":1.1017790089258224},{"x":71.80026038781165,"y":1.0003447214527537},{"x":71.90169467528472,"y":1.0003447214527537},{"x":72.00312896275778,"y":1.0003447214527537},{"x":72.00312896275778,"y":1.0003447214527537},{"x":72.10456325023085,"y":1.0003447214527537},{"x":72.20599753770392,"y":1.0003447214527537},{"x":72.30743182517699,"y":1.0003447214527537},{"x":72.40886611265006,"y":1.0003447214527537},{"x":72.40886611265006,"y":1.0003447214527537},{"x":72.51030040012313,"y":1.0003447214527537},{"x":72.6117346875962,"y":1.0003447214527537},{"x":72.71316897506927,"y":1.0003447214527537},{"x":72.81460326254233,"y":1.0003447214527537},{"x":72.81460326254233,"y":1.0003447214527537},{"x":72.9160375500154,"y":1.0003447214527537},{"x":73.01747183748847,"y":1.0003447214527537},{"x":73.11890612496154,"y":1.0003447214527537},{"x":73.22034041243461,"y":1.0003447214527537},{"x":73.22034041243461,"y":1.0003447214527537},{"x":73.32177469990768,"y":1.0003447214527537},{"x":73.42320898738075,"y":1.0003447214527537},{"x":73.52464327485382,"y":1.0003447214527537},{"x":73.62607756232688,"y":1.0003447214527537},{"x":73.62607756232688,"y":1.0003447214527537},{"x":73.72751184979995,"y":1.0003447214527537},{"x":73.72751184979995,"y":1.0003447214527537},{"x":73.82894613727302,"y":1.0003447214527537},{"x":73.93038042474609,"y":1.0003447214527537},{"x":74.03181471221916,"y":1.0003447214527537},{"x":74.03181471221916,"y":1.0003447214527537},{"x":74.03181471221916,"y":1.0003447214527537},{"x":74.13324899969223,"y":0.898910433979685},{"x":74.13324899969223,"y":0.898910433979685},{"x":74.13324899969223,"y":0.898910433979685},{"x":74.2346832871653,"y":0.7974761465066162},{"x":74.2346832871653,"y":0.7974761465066162},{"x":74.2346832871653,"y":0.7974761465066162},{"x":74.33611757463837,"y":0.7974761465066162},{"x":74.33611757463837,"y":0.7974761465066162},{"x":74.43755186211143,"y":0.7974761465066162},{"x":74.43755186211143,"y":0.6960418590335475},{"x":74.43755186211143,"y":0.5946075715604788},{"x":74.43755186211143,"y":0.5946075715604788},{"x":74.43755186211143,"y":0.5946075715604788},{"x":74.5389861495845,"y":0.4931732840874101},{"x":74.5389861495845,"y":0.3917389966143414},{"x":74.5389861495845,"y":0.3917389966143414},{"x":74.64042043705757,"y":0.3917389966143414},{"x":74.64042043705757,"y":0.3917389966143414},{"x":74.74185472453064,"y":0.2903047091412727},{"x":74.74185472453064,"y":0.188870421668204},{"x":74.74185472453064,"y":0.0874361341951353},{"x":74.74185472453064,"y":-0.013998153277933412},{"x":74.74185472453064,"y":-0.013998153277933412},{"x":74.74185472453064,"y":-0.11543244075100212},{"x":74.74185472453064,"y":-0.21686672822407083},{"x":74.84328901200371,"y":-0.31830101569713953},{"x":74.84328901200371,"y":-0.4197353031702047},{"x":74.84328901200371,"y":-0.4197353031702047},{"x":74.84328901200371,"y":-0.5211695906432734},{"x":74.84328901200371,"y":-0.6226038781163421},{"x":74.84328901200371,"y":-0.7240381655894108},{"x":74.84328901200371,"y":-0.8254724530624795},{"x":74.84328901200371,"y":-0.8254724530624795},{"x":74.84328901200371,"y":-0.9269067405355482},{"x":74.94472329947678,"y":-1.028341028008617},{"x":74.94472329947678,"y":-1.1297753154816856},{"x":74.94472329947678,"y":-1.2312096029547543},{"x":75.04615758694985,"y":-1.2312096029547543},{"x":75.04615758694985,"y":-1.2312096029547543},{"x":75.14759187442291,"y":-1.332643890427823},{"x":75.14759187442291,"y":-1.4340781779008918},{"x":75.14759187442291,"y":-1.5355124653739605},{"x":75.24902616189598,"y":-1.6369467528470292},{"x":75.24902616189598,"y":-1.6369467528470292},{"x":75.24902616189598,"y":-1.7383810403200979},{"x":75.24902616189598,"y":-1.8398153277931666},{"x":75.24902616189598,"y":-1.9412496152662353},{"x":75.24902616189598,"y":-2.042683902739304},{"x":75.24902616189598,"y":-2.042683902739304},{"x":75.24902616189598,"y":-2.1441181902123727},{"x":75.24902616189598,"y":-2.2455524776854414},{"x":75.24902616189598,"y":-2.34698676515851},{"x":75.24902616189598,"y":-2.448421052631579},{"x":75.35046044936905,"y":-2.448421052631579},{"x":75.35046044936905,"y":-2.5498553401046475},{"x":75.35046044936905,"y":-2.6512896275777162},{"x":75.35046044936905,"y":-2.752723915050785},{"x":75.45189473684212,"y":-2.8541582025238537},{"x":75.45189473684212,"y":-2.8541582025238537},{"x":75.55332902431519,"y":-2.9555924899969224},{"x":75.55332902431519,"y":-3.057026777469991},{"x":75.65476331178826,"y":-3.15846106494306},{"x":75.65476331178826,"y":-3.2598953524161285},{"x":75.65476331178826,"y":-3.2598953524161285},{"x":75.65476331178826,"y":-3.361329639889197},{"x":75.65476331178826,"y":-3.462763927362266},{"x":75.65476331178826,"y":-3.5641982148353346},{"x":75.65476331178826,"y":-3.6656325023084033},{"x":75.65476331178826,"y":-3.6656325023084033},{"x":75.65476331178826,"y":-3.767066789781472},{"x":75.65476331178826,"y":-3.8685010772545407},{"x":75.65476331178826,"y":-3.9699353647276094},{"x":75.65476331178826,"y":-4.071369652200678},{"x":75.65476331178826,"y":-4.071369652200678},{"x":75.75619759926133,"y":-4.172803939673747},{"x":75.75619759926133,"y":-4.274238227146816},{"x":75.8576318867344,"y":-4.375672514619884},{"x":75.8576318867344,"y":-4.477106802092953},{"x":75.8576318867344,"y":-4.477106802092953},{"x":75.8576318867344,"y":-4.578541089566022},{"x":75.8576318867344,"y":-4.67997537703909},{"x":75.95906617420746,"y":-4.781409664512159},{"x":75.95906617420746,"y":-4.882843951985228},{"x":75.95906617420746,"y":-4.882843951985228},{"x":75.95906617420746,"y":-4.9842782394582965},{"x":75.95906617420746,"y":-4.6379809172052955},{"x":75.95906617420746,"y":-4.6379809172052955},{"x":76.06050046168053,"y":-4.739415204678364},{"x":76.06050046168053,"y":-4.840849492151433},{"x":76.06050046168053,"y":-4.942283779624502},{"x":76.06050046168053,"y":-5.04371806709757},{"x":76.06050046168053,"y":-5.04371806709757},{"x":76.06050046168053,"y":-5.145152354570639},{"x":76.06050046168053,"y":-4.739415204678364},{"x":76.06050046168053,"y":-4.739415204678364},{"x":76.06050046168053,"y":-4.840849492151433},{"x":76.06050046168053,"y":-4.942283779624502},{"x":76.06050046168053,"y":-4.942283779624502},{"x":76.06050046168053,"y":-5.04371806709757},{"x":76.06050046168053,"y":-5.145152354570639},{"x":76.06050046168053,"y":-5.348020929516776},{"x":76.06050046168053,"y":-5.550889504462914},{"x":76.06050046168053,"y":-5.85519236688212},{"x":76.06050046168053,"y":-6.159495229301326},{"x":76.06050046168053,"y":-6.463798091720532},{"x":76.06050046168053,"y":-6.869535241612807},{"x":76.06050046168053,"y":-7.275272391505082},{"x":76.06050046168053,"y":-7.579575253924288},{"x":76.06050046168053,"y":-7.985312403816563},{"x":76.1619347491536,"y":-8.289615266235769},{"x":76.36480332409974,"y":-8.593918128654975},{"x":76.46623761157281,"y":-8.796786703601112},{"x":76.46623761157281,"y":-9.101089566020319},{"x":76.56767189904588,"y":-9.303958140966456},{"x":76.66910618651895,"y":-9.506826715912593},{"x":76.87197476146508,"y":-9.8111295783318},{"x":76.87197476146508,"y":-10.013998153277937},{"x":76.97340904893815,"y":-10.318301015697143},{"x":77.07484333641122,"y":-10.62260387811635},{"x":77.17627762388429,"y":-10.724038165589418},{"x":78.59635764850725,"y":-3.5222037550015397},{"x":78.69779193598032,"y":-3.5222037550015397},{"x":78.69779193598032,"y":-3.5222037550015397},{"x":78.69779193598032,"y":-3.5222037550015397},{"x":78.69779193598032,"y":-3.5222037550015397},{"x":78.79922622345339,"y":-3.5222037550015397},{"x":78.79922622345339,"y":-3.5222037550015397},{"x":78.90066051092646,"y":-3.6236380424746084},{"x":78.90066051092646,"y":-3.6236380424746084},{"x":78.90066051092646,"y":-3.725072329947677},{"x":79.00209479839953,"y":-3.725072329947677},{"x":79.00209479839953,"y":-3.725072329947677},{"x":79.10352908587258,"y":-3.826506617420746},{"x":79.10352908587258,"y":-3.826506617420746},{"x":79.20496337334565,"y":-3.826506617420746},{"x":79.30639766081872,"y":-3.9279409048938145},{"x":79.30639766081872,"y":-3.9279409048938145},{"x":79.40783194829179,"y":-3.9279409048938145},{"x":79.50926623576485,"y":-3.9279409048938145},{"x":79.61070052323792,"y":-4.029375192366883},{"x":79.71213481071099,"y":-4.029375192366883},{"x":79.71213481071099,"y":-4.029375192366883},{"x":79.81356909818406,"y":-4.130809479839952},{"x":79.91500338565713,"y":-4.232243767313021},{"x":80.0164376731302,"y":-4.232243767313021},{"x":80.11787196060327,"y":-4.333678054786089},{"x":80.3207405355494,"y":-4.333678054786089},{"x":80.52360911049554,"y":-4.333678054786089},{"x":80.72647768544168,"y":-4.435112342259158},{"x":80.92934626038782,"y":-4.435112342259158},{"x":81.23364912280702,"y":-4.435112342259158},{"x":81.43651769775316,"y":-4.435112342259158},{"x":81.74082056017237,"y":-4.435112342259158},{"x":81.9436891351185,"y":-4.435112342259158},{"x":82.14655771006464,"y":-4.435112342259158},{"x":82.45086057248385,"y":-4.435112342259158},{"x":82.75516343490305,"y":-4.435112342259158},{"x":82.95803200984919,"y":-4.536546629732227},{"x":83.16090058479533,"y":-4.536546629732227},{"x":83.36376915974147,"y":-4.536546629732227},{"x":83.36376915974147,"y":-4.536546629732227},{"x":83.46520344721453,"y":-4.536546629732227},{"x":83.76950630963374,"y":-4.536546629732227},{"x":83.87094059710681,"y":-4.536546629732227},{"x":84.07380917205295,"y":-4.6379809172052955},{"x":84.17524345952602,"y":-4.6379809172052955},{"x":84.47954632194522,"y":-4.6379809172052955},{"x":84.68241489689136,"y":-4.6379809172052955},{"x":84.98671775931057,"y":-4.6379809172052955},{"x":85.29102062172977,"y":-4.6379809172052955},{"x":85.49388919667591,"y":-4.6379809172052955},{"x":85.69675777162205,"y":-4.6379809172052955},{"x":85.89962634656818,"y":-4.6379809172052955},{"x":86.00106063404125,"y":-4.6379809172052955},{"x":86.10249492151432,"y":-4.6379809172052955},{"x":86.20392920898739,"y":-4.739415204678364},{"x":86.40679778393353,"y":-4.739415204678364},{"x":86.60966635887966,"y":-4.739415204678364},{"x":86.71110064635273,"y":-4.739415204678364},{"x":87.01540350877194,"y":-4.739415204678364},{"x":87.21827208371808,"y":-4.739415204678364},{"x":87.42114065866421,"y":-4.739415204678364},{"x":87.72544352108342,"y":-4.739415204678364},{"x":88.02974638350263,"y":-4.840849492151433},{"x":88.23261495844876,"y":-4.942283779624502},{"x":88.53691782086797,"y":-5.145152354570639},{"x":88.63835210834104,"y":-5.145152354570639},{"x":88.94265497076024,"y":-5.246586642043708},{"x":89.24695783317945,"y":-5.348020929516776},{"x":89.44982640812559,"y":-5.348020929516776},{"x":89.65269498307173,"y":-5.449455216989845},{"x":89.85556355801786,"y":-5.449455216989845},{"x":90.26130070791014,"y":-5.550889504462914},{"x":90.3627349953832,"y":-5.550889504462914},{"x":90.66703785780241,"y":-5.550889504462914},{"x":90.97134072022162,"y":-5.6523237919359826},{"x":91.17420929516776,"y":-5.6523237919359826},{"x":91.47851215758696,"y":-5.753758079409051},{"x":91.6813807325331,"y":-5.753758079409051},{"x":91.88424930747924,"y":-5.956626654355189},{"x":92.28998645737151,"y":-5.956626654355189},{"x":92.49285503231765,"y":-5.956626654355189},{"x":92.79715789473686,"y":-5.956626654355189},{"x":93.10146075715606,"y":-5.956626654355189},{"x":93.3043293321022,"y":-5.956626654355189},{"x":93.6086321945214,"y":-5.956626654355189},{"x":93.91293505694061,"y":-5.956626654355189},{"x":94.11580363188675,"y":-5.956626654355189},{"x":94.31867220683289,"y":-5.956626654355189},{"x":94.62297506925209,"y":-5.956626654355189},{"x":94.9272779316713,"y":-5.956626654355189},{"x":95.13014650661744,"y":-5.956626654355189},{"x":95.33301508156357,"y":-5.956626654355189},{"x":95.53588365650971,"y":-5.956626654355189},{"x":95.63731794398278,"y":-5.956626654355189},{"x":95.73875223145585,"y":-5.956626654355189},{"x":95.94162080640199,"y":-5.956626654355189},{"x":96.04305509387505,"y":-5.956626654355189},{"x":96.14448938134812,"y":-5.956626654355189},{"x":96.24592366882119,"y":-5.956626654355189},{"x":96.34735795629426,"y":-5.956626654355189},{"x":96.34735795629426,"y":-5.956626654355189},{"x":96.44879224376733,"y":-5.956626654355189},{"x":96.5502265312404,"y":-5.956626654355189},{"x":96.65166081871347,"y":-5.956626654355189},{"x":96.75309510618654,"y":-5.956626654355189},{"x":96.95596368113267,"y":-5.956626654355189},{"x":97.05739796860574,"y":-5.956626654355189},{"x":97.15883225607881,"y":-5.956626654355189},{"x":97.36170083102495,"y":-5.956626654355189},{"x":97.46313511849802,"y":-5.956626654355189},{"x":97.56456940597108,"y":-5.85519236688212},{"x":97.56456940597108,"y":-5.85519236688212},{"x":97.66600369344415,"y":-5.85519236688212},{"x":97.76743798091722,"y":-5.753758079409051},{"x":97.86887226839029,"y":-5.6523237919359826},{"x":97.97030655586336,"y":-5.6523237919359826},{"x":97.97030655586336,"y":-5.6523237919359826},{"x":98.07174084333643,"y":-5.550889504462914},{"x":98.1731751308095,"y":-5.550889504462914},{"x":98.27460941828257,"y":-5.449455216989845},{"x":98.37604370575563,"y":-5.449455216989845},{"x":98.37604370575563,"y":-5.348020929516776},{"x":98.4774779932287,"y":-5.246586642043708},{"x":98.57891228070177,"y":-5.145152354570639},{"x":98.68034656817484,"y":-5.145152354570639},{"x":98.78178085564791,"y":-5.04371806709757},{"x":98.78178085564791,"y":-4.942283779624502},{"x":98.88321514312098,"y":-4.840849492151433},{"x":99.08608371806712,"y":-4.840849492151433},{"x":99.18751800554018,"y":-4.739415204678364},{"x":99.49182086795939,"y":-4.739415204678364},{"x":99.59325515543246,"y":-4.739415204678364},{"x":99.7961237303786,"y":-4.739415204678364},{"x":99.99899230532473,"y":-4.739415204678364},{"x":99.99899230532473,"y":-4.6379809172052955},{"x":100.1004265927978,"y":-4.6379809172052955},{"x":100.20186088027087,"y":-4.6379809172052955},{"x":100.30329516774394,"y":-4.536546629732227},{"x":100.40472945521701,"y":-4.536546629732227},{"x":100.40472945521701,"y":-4.536546629732227},{"x":100.50616374269008,"y":-4.435112342259158},{"x":100.60759803016315,"y":-4.435112342259158},{"x":100.70903231763621,"y":-4.333678054786089},{"x":100.81046660510928,"y":-4.333678054786089},{"x":101.01333518005542,"y":-4.333678054786089},{"x":101.11476946752849,"y":-4.333678054786089},{"x":101.21620375500156,"y":-4.333678054786089},{"x":101.31763804247463,"y":-4.333678054786089},{"x":101.4190723299477,"y":-4.333678054786089},{"x":101.62194090489383,"y":-4.232243767313021},{"x":101.62194090489383,"y":-4.232243767313021},{"x":101.82480947983997,"y":-4.232243767313021},{"x":102.02767805478611,"y":-4.130809479839952},{"x":102.12911234225918,"y":-4.029375192366883},{"x":102.23054662973225,"y":-4.029375192366883},{"x":102.33198091720531,"y":-3.9279409048938145},{"x":102.43341520467838,"y":-3.9279409048938145},{"x":102.43341520467838,"y":-3.9279409048938145},{"x":102.53484949215145,"y":-3.9279409048938145},{"x":102.63628377962452,"y":-3.826506617420746},{"x":102.73771806709759,"y":-3.725072329947677},{"x":102.83915235457066,"y":-3.6236380424746084},{"x":102.83915235457066,"y":-3.6236380424746084},{"x":102.94058664204373,"y":-3.5222037550015397},{"x":103.0420209295168,"y":-3.5222037550015397},{"x":103.14345521698986,"y":-3.420769467528471},{"x":103.24488950446293,"y":-3.3193351800554023},{"x":103.24488950446293,"y":-3.2179008925823336},{"x":103.34632379193599,"y":-3.116466605109265},{"x":103.44775807940906,"y":-3.116466605109265},{"x":103.44775807940906,"y":-3.015032317636196},{"x":103.54919236688212,"y":-3.015032317636196},{"x":103.6506266543552,"y":-2.9135980301631275},{"x":103.6506266543552,"y":-2.8121637426900588},{"x":103.75206094182826,"y":-2.71072945521699},{"x":103.85349522930133,"y":-2.71072945521699},{"x":103.9549295167744,"y":-2.71072945521699},{"x":104.05636380424747,"y":-2.6092951677439213},{"x":104.05636380424747,"y":-2.5078608802708526},{"x":104.05636380424747,"y":-2.5078608802708526},{"x":104.15779809172054,"y":-2.406426592797784},{"x":104.2592323791936,"y":-2.304992305324715},{"x":104.36066666666667,"y":-2.304992305324715}],"ceiling":[{"x":8.809567867036012,"y":16.666666666666664},{"x":8.911002154509081,"y":16.666666666666664},{"x":9.01243644198215,"y":16.666666666666664},{"x":9.113870729455217,"y":16.666666666666664},{"x":9.113870729455217,"y":16.666666666666664},{"x":9.215305016928285,"y":16.666666666666664},{"x":9.215305016928285,"y":16.666666666666664},{"x":9.316739304401354,"y":16.666666666666664},{"x":9.418173591874423,"y":16.666666666666664},{"x":9.519607879347491,"y":16.666666666666664},{"x":9.519607879347491,"y":16.666666666666664},{"x":9.62104216682056,"y":16.666666666666664},{"x":9.722476454293629,"y":16.666666666666664},{"x":9.823910741766698,"y":16.666666666666664},{"x":9.925345029239766,"y":16.666666666666664},{"x":9.925345029239766,"y":16.666666666666664},{"x":10.026779316712835,"y":16.666666666666664},{"x":10.128213604185904,"y":16.666666666666664},{"x":10.229647891658972,"y":16.666666666666664},{"x":10.331082179132041,"y":16.666666666666664},{"x":10.331082179132041,"y":16.666666666666664},{"x":10.43251646660511,"y":16.666666666666664},{"x":10.533950754078178,"y":16.666666666666664},{"x":10.635385041551247,"y":16.666666666666664},{"x":10.736819329024316,"y":16.666666666666664},{"x":10.736819329024316,"y":16.666666666666664},{"x":10.838253616497385,"y":16.666666666666664},{"x":10.838253616497385,"y":16.565232379193596},{"x":10.939687903970453,"y":16.565232379193596},{"x":11.041122191443522,"y":16.565232379193596},{"x":11.14255647891659,"y":16.565232379193596},{"x":11.14255647891659,"y":16.463798091720527},{"x":11.24399076638966,"y":16.463798091720527},{"x":11.345425053862728,"y":16.463798091720527},{"x":11.446859341335797,"y":16.463798091720527},{"x":11.548293628808866,"y":16.463798091720527},{"x":11.548293628808866,"y":16.463798091720527},{"x":11.649727916281934,"y":16.362363804247458},{"x":11.751162203755003,"y":16.362363804247458},{"x":11.852596491228072,"y":16.362363804247458},{"x":11.95403077870114,"y":16.362363804247458},{"x":11.95403077870114,"y":16.26092951677439},{"x":12.055465066174207,"y":16.26092951677439},{"x":12.156899353647276,"y":16.26092951677439},{"x":12.258333641120345,"y":16.15949522930132},{"x":12.359767928593413,"y":16.058060941828252},{"x":12.359767928593413,"y":16.058060941828252},{"x":12.461202216066482,"y":16.058060941828252},{"x":12.56263650353955,"y":16.058060941828252},{"x":12.66407079101262,"y":16.058060941828252},{"x":12.765505078485688,"y":16.058060941828252},{"x":12.765505078485688,"y":15.956626654355182},{"x":12.866939365958757,"y":15.956626654355182},{"x":12.968373653431826,"y":15.855192366882113},{"x":13.069807940904894,"y":15.855192366882113},{"x":13.171242228377963,"y":15.855192366882113},{"x":13.171242228377963,"y":15.753758079409044},{"x":13.272676515851032,"y":15.652323791935975},{"x":13.3741108033241,"y":15.652323791935975},{"x":13.47554509079717,"y":15.652323791935975},{"x":13.576979378270238,"y":15.652323791935975},{"x":13.576979378270238,"y":15.550889504462907},{"x":13.678413665743307,"y":15.44945521698984},{"x":13.779847953216375,"y":15.44945521698984},{"x":13.779847953216375,"y":15.348020929516771},{"x":13.881282240689444,"y":15.348020929516771},{"x":13.982716528162513,"y":15.246586642043702},{"x":13.982716528162513,"y":15.246586642043702},{"x":14.084150815635581,"y":15.246586642043702},{"x":14.18558510310865,"y":15.145152354570634},{"x":14.287019390581719,"y":15.043718067097565},{"x":14.388453678054788,"y":15.043718067097565},{"x":14.388453678054788,"y":15.043718067097565},{"x":14.489887965527856,"y":14.942283779624496},{"x":14.591322253000925,"y":14.942283779624496},{"x":14.692756540473994,"y":14.840849492151428},{"x":14.794190827947062,"y":14.840849492151428},{"x":14.794190827947062,"y":14.840849492151428},{"x":14.895625115420131,"y":14.739415204678359},{"x":14.9970594028932,"y":14.63798091720529},{"x":15.098493690366267,"y":14.63798091720529},{"x":15.199927977839335,"y":14.63798091720529},{"x":15.199927977839335,"y":14.536546629732221},{"x":15.301362265312404,"y":14.536546629732221},{"x":15.402796552785473,"y":14.435112342259153},{"x":15.504230840258542,"y":14.435112342259153},{"x":15.60566512773161,"y":14.435112342259153},{"x":15.60566512773161,"y":14.435112342259153},{"x":15.60566512773161,"y":14.435112342259153},{"x":15.707099415204679,"y":14.333678054786084},{"x":15.808533702677748,"y":14.333678054786084},{"x":15.909967990150816,"y":14.333678054786084},{"x":16.011402277623887,"y":14.333678054786084},{"x":16.011402277623887,"y":14.333678054786084},{"x":16.112836565096956,"y":14.232243767313015},{"x":16.214270852570024,"y":14.232243767313015},{"x":16.315705140043093,"y":14.232243767313015},{"x":16.41713942751616,"y":14.130809479839947},{"x":16.41713942751616,"y":14.130809479839947},{"x":16.51857371498923,"y":14.130809479839947},{"x":16.620008002462296,"y":14.029375192366878},{"x":16.721442289935364,"y":14.029375192366878},{"x":16.822876577408433,"y":14.029375192366878},{"x":16.822876577408433,"y":14.029375192366878},{"x":16.9243108648815,"y":14.029375192366878},{"x":17.02574515235457,"y":14.029375192366878},{"x":17.12717943982764,"y":13.92794090489381},{"x":17.228613727300708,"y":13.92794090489381},{"x":17.228613727300708,"y":13.92794090489381},{"x":17.330048014773777,"y":13.92794090489381},{"x":17.431482302246845,"y":13.82650661742074},{"x":17.532916589719914,"y":13.82650661742074},{"x":17.634350877192983,"y":13.82650661742074},{"x":17.634350877192983,"y":13.725072329947672},{"x":17.73578516466605,"y":13.725072329947672},{"x":17.83721945213912,"y":13.725072329947672},{"x":17.93865373961219,"y":13.623638042474603},{"x":18.040088027085257,"y":13.623638042474603},{"x":18.040088027085257,"y":13.623638042474603},{"x":18.141522314558326,"y":13.623638042474603},{"x":18.242956602031395,"y":13.623638042474603},{"x":18.445825176977532,"y":13.522203755001534},{"x":18.445825176977532,"y":13.522203755001534},{"x":18.5472594644506,"y":13.420769467528466},{"x":18.64869375192367,"y":13.420769467528466},{"x":18.75012803939674,"y":13.420769467528466},{"x":18.851562326869807,"y":13.420769467528466},{"x":18.851562326869807,"y":13.420769467528466},{"x":18.952996614342876,"y":13.420769467528466},{"x":19.054430901815945,"y":13.319335180055397},{"x":19.155865189289013,"y":13.319335180055397},{"x":19.257299476762082,"y":13.319335180055397},{"x":19.257299476762082,"y":13.319335180055397},{"x":19.35873376423515,"y":13.319335180055397},{"x":19.46016805170822,"y":13.217900892582328},{"x":19.561602339181288,"y":13.217900892582328},{"x":19.663036626654357,"y":13.217900892582328},{"x":19.663036626654357,"y":13.217900892582328},{"x":19.764470914127426,"y":13.217900892582328},{"x":19.865905201600494,"y":13.217900892582328},{"x":19.967339489073563,"y":13.217900892582328},{"x":20.06877377654663,"y":13.217900892582328},{"x":20.06877377654663,"y":13.217900892582328},{"x":20.1702080640197,"y":13.217900892582328},{"x":20.27164235149277,"y":13.217900892582328},{"x":20.373076638965838,"y":13.217900892582328},{"x":20.474510926438906,"y":13.217900892582328},{"x":20.474510926438906,"y":13.217900892582328},{"x":20.575945213911975,"y":13.217900892582328},{"x":20.677379501385044,"y":13.217900892582328},{"x":20.778813788858113,"y":13.217900892582328},{"x":20.88024807633118,"y":13.217900892582328},{"x":20.88024807633118,"y":13.217900892582328},{"x":20.98168236380425,"y":13.217900892582328},{"x":21.08311665127732,"y":13.217900892582328},{"x":21.184550938750387,"y":13.217900892582328},{"x":21.285985226223456,"y":13.217900892582328},{"x":21.285985226223456,"y":13.217900892582328},{"x":21.387419513696525,"y":13.217900892582328},{"x":21.488853801169594,"y":13.217900892582328},{"x":21.590288088642662,"y":13.217900892582328},{"x":21.69172237611573,"y":13.217900892582328},{"x":21.69172237611573,"y":13.217900892582328},{"x":21.7931566635888,"y":13.217900892582328},{"x":21.89459095106187,"y":13.217900892582328},{"x":21.996025238534937,"y":13.217900892582328},{"x":22.097459526008006,"y":13.217900892582328},{"x":22.097459526008006,"y":13.217900892582328},{"x":22.198893813481074,"y":13.217900892582328},{"x":22.300328100954143,"y":13.217900892582328},{"x":22.401762388427212,"y":13.217900892582328},{"x":22.50319667590028,"y":13.217900892582328},{"x":22.50319667590028,"y":13.217900892582328},{"x":22.60463096337335,"y":13.217900892582328},{"x":22.807499538319483,"y":13.217900892582328},{"x":22.908933825792552,"y":13.217900892582328},{"x":22.908933825792552,"y":13.217900892582328},{"x":23.01036811326562,"y":13.217900892582328},{"x":23.11180240073869,"y":13.217900892582328},{"x":23.213236688211758,"y":13.217900892582328},{"x":23.314670975684827,"y":13.217900892582328},{"x":23.416105263157895,"y":13.217900892582328},{"x":23.517539550630964,"y":13.217900892582328},{"x":23.618973838104033,"y":13.217900892582328},{"x":23.7204081255771,"y":13.217900892582328},{"x":23.7204081255771,"y":13.217900892582328},{"x":23.82184241305017,"y":13.217900892582328},{"x":23.92327670052324,"y":13.217900892582328},{"x":24.024710987996308,"y":13.217900892582328},{"x":24.126145275469376,"y":13.217900892582328},{"x":24.126145275469376,"y":13.217900892582328},{"x":24.227579562942445,"y":13.217900892582328},{"x":24.329013850415514,"y":13.217900892582328},{"x":24.430448137888582,"y":13.319335180055397},{"x":24.53188242536165,"y":13.319335180055397},{"x":24.53188242536165,"y":13.319335180055397},{"x":24.63331671283472,"y":13.319335180055397},{"x":24.73475100030779,"y":13.319335180055397},{"x":24.836185287780857,"y":13.319335180055397},{"x":24.937619575253926,"y":13.319335180055397},{"x":24.937619575253926,"y":13.319335180055397},{"x":25.039053862726995,"y":13.319335180055397},{"x":25.140488150200063,"y":13.319335180055397},{"x":25.241922437673132,"y":13.319335180055397},{"x":25.3433567251462,"y":13.319335180055397},{"x":25.3433567251462,"y":13.319335180055397},{"x":25.44479101261927,"y":13.319335180055397},{"x":25.54622530009234,"y":13.319335180055397},{"x":25.647659587565407,"y":13.319335180055397},{"x":25.749093875038476,"y":13.319335180055397},{"x":25.749093875038476,"y":13.319335180055397},{"x":25.850528162511544,"y":13.319335180055397},{"x":26.053396737457685,"y":13.217900892582328},{"x":26.154831024930754,"y":13.217900892582328},{"x":26.154831024930754,"y":13.217900892582328},{"x":26.256265312403823,"y":13.217900892582328},{"x":26.35769959987689,"y":13.217900892582328},{"x":26.45913388734996,"y":13.217900892582328},{"x":26.56056817482303,"y":13.217900892582328},{"x":26.56056817482303,"y":13.217900892582328},{"x":26.662002462296098,"y":13.217900892582328},{"x":26.763436749769166,"y":13.11646660510926},{"x":26.864871037242235,"y":13.11646660510926},{"x":26.966305324715304,"y":13.11646660510926},{"x":26.966305324715304,"y":13.11646660510926},{"x":27.067739612188372,"y":13.11646660510926},{"x":27.16917389966144,"y":13.01503231763619},{"x":27.27060818713451,"y":13.01503231763619},{"x":27.37204247460758,"y":13.01503231763619},{"x":27.37204247460758,"y":13.01503231763619},{"x":27.473476762080647,"y":13.01503231763619},{"x":27.574911049553712,"y":13.01503231763619},{"x":27.67634533702678,"y":13.01503231763619},{"x":27.77777962449985,"y":13.01503231763619},{"x":27.87921391197292,"y":13.01503231763619},{"x":27.980648199445987,"y":13.01503231763619},{"x":28.082082486919056,"y":13.01503231763619},{"x":28.183516774392125,"y":13.11646660510926},{"x":28.183516774392125,"y":13.11646660510926},{"x":28.284951061865193,"y":13.11646660510926},{"x":28.386385349338262,"y":13.11646660510926},{"x":28.48781963681133,"y":13.11646660510926},{"x":28.5892539242844,"y":13.11646660510926},{"x":28.5892539242844,"y":13.11646660510926},{"x":28.690688211757468,"y":13.11646660510926},{"x":28.792122499230537,"y":13.11646660510926},{"x":28.893556786703606,"y":13.11646660510926},{"x":28.994991074176674,"y":13.11646660510926},{"x":28.994991074176674,"y":13.11646660510926},{"x":29.096425361649743,"y":13.11646660510926},{"x":29.19785964912281,"y":13.11646660510926},{"x":29.29929393659588,"y":13.01503231763619},{"x":29.40072822406895,"y":13.01503231763619},{"x":29.40072822406895,"y":13.01503231763619},{"x":29.502162511542018,"y":13.01503231763619},{"x":29.603596799015087,"y":13.01503231763619},{"x":29.705031086488155,"y":13.01503231763619},{"x":29.806465373961224,"y":12.913598030163122},{"x":29.907899661434293,"y":12.913598030163122},{"x":30.11076823638043,"y":12.913598030163122},{"x":30.2122025238535,"y":12.913598030163122},{"x":30.2122025238535,"y":12.913598030163122},{"x":30.313636811326568,"y":12.913598030163122},{"x":30.415071098799636,"y":12.913598030163122},{"x":30.516505386272705,"y":12.913598030163122},{"x":30.617939673745774,"y":12.812163742690053},{"x":30.617939673745774,"y":12.812163742690053},{"x":30.719373961218842,"y":12.812163742690053},{"x":30.82080824869191,"y":12.812163742690053},{"x":30.92224253616498,"y":12.812163742690053},{"x":31.02367682363805,"y":12.812163742690053},{"x":31.02367682363805,"y":12.812163742690053},{"x":31.125111111111117,"y":12.812163742690053},{"x":31.226545398584186,"y":12.812163742690053},{"x":31.327979686057255,"y":12.812163742690053},{"x":31.429413973530323,"y":12.812163742690053},{"x":31.429413973530323,"y":12.812163742690053},{"x":31.530848261003392,"y":12.812163742690053},{"x":31.63228254847646,"y":12.812163742690053},{"x":31.73371683594953,"y":12.812163742690053},{"x":31.835151123422598,"y":12.812163742690053},{"x":31.835151123422598,"y":12.812163742690053},{"x":31.936585410895667,"y":12.812163742690053},{"x":32.038019698368736,"y":12.812163742690053},{"x":32.139453985841804,"y":12.812163742690053},{"x":32.24088827331487,"y":12.812163742690053},{"x":32.24088827331487,"y":12.812163742690053},{"x":32.34232256078794,"y":12.812163742690053},{"x":32.44375684826101,"y":12.812163742690053},{"x":32.54519113573408,"y":12.812163742690053},{"x":32.64662542320715,"y":12.812163742690053},{"x":32.64662542320715,"y":12.812163742690053},{"x":32.74805971068022,"y":12.812163742690053},{"x":32.849493998153285,"y":12.812163742690053},{"x":32.950928285626354,"y":12.913598030163122},{"x":33.05236257309942,"y":12.913598030163122},{"x":33.05236257309942,"y":12.913598030163122},{"x":33.15379686057249,"y":12.913598030163122},{"x":33.25523114804556,"y":12.913598030163122},{"x":33.35666543551863,"y":12.913598030163122},{"x":33.4580997229917,"y":12.913598030163122},{"x":33.559534010464766,"y":12.913598030163122},{"x":33.660968297937835,"y":13.01503231763619},{"x":33.762402585410904,"y":13.01503231763619},{"x":33.86383687288397,"y":13.01503231763619},{"x":33.86383687288397,"y":13.01503231763619},{"x":33.96527116035704,"y":13.01503231763619},{"x":34.06670544783011,"y":13.01503231763619},{"x":34.16813973530318,"y":13.11646660510926},{"x":34.26957402277625,"y":13.11646660510926},{"x":34.26957402277625,"y":13.11646660510926},{"x":34.371008310249316,"y":13.217900892582328},{"x":34.472442597722385,"y":13.217900892582328},{"x":34.57387688519545,"y":13.217900892582328},{"x":34.67531117266852,"y":13.217900892582328},{"x":34.67531117266852,"y":13.217900892582328},{"x":34.77674546014159,"y":13.217900892582328},{"x":34.87817974761466,"y":13.217900892582328},{"x":34.97961403508773,"y":13.217900892582328},{"x":35.0810483225608,"y":13.217900892582328},{"x":35.0810483225608,"y":13.217900892582328},{"x":35.182482610033865,"y":13.217900892582328},{"x":35.283916897506934,"y":13.217900892582328},{"x":35.38535118498,"y":13.319335180055397},{"x":35.48678547245307,"y":13.319335180055397},{"x":35.48678547245307,"y":13.319335180055397},{"x":35.58821975992614,"y":13.319335180055397},{"x":35.68965404739921,"y":13.319335180055397},{"x":35.79108833487228,"y":13.420769467528466},{"x":35.892522622345346,"y":13.420769467528466},{"x":35.892522622345346,"y":13.522203755001534},{"x":35.993956909818415,"y":13.522203755001534},{"x":36.095391197291484,"y":13.623638042474603},{"x":36.19682548476455,"y":13.623638042474603},{"x":36.29825977223762,"y":13.623638042474603},{"x":36.29825977223762,"y":13.725072329947672},{"x":36.39969405971069,"y":13.725072329947672},{"x":36.50112834718376,"y":13.82650661742074},{"x":36.60256263465683,"y":13.82650661742074},{"x":36.70399692212989,"y":13.92794090489381},{"x":36.70399692212989,"y":13.92794090489381},{"x":36.80543120960296,"y":14.029375192366878},{"x":36.906865497076026,"y":14.029375192366878},{"x":37.008299784549095,"y":14.029375192366878},{"x":37.109734072022164,"y":14.130809479839947},{"x":37.109734072022164,"y":14.130809479839947},{"x":37.21116835949523,"y":14.232243767313015},{"x":37.3126026469683,"y":14.333678054786084},{"x":37.41403693444137,"y":14.333678054786084},{"x":37.41403693444137,"y":14.435112342259153},{"x":37.51547122191444,"y":14.435112342259153},{"x":37.51547122191444,"y":14.435112342259153},{"x":37.61690550938751,"y":14.536546629732221},{"x":37.718339796860576,"y":14.63798091720529},{"x":37.819774084333645,"y":14.63798091720529},{"x":37.92120837180671,"y":14.739415204678359},{"x":37.92120837180671,"y":14.739415204678359},{"x":38.02264265927978,"y":14.840849492151428},{"x":38.12407694675285,"y":14.840849492151428},{"x":38.22551123422592,"y":14.942283779624496},{"x":38.32694552169899,"y":14.942283779624496},{"x":38.32694552169899,"y":15.043718067097565},{"x":38.42837980917206,"y":15.043718067097565},{"x":38.529814096645126,"y":15.145152354570634},{"x":38.631248384118194,"y":15.145152354570634},{"x":38.73268267159126,"y":15.246586642043702},{"x":38.73268267159126,"y":15.246586642043702},{"x":38.83411695906433,"y":15.246586642043702},{"x":38.9355512465374,"y":15.348020929516771},{"x":39.03698553401047,"y":15.44945521698984},{"x":39.13841982148354,"y":15.44945521698984},{"x":39.13841982148354,"y":15.44945521698984},{"x":39.23985410895661,"y":15.550889504462907},{"x":39.341288396429675,"y":15.652323791935975},{"x":39.442722683902744,"y":15.652323791935975},{"x":39.54415697137581,"y":15.652323791935975},{"x":39.54415697137581,"y":15.753758079409044},{"x":39.64559125884888,"y":15.753758079409044},{"x":39.74702554632195,"y":15.855192366882113},{"x":39.84845983379502,"y":15.956626654355182},{"x":39.94989412126809,"y":15.956626654355182},{"x":39.94989412126809,"y":16.058060941828252},{"x":40.051328408741156,"y":16.058060941828252},{"x":40.152762696214225,"y":16.058060941828252},{"x":40.254196983687294,"y":16.058060941828252},{"x":40.35563127116036,"y":16.058060941828252},{"x":40.35563127116036,"y":16.058060941828252},{"x":40.45706555863343,"y":16.15949522930132},{"x":40.5584998461065,"y":16.15949522930132},{"x":40.5584998461065,"y":16.26092951677439},{"x":40.65993413357957,"y":16.26092951677439},{"x":40.76136842105264,"y":16.26092951677439},{"x":40.76136842105264,"y":16.362363804247458},{"x":40.76136842105264,"y":16.362363804247458},{"x":40.862802708525706,"y":16.463798091720527},{"x":40.964236995998775,"y":16.463798091720527},{"x":41.06567128347184,"y":16.463798091720527},{"x":41.16710557094491,"y":16.463798091720527},{"x":41.16710557094491,"y":16.565232379193596},{"x":41.16710557094491,"y":16.565232379193596},{"x":41.16710557094491,"y":16.666666666666664},{"x":41.26853985841798,"y":16.666666666666664},{"x":41.36997414589105,"y":16.768100954139733},{"x":41.47140843336412,"y":16.768100954139733},{"x":41.57284272083719,"y":16.8695352416128},{"x":41.57284272083719,"y":16.8695352416128},{"x":41.674277008310256,"y":16.8695352416128},{"x":41.775711295783324,"y":16.97096952908587},{"x":41.87714558325639,"y":16.97096952908587},{"x":41.97857987072946,"y":17.07240381655894},{"x":41.97857987072946,"y":17.07240381655894},{"x":41.97857987072946,"y":17.173838104032008},{"x":42.08001415820253,"y":17.173838104032008},{"x":42.1814484456756,"y":17.275272391505077},{"x":42.28288273314867,"y":17.275272391505077},{"x":42.38431702062174,"y":17.275272391505077},{"x":42.38431702062174,"y":17.275272391505077},{"x":42.485751308094805,"y":17.376706678978145},{"x":42.587185595567874,"y":17.376706678978145},{"x":42.68861988304094,"y":17.376706678978145},{"x":42.79005417051401,"y":17.478140966451214},{"x":42.79005417051401,"y":17.579575253924283},{"x":42.89148845798708,"y":17.579575253924283},{"x":42.99292274546015,"y":17.579575253924283},{"x":42.99292274546015,"y":17.68100954139735},{"x":43.09435703293322,"y":17.68100954139735},{"x":43.195791320406286,"y":17.68100954139735},{"x":43.195791320406286,"y":17.68100954139735},{"x":43.297225607879355,"y":17.68100954139735},{"x":43.398659895352424,"y":17.68100954139735},{"x":43.50009418282549,"y":17.68100954139735},{"x":43.60152847029856,"y":17.78244382887042},{"x":43.60152847029856,"y":17.78244382887042},{"x":43.70296275777163,"y":17.78244382887042},{"x":43.8043970452447,"y":17.78244382887042},{"x":43.8043970452447,"y":17.88387811634349},{"x":43.90583133271777,"y":17.88387811634349},{"x":44.007265620190836,"y":17.88387811634349},{"x":44.007265620190836,"y":17.985312403816557},{"x":44.108699907663905,"y":17.985312403816557},{"x":44.21013419513697,"y":17.985312403816557},{"x":44.31156848261004,"y":17.985312403816557},{"x":44.41300277008311,"y":17.985312403816557},{"x":44.41300277008311,"y":17.985312403816557},{"x":44.51443705755618,"y":17.985312403816557},{"x":44.61587134502925,"y":18.086746691289626},{"x":44.71730563250232,"y":18.086746691289626},{"x":44.818739919975386,"y":18.086746691289626},{"x":44.818739919975386,"y":18.086746691289626},{"x":44.920174207448454,"y":18.086746691289626},{"x":45.02160849492152,"y":18.086746691289626},{"x":45.12304278239459,"y":18.086746691289626},{"x":45.22447706986766,"y":18.086746691289626},{"x":45.22447706986766,"y":18.086746691289626},{"x":45.32591135734073,"y":18.086746691289626},{"x":45.32591135734073,"y":18.188180978762695},{"x":45.4273456448138,"y":18.188180978762695},{"x":45.52877993228687,"y":18.188180978762695},{"x":45.630214219759935,"y":18.188180978762695},{"x":45.630214219759935,"y":18.188180978762695},{"x":45.731648507233004,"y":18.188180978762695},{"x":45.83308279470607,"y":18.289615266235764},{"x":45.93451708217914,"y":18.289615266235764},{"x":46.03595136965221,"y":18.289615266235764},{"x":46.03595136965221,"y":18.289615266235764},{"x":46.03595136965221,"y":18.391049553708832},{"x":46.13738565712528,"y":18.391049553708832},{"x":46.23881994459835,"y":18.391049553708832},{"x":46.340254232071416,"y":18.4924838411819},{"x":46.441688519544485,"y":18.4924838411819},{"x":46.441688519544485,"y":18.4924838411819},{"x":46.441688519544485,"y":18.4924838411819},{"x":46.543122807017554,"y":18.4924838411819},{"x":46.543122807017554,"y":18.4924838411819},{"x":46.64455709449062,"y":18.4924838411819},{"x":46.64455709449062,"y":18.4924838411819},{"x":46.74599138196369,"y":18.4924838411819},{"x":46.84742566943676,"y":18.4924838411819},{"x":46.84742566943676,"y":18.4924838411819},{"x":46.84742566943676,"y":18.4924838411819},{"x":46.94885995690983,"y":18.59391812865497},{"x":47.0502942443829,"y":18.59391812865497},{"x":47.0502942443829,"y":18.59391812865497},{"x":47.151728531855966,"y":18.69535241612804},{"x":47.253162819329035,"y":18.69535241612804},{"x":47.253162819329035,"y":18.69535241612804},{"x":47.253162819329035,"y":18.69535241612804},{"x":47.253162819329035,"y":18.69535241612804},{"x":47.3545971068021,"y":18.69535241612804},{"x":47.3545971068021,"y":18.796786703601107},{"x":47.45603139427517,"y":18.796786703601107},{"x":47.45603139427517,"y":18.898220991074176},{"x":47.55746568174824,"y":18.898220991074176},{"x":47.55746568174824,"y":18.898220991074176},{"x":47.65889996922131,"y":18.898220991074176},{"x":47.65889996922131,"y":18.898220991074176},{"x":47.65889996922131,"y":18.898220991074176},{"x":47.65889996922131,"y":18.898220991074176},{"x":47.65889996922131,"y":18.898220991074176},{"x":47.76033425669438,"y":18.898220991074176},{"x":47.86176854416745,"y":18.898220991074176},{"x":47.86176854416745,"y":18.999655278547245},{"x":47.86176854416745,"y":18.999655278547245},{"x":47.86176854416745,"y":18.999655278547245},{"x":47.963202831640515,"y":18.999655278547245},{"x":47.963202831640515,"y":19.101089566020313},{"x":48.064637119113584,"y":19.101089566020313},{"x":48.064637119113584,"y":19.202523853493382},{"x":48.16607140658665,"y":19.202523853493382},{"x":48.16607140658665,"y":19.202523853493382},{"x":48.26750569405972,"y":19.30395814096645},{"x":48.36893998153279,"y":19.30395814096645},{"x":48.36893998153279,"y":19.30395814096645},{"x":48.47037426900586,"y":19.30395814096645},{"x":48.47037426900586,"y":19.30395814096645},{"x":48.47037426900586,"y":19.40539242843952},{"x":48.57180855647893,"y":19.40539242843952},{"x":48.673242843951996,"y":19.40539242843952},{"x":48.774677131425065,"y":19.506826715912588},{"x":48.774677131425065,"y":19.506826715912588},{"x":48.87611141889813,"y":19.506826715912588},{"x":48.87611141889813,"y":19.506826715912588},{"x":48.977545706371195,"y":19.506826715912588},{"x":49.078979993844264,"y":19.506826715912588},{"x":49.18041428131733,"y":19.506826715912588},{"x":49.18041428131733,"y":19.506826715912588},{"x":49.2818485687904,"y":19.506826715912588},{"x":49.2818485687904,"y":19.506826715912588},{"x":49.38328285626347,"y":19.608261003385657},{"x":49.48471714373654,"y":19.608261003385657},{"x":49.58615143120961,"y":19.608261003385657},{"x":49.687585718682676,"y":19.709695290858726},{"x":49.687585718682676,"y":19.709695290858726},{"x":49.789020006155745,"y":19.709695290858726},{"x":49.890454293628814,"y":19.709695290858726},{"x":49.99188858110188,"y":19.709695290858726},{"x":50.09332286857495,"y":19.709695290858726},{"x":50.09332286857495,"y":19.709695290858726},{"x":50.19475715604802,"y":19.709695290858726},{"x":50.29619144352109,"y":19.709695290858726},{"x":50.39762573099416,"y":19.709695290858726},{"x":50.499060018467226,"y":19.709695290858726},{"x":50.499060018467226,"y":19.709695290858726},{"x":50.600494305940295,"y":19.709695290858726},{"x":50.70192859341336,"y":19.709695290858726},{"x":50.80336288088643,"y":19.709695290858726},{"x":50.9047971683595,"y":19.709695290858726},{"x":50.9047971683595,"y":19.709695290858726},{"x":51.00623145583257,"y":19.709695290858726},{"x":51.10766574330564,"y":19.709695290858726},{"x":51.20910003077871,"y":19.709695290858726},{"x":51.310534318251776,"y":19.709695290858726},{"x":51.310534318251776,"y":19.709695290858726},{"x":51.411968605724844,"y":19.709695290858726},{"x":51.51340289319791,"y":19.709695290858726},{"x":51.61483718067098,"y":19.709695290858726},{"x":51.71627146814405,"y":19.709695290858726},{"x":51.71627146814405,"y":19.709695290858726},{"x":51.81770575561712,"y":19.709695290858726},{"x":51.91914004309019,"y":19.709695290858726},{"x":52.02057433056326,"y":19.709695290858726},{"x":52.122008618036325,"y":19.709695290858726},{"x":52.122008618036325,"y":19.709695290858726},{"x":52.223442905509394,"y":19.709695290858726},{"x":52.32487719298246,"y":19.709695290858726},{"x":52.42631148045553,"y":19.709695290858726},{"x":52.5277457679286,"y":19.709695290858726},{"x":52.5277457679286,"y":19.709695290858726},{"x":52.62918005540167,"y":19.709695290858726},{"x":52.73061434287474,"y":19.709695290858726},{"x":52.832048630347806,"y":19.709695290858726},{"x":52.933482917820875,"y":19.709695290858726},{"x":52.933482917820875,"y":19.709695290858726},{"x":53.034917205293944,"y":19.811129578331794},{"x":53.13635149276701,"y":19.811129578331794},{"x":53.23778578024008,"y":19.811129578331794},{"x":53.33922006771315,"y":19.811129578331794},{"x":53.33922006771315,"y":19.811129578331794},{"x":53.44065435518622,"y":19.811129578331794},{"x":53.54208864265929,"y":19.811129578331794},{"x":53.643522930132356,"y":19.811129578331794},{"x":53.744957217605425,"y":19.811129578331794},{"x":53.744957217605425,"y":19.811129578331794},{"x":53.84639150507849,"y":19.811129578331794},{"x":53.94782579255156,"y":19.811129578331794},{"x":54.04926008002463,"y":19.811129578331794},{"x":54.1506943674977,"y":19.811129578331794},{"x":54.1506943674977,"y":19.811129578331794},{"x":54.25212865497077,"y":19.811129578331794},{"x":54.35356294244384,"y":19.811129578331794},{"x":54.35356294244384,"y":19.912563865804863},{"x":54.454997229916906,"y":19.912563865804863},{"x":54.556431517389974,"y":19.912563865804863},{"x":54.556431517389974,"y":19.912563865804863},{"x":54.65786580486304,"y":19.912563865804863},{"x":54.75930009233611,"y":19.912563865804863},{"x":54.86073437980918,"y":19.912563865804863},{"x":54.96216866728225,"y":19.912563865804863},{"x":54.96216866728225,"y":19.912563865804863},{"x":55.06360295475532,"y":19.912563865804863},{"x":55.16503724222839,"y":19.912563865804863},{"x":55.266471529701455,"y":19.912563865804863},{"x":55.367905817174524,"y":19.912563865804863},{"x":55.367905817174524,"y":19.912563865804863},{"x":55.46934010464759,"y":19.912563865804863},{"x":55.57077439212066,"y":19.912563865804863},{"x":55.67220867959373,"y":19.912563865804863},{"x":55.7736429670668,"y":19.912563865804863},{"x":55.7736429670668,"y":19.912563865804863},{"x":55.87507725453987,"y":19.912563865804863},{"x":55.976511542012936,"y":19.912563865804863},{"x":56.077945829486005,"y":19.912563865804863},{"x":56.179380116959074,"y":19.912563865804863},{"x":56.179380116959074,"y":19.912563865804863},{"x":56.28081440443214,"y":19.912563865804863},{"x":56.38224869190521,"y":19.912563865804863},{"x":56.48368297937828,"y":19.912563865804863},{"x":56.58511726685135,"y":19.912563865804863},{"x":56.58511726685135,"y":19.912563865804863},{"x":56.68655155432442,"y":19.912563865804863},{"x":56.787985841797486,"y":19.811129578331794},{"x":56.889420129270555,"y":19.811129578331794},{"x":56.99085441674362,"y":19.811129578331794},{"x":56.99085441674362,"y":19.811129578331794},{"x":56.99085441674362,"y":19.709695290858726},{"x":57.09228870421669,"y":19.709695290858726},{"x":57.19372299168976,"y":19.709695290858726},{"x":57.29515727916283,"y":19.709695290858726},{"x":57.3965915666359,"y":19.709695290858726},{"x":57.3965915666359,"y":19.709695290858726},{"x":57.49802585410897,"y":19.709695290858726},{"x":57.599460141582036,"y":19.709695290858726},{"x":57.700894429055104,"y":19.608261003385657},{"x":57.80232871652817,"y":19.608261003385657},{"x":57.80232871652817,"y":19.608261003385657},{"x":57.90376300400124,"y":19.608261003385657},{"x":58.00519729147431,"y":19.506826715912588},{"x":58.10663157894738,"y":19.506826715912588},{"x":58.20806586642045,"y":19.40539242843952},{"x":58.20806586642045,"y":19.40539242843952},{"x":58.30950015389352,"y":19.40539242843952},{"x":58.410934441366585,"y":19.40539242843952},{"x":58.512368728839654,"y":19.40539242843952},{"x":58.61380301631272,"y":19.30395814096645},{"x":58.61380301631272,"y":19.30395814096645},{"x":58.71523730378579,"y":19.30395814096645},{"x":58.71523730378579,"y":19.30395814096645},{"x":58.81667159125886,"y":19.30395814096645},{"x":58.91810587873193,"y":19.30395814096645},{"x":59.019540166205,"y":19.30395814096645},{"x":59.019540166205,"y":19.30395814096645},{"x":59.019540166205,"y":19.30395814096645},{"x":59.120974453678066,"y":19.30395814096645},{"x":59.222408741151135,"y":19.30395814096645},{"x":59.222408741151135,"y":19.30395814096645},{"x":59.323843028624204,"y":19.30395814096645},{"x":59.42527731609727,"y":19.30395814096645},{"x":59.42527731609727,"y":19.30395814096645},{"x":59.42527731609727,"y":19.30395814096645},{"x":59.52671160357034,"y":19.30395814096645},{"x":59.62814589104341,"y":19.30395814096645},{"x":59.72958017851648,"y":19.30395814096645},{"x":59.83101446598955,"y":19.30395814096645},{"x":59.83101446598955,"y":19.30395814096645},{"x":59.83101446598955,"y":19.30395814096645},{"x":59.932448753462616,"y":19.30395814096645},{"x":60.033883040935685,"y":19.30395814096645},{"x":60.13531732840875,"y":19.30395814096645},{"x":60.13531732840875,"y":19.30395814096645},{"x":60.23675161588182,"y":19.30395814096645},{"x":60.23675161588182,"y":19.30395814096645},{"x":60.33818590335489,"y":19.30395814096645},{"x":60.43962019082796,"y":19.30395814096645},{"x":60.54105447830103,"y":19.30395814096645},{"x":60.6424887657741,"y":19.30395814096645},{"x":60.6424887657741,"y":19.30395814096645},{"x":60.743923053247165,"y":19.30395814096645},{"x":60.743923053247165,"y":19.30395814096645},{"x":60.845357340720234,"y":19.30395814096645},{"x":60.946791628193296,"y":19.30395814096645},{"x":61.048225915666364,"y":19.30395814096645},{"x":61.048225915666364,"y":19.30395814096645},{"x":61.048225915666364,"y":19.30395814096645},{"x":61.14966020313943,"y":19.30395814096645},{"x":61.2510944906125,"y":19.30395814096645},{"x":61.35252877808557,"y":19.30395814096645},{"x":61.35252877808557,"y":19.30395814096645},{"x":61.45396306555864,"y":19.30395814096645},{"x":61.45396306555864,"y":19.30395814096645},{"x":61.45396306555864,"y":19.30395814096645},{"x":61.55539735303171,"y":19.30395814096645},{"x":61.65683164050478,"y":19.30395814096645},{"x":61.65683164050478,"y":19.30395814096645},{"x":61.758265927977845,"y":19.30395814096645},{"x":61.758265927977845,"y":19.30395814096645},{"x":61.758265927977845,"y":19.30395814096645},{"x":61.859700215450914,"y":19.30395814096645},{"x":61.859700215450914,"y":19.40539242843952},{"x":61.859700215450914,"y":19.40539242843952},{"x":61.859700215450914,"y":19.40539242843952},{"x":61.859700215450914,"y":19.506826715912588},{"x":61.859700215450914,"y":19.608261003385657},{"x":61.859700215450914,"y":19.608261003385657},{"x":61.859700215450914,"y":19.608261003385657},{"x":61.96113450292398,"y":19.709695290858726},{"x":61.96113450292398,"y":19.709695290858726},{"x":61.96113450292398,"y":19.709695290858726},{"x":61.96113450292398,"y":19.811129578331794},{"x":61.96113450292398,"y":19.912563865804863},{"x":62.06256879039705,"y":19.912563865804863},{"x":62.06256879039705,"y":20.01399815327793},{"x":62.06256879039705,"y":20.115432440751},{"x":62.06256879039705,"y":20.115432440751},{"x":62.06256879039705,"y":20.115432440751},{"x":62.06256879039705,"y":20.21686672822407},{"x":62.06256879039705,"y":20.318301015697138},{"x":62.06256879039705,"y":20.419735303170206},{"x":62.16400307787012,"y":20.521169590643275},{"x":62.16400307787012,"y":20.521169590643275},{"x":62.16400307787012,"y":20.622603878116344},{"x":62.16400307787012,"y":20.724038165589413},{"x":62.26543736534319,"y":20.82547245306248},{"x":62.26543736534319,"y":20.92690674053555},{"x":62.26543736534319,"y":20.92690674053555},{"x":62.26543736534319,"y":21.02834102800862},{"x":62.26543736534319,"y":21.129775315481687},{"x":62.26543736534319,"y":21.231209602954756},{"x":62.26543736534319,"y":21.332643890427825},{"x":62.36687165281626,"y":21.332643890427825},{"x":62.36687165281626,"y":21.434078177900894},{"x":62.36687165281626,"y":21.535512465373962},{"x":62.36687165281626,"y":21.63694675284703},{"x":62.36687165281626,"y":21.7383810403201},{"x":62.36687165281626,"y":21.7383810403201},{"x":62.36687165281626,"y":21.83981532779317},{"x":62.468305940289326,"y":21.941249615266237},{"x":62.468305940289326,"y":22.042683902739306},{"x":62.569740227762395,"y":22.144118190212374},{"x":62.569740227762395,"y":22.144118190212374},{"x":62.569740227762395,"y":22.245552477685443},{"x":62.569740227762395,"y":22.346986765158512},{"x":62.569740227762395,"y":22.44842105263158},{"x":62.671174515235464,"y":22.54985534010465},{"x":62.671174515235464,"y":22.54985534010465},{"x":62.671174515235464,"y":22.651289627577718},{"x":62.671174515235464,"y":22.752723915050787},{"x":62.671174515235464,"y":22.854158202523855},{"x":62.671174515235464,"y":22.955592489996924},{"x":62.671174515235464,"y":22.955592489996924},{"x":62.671174515235464,"y":23.057026777469993},{"x":62.671174515235464,"y":23.15846106494306},{"x":62.671174515235464,"y":23.25989535241613},{"x":62.671174515235464,"y":23.3613296398892},{"x":62.671174515235464,"y":23.3613296398892},{"x":62.77260880270853,"y":23.462763927362268},{"x":62.77260880270853,"y":23.56419821483533},{"x":62.77260880270853,"y":23.665632502308398},{"x":62.77260880270853,"y":23.767066789781467},{"x":62.77260880270853,"y":23.767066789781467},{"x":62.77260880270853,"y":23.868501077254535},{"x":62.8740430901816,"y":23.969935364727604},{"x":62.8740430901816,"y":24.071369652200673},{"x":62.8740430901816,"y":24.17280393967374},{"x":62.8740430901816,"y":24.17280393967374},{"x":62.97547737765467,"y":24.27423822714681},{"x":62.97547737765467,"y":24.37567251461988},{"x":63.07691166512774,"y":24.477106802092948},{"x":63.07691166512774,"y":24.578541089566016},{"x":63.07691166512774,"y":24.578541089566016},{"x":63.07691166512774,"y":24.679975377039085},{"x":63.07691166512774,"y":24.781409664512154},{"x":63.07691166512774,"y":24.882843951985222},{"x":63.07691166512774,"y":24.98427823945829},{"x":63.07691166512774,"y":24.98427823945829},{"x":63.07691166512774,"y":25.08571252693136},{"x":63.07691166512774,"y":25.18714681440443},{"x":63.07691166512774,"y":25.288581101877497},{"x":63.07691166512774,"y":25.390015389350566},{"x":63.07691166512774,"y":25.390015389350566},{"x":63.07691166512774,"y":25.491449676823635},{"x":63.07691166512774,"y":25.694318251769772},{"x":63.07691166512774,"y":25.79575253924284},{"x":63.07691166512774,"y":25.79575253924284},{"x":63.07691166512774,"y":25.89718682671591},{"x":63.07691166512774,"y":25.99862111418898},{"x":63.07691166512774,"y":26.100055401662047},{"x":63.07691166512774,"y":26.201489689135116},{"x":63.07691166512774,"y":26.201489689135116},{"x":63.07691166512774,"y":26.302923976608184},{"x":63.07691166512774,"y":26.404358264081253},{"x":63.07691166512774,"y":26.505792551554322},{"x":63.07691166512774,"y":26.60722683902739},{"x":63.07691166512774,"y":26.60722683902739},{"x":63.07691166512774,"y":26.70866112650046},{"x":63.07691166512774,"y":26.810095413973528},{"x":63.07691166512774,"y":26.911529701446597},{"x":63.07691166512774,"y":27.012963988919665},{"x":63.07691166512774,"y":27.012963988919665},{"x":63.07691166512774,"y":27.114398276392734},{"x":63.07691166512774,"y":27.215832563865803},{"x":63.07691166512774,"y":27.31726685133887},{"x":63.07691166512774,"y":27.41870113881194},{"x":63.07691166512774,"y":27.41870113881194},{"x":63.07691166512774,"y":27.52013542628501},{"x":63.07691166512774,"y":27.621569713758078},{"x":63.07691166512774,"y":27.723004001231146},{"x":63.07691166512774,"y":27.824438288704215},{"x":63.07691166512774,"y":27.824438288704215},{"x":63.07691166512774,"y":27.925872576177284},{"x":63.07691166512774,"y":28.027306863650352},{"x":63.07691166512774,"y":28.12874115112342},{"x":63.07691166512774,"y":28.23017543859649},{"x":63.07691166512774,"y":28.23017543859649},{"x":63.07691166512774,"y":28.33160972606956},{"x":63.07691166512774,"y":28.433044013542627},{"x":63.07691166512774,"y":28.534478301015696},{"x":63.07691166512774,"y":28.635912588488765},{"x":63.07691166512774,"y":28.635912588488765},{"x":63.07691166512774,"y":28.737346875961833},{"x":63.07691166512774,"y":28.838781163434902},{"x":63.07691166512774,"y":28.94021545090797},{"x":63.17834595260081,"y":29.04164973838104},{"x":63.17834595260081,"y":29.04164973838104},{"x":63.17834595260081,"y":29.143084025854108},{"x":63.17834595260081,"y":29.244518313327177},{"x":63.17834595260081,"y":29.345952600800246},{"x":63.279780240073876,"y":29.447386888273314},{"x":63.279780240073876,"y":29.447386888273314},{"x":63.279780240073876,"y":29.548821175746383},{"x":63.279780240073876,"y":29.65025546321945},{"x":63.279780240073876,"y":29.75168975069252},{"x":63.381214527546945,"y":29.85312403816559},{"x":63.381214527546945,"y":29.85312403816559},{"x":63.381214527546945,"y":29.954558325638658},{"x":63.48264881502001,"y":29.954558325638658},{"x":63.48264881502001,"y":30.055992613111727},{"x":65.10559741458911,"y":20.21686672822407},{"x":65.10559741458911,"y":20.318301015697138},{"x":65.10559741458911,"y":20.318301015697138},{"x":65.20703170206218,"y":20.21686672822407},{"x":65.30846598953525,"y":20.21686672822407},{"x":65.40990027700832,"y":20.21686672822407},{"x":65.51133456448139,"y":20.21686672822407},{"x":65.51133456448139,"y":20.21686672822407},{"x":65.61276885195446,"y":20.21686672822407},{"x":65.71420313942753,"y":20.21686672822407},{"x":65.8156374269006,"y":20.115432440751},{"x":65.91707171437366,"y":20.115432440751},{"x":65.91707171437366,"y":20.115432440751},{"x":66.01850600184673,"y":20.115432440751},{"x":66.1199402893198,"y":20.115432440751},{"x":66.22137457679287,"y":20.115432440751},{"x":66.32280886426594,"y":20.115432440751},{"x":66.32280886426594,"y":20.115432440751},{"x":66.424243151739,"y":20.01399815327793},{"x":66.52567743921207,"y":20.01399815327793},{"x":66.52567743921207,"y":20.01399815327793},{"x":66.62711172668514,"y":19.912563865804863},{"x":66.62711172668514,"y":19.912563865804863},{"x":66.72854601415821,"y":19.608261003385657},{"x":66.72854601415821,"y":19.709695290858726},{"x":66.72854601415821,"y":19.811129578331794},{"x":66.72854601415821,"y":19.811129578331794},{"x":66.72854601415821,"y":19.811129578331794},{"x":66.82998030163128,"y":19.608261003385657},{"x":66.82998030163128,"y":19.608261003385657},{"x":66.82998030163128,"y":19.709695290858726},{"x":66.82998030163128,"y":19.709695290858726},{"x":66.82998030163128,"y":19.709695290858726},{"x":66.93141458910435,"y":19.506826715912588},{"x":66.93141458910435,"y":19.608261003385657},{"x":66.93141458910435,"y":19.709695290858726},{"x":67.03284887657742,"y":19.506826715912588},{"x":67.03284887657742,"y":19.506826715912588},{"x":67.13428316405049,"y":19.506826715912588},{"x":67.13428316405049,"y":19.506826715912588},{"x":67.23571745152356,"y":19.506826715912588},{"x":67.23571745152356,"y":19.506826715912588},{"x":67.33715173899662,"y":19.506826715912588},{"x":67.4385860264697,"y":19.506826715912588},{"x":67.54002031394276,"y":19.506826715912588},{"x":67.54002031394276,"y":19.506826715912588},{"x":67.54002031394276,"y":19.506826715912588},{"x":67.64145460141583,"y":19.40539242843952},{"x":67.7428888888889,"y":19.40539242843952},{"x":67.84432317636197,"y":19.40539242843952},{"x":67.84432317636197,"y":19.30395814096645},{"x":67.94575746383504,"y":19.30395814096645},{"x":67.94575746383504,"y":19.30395814096645},{"x":68.0471917513081,"y":19.30395814096645},{"x":68.14862603878117,"y":19.30395814096645},{"x":68.25006032625424,"y":19.30395814096645},{"x":68.35149461372731,"y":19.30395814096645},{"x":68.35149461372731,"y":19.30395814096645},{"x":68.45292890120038,"y":19.202523853493382},{"x":68.55436318867345,"y":19.202523853493382},{"x":68.65579747614652,"y":19.202523853493382},{"x":68.75723176361959,"y":19.202523853493382},{"x":68.75723176361959,"y":19.101089566020313},{"x":68.85866605109265,"y":19.101089566020313},{"x":69.06153462603879,"y":18.999655278547245},{"x":69.16296891351186,"y":18.999655278547245},{"x":69.26440320098493,"y":18.999655278547245},{"x":69.56870606340414,"y":18.898220991074176},{"x":69.56870606340414,"y":18.898220991074176},{"x":69.87300892582334,"y":18.898220991074176},{"x":70.07587750076948,"y":18.898220991074176},{"x":70.27874607571562,"y":18.898220991074176},{"x":70.48161465066175,"y":18.796786703601107},{"x":70.68448322560789,"y":18.796786703601107},{"x":70.88735180055403,"y":18.796786703601107},{"x":71.09022037550017,"y":18.796786703601107},{"x":71.19165466297324,"y":18.796786703601107},{"x":71.2930889504463,"y":18.796786703601107},{"x":71.39452323791937,"y":18.796786703601107},{"x":71.49595752539244,"y":18.796786703601107},{"x":71.59739181286551,"y":18.796786703601107},{"x":71.69882610033858,"y":18.796786703601107},{"x":71.80026038781165,"y":18.796786703601107},{"x":71.90169467528472,"y":18.796786703601107},{"x":72.00312896275778,"y":18.796786703601107},{"x":72.10456325023085,"y":18.796786703601107},{"x":72.30743182517699,"y":18.898220991074176},{"x":72.40886611265006,"y":18.898220991074176},{"x":72.6117346875962,"y":18.898220991074176},{"x":72.71316897506927,"y":18.898220991074176},{"x":72.81460326254233,"y":18.898220991074176},{"x":72.81460326254233,"y":18.898220991074176},{"x":73.01747183748847,"y":18.898220991074176},{"x":73.11890612496154,"y":18.999655278547245},{"x":73.22034041243461,"y":18.999655278547245},{"x":73.32177469990768,"y":19.101089566020313},{"x":73.52464327485382,"y":19.101089566020313},{"x":73.72751184979995,"y":19.101089566020313},{"x":74.03181471221916,"y":19.101089566020313},{"x":74.2346832871653,"y":19.101089566020313},{"x":74.43755186211143,"y":19.101089566020313},{"x":74.64042043705757,"y":19.101089566020313},{"x":74.84328901200371,"y":19.101089566020313},{"x":75.04615758694985,"y":19.101089566020313},{"x":75.24902616189598,"y":19.101089566020313},{"x":75.35046044936905,"y":19.101089566020313},{"x":75.45189473684212,"y":19.101089566020313},{"x":75.65476331178826,"y":19.101089566020313},{"x":75.65476331178826,"y":19.101089566020313},{"x":75.75619759926133,"y":19.101089566020313},{"x":75.8576318867344,"y":18.999655278547245},{"x":75.95906617420746,"y":18.999655278547245},{"x":76.06050046168053,"y":18.999655278547245},{"x":76.06050046168053,"y":18.999655278547245},{"x":76.26336903662667,"y":18.898220991074176},{"x":76.36480332409974,"y":18.898220991074176},{"x":76.46623761157281,"y":18.898220991074176},{"x":76.46623761157281,"y":18.898220991074176},{"x":76.66910618651895,"y":18.898220991074176},{"x":76.77054047399201,"y":18.898220991074176},{"x":76.87197476146508,"y":18.898220991074176},{"x":76.97340904893815,"y":18.898220991074176},{"x":77.07484333641122,"y":18.898220991074176},{"x":77.27771191135736,"y":18.898220991074176},{"x":77.27771191135736,"y":18.898220991074176},{"x":77.4805804863035,"y":18.898220991074176},{"x":77.58201477377656,"y":18.898220991074176},{"x":77.68344906124963,"y":18.898220991074176},{"x":77.88631763619577,"y":18.898220991074176},{"x":77.98775192366884,"y":18.898220991074176},{"x":78.08918621114191,"y":18.898220991074176},{"x":78.29205478608804,"y":18.898220991074176},{"x":78.49492336103418,"y":18.898220991074176},{"x":78.69779193598032,"y":18.898220991074176},{"x":78.90066051092646,"y":18.898220991074176},{"x":79.10352908587258,"y":18.796786703601107},{"x":79.30639766081872,"y":18.796786703601107},{"x":79.30639766081872,"y":18.69535241612804},{"x":79.40783194829179,"y":18.69535241612804},{"x":79.50926623576485,"y":18.69535241612804},{"x":79.61070052323792,"y":18.69535241612804},{"x":79.71213481071099,"y":18.59391812865497},{"x":79.71213481071099,"y":18.59391812865497},{"x":79.81356909818406,"y":18.59391812865497},{"x":79.91500338565713,"y":18.4924838411819},{"x":80.11787196060327,"y":18.4924838411819},{"x":80.21930624807634,"y":18.4924838411819},{"x":80.42217482302247,"y":18.4924838411819},{"x":80.62504339796861,"y":18.391049553708832},{"x":80.82791197291475,"y":18.391049553708832},{"x":80.92934626038782,"y":18.391049553708832},{"x":80.92934626038782,"y":18.391049553708832},{"x":81.03078054786089,"y":18.391049553708832},{"x":81.13221483533395,"y":18.4924838411819},{"x":81.23364912280702,"y":18.4924838411819},{"x":81.33508341028009,"y":18.4924838411819},{"x":81.33508341028009,"y":18.4924838411819},{"x":81.43651769775316,"y":18.4924838411819},{"x":81.53795198522623,"y":18.4924838411819},{"x":81.6393862726993,"y":18.59391812865497},{"x":81.74082056017237,"y":18.59391812865497},{"x":81.74082056017237,"y":18.59391812865497},{"x":81.9436891351185,"y":18.69535241612804},{"x":82.14655771006464,"y":18.69535241612804},{"x":82.24799199753771,"y":18.69535241612804},{"x":82.45086057248385,"y":18.69535241612804},{"x":82.65372914742998,"y":18.69535241612804},{"x":82.85659772237612,"y":18.69535241612804},{"x":82.95803200984919,"y":18.69535241612804},{"x":82.95803200984919,"y":18.69535241612804},{"x":83.05946629732226,"y":18.69535241612804},{"x":83.16090058479533,"y":18.69535241612804},{"x":83.2623348722684,"y":18.69535241612804},{"x":83.36376915974147,"y":18.69535241612804},{"x":83.46520344721453,"y":18.69535241612804},{"x":83.5666377346876,"y":18.69535241612804},{"x":83.76950630963374,"y":18.69535241612804},{"x":83.87094059710681,"y":18.69535241612804},{"x":83.97237488457988,"y":18.69535241612804},{"x":84.07380917205295,"y":18.796786703601107},{"x":84.17524345952602,"y":18.796786703601107},{"x":84.17524345952602,"y":18.796786703601107},{"x":84.27667774699908,"y":18.796786703601107},{"x":84.37811203447215,"y":18.796786703601107},{"x":84.47954632194522,"y":18.898220991074176},{"x":84.58098060941829,"y":18.898220991074176},{"x":84.58098060941829,"y":18.898220991074176},{"x":84.78384918436443,"y":18.898220991074176},{"x":84.98671775931057,"y":18.898220991074176},{"x":84.98671775931057,"y":18.898220991074176},{"x":85.08815204678363,"y":18.898220991074176},{"x":85.1895863342567,"y":18.898220991074176},{"x":85.29102062172977,"y":18.898220991074176},{"x":85.39245490920284,"y":18.898220991074176},{"x":85.39245490920284,"y":18.796786703601107},{"x":85.49388919667591,"y":18.796786703601107},{"x":85.59532348414898,"y":18.796786703601107},{"x":85.59532348414898,"y":18.69535241612804},{"x":85.79819205909511,"y":18.69535241612804},{"x":85.89962634656818,"y":18.69535241612804},{"x":86.00106063404125,"y":18.69535241612804},{"x":86.10249492151432,"y":18.69535241612804},{"x":86.20392920898739,"y":18.69535241612804},{"x":86.5082320714066,"y":18.59391812865497},{"x":86.71110064635273,"y":18.59391812865497},{"x":87.01540350877194,"y":18.4924838411819},{"x":87.21827208371808,"y":18.4924838411819},{"x":87.52257494613728,"y":18.391049553708832},{"x":87.82687780855649,"y":18.391049553708832},{"x":88.02974638350263,"y":18.289615266235764},{"x":88.23261495844876,"y":18.289615266235764},{"x":88.63835210834104,"y":18.289615266235764},{"x":88.63835210834104,"y":18.289615266235764},{"x":88.84122068328718,"y":18.289615266235764},{"x":89.04408925823331,"y":18.289615266235764},{"x":89.34839212065252,"y":18.289615266235764},{"x":89.65269498307173,"y":18.289615266235764},{"x":89.85556355801786,"y":18.289615266235764},{"x":90.15986642043707,"y":18.289615266235764},{"x":90.46416928285628,"y":18.289615266235764},{"x":90.66703785780241,"y":18.289615266235764},{"x":91.07277500769469,"y":18.289615266235764},{"x":91.27564358264083,"y":18.289615266235764},{"x":91.57994644506003,"y":18.289615266235764},{"x":91.88424930747924,"y":18.289615266235764},{"x":91.9856835949523,"y":18.289615266235764},{"x":92.28998645737151,"y":18.289615266235764},{"x":92.49285503231765,"y":18.391049553708832},{"x":92.69572360726379,"y":18.391049553708832},{"x":92.79715789473686,"y":18.391049553708832},{"x":93.000026469683,"y":18.4924838411819},{"x":93.10146075715606,"y":18.4924838411819},{"x":93.3043293321022,"y":18.4924838411819},{"x":93.50719790704834,"y":18.4924838411819},{"x":93.6086321945214,"y":18.59391812865497},{"x":93.81150076946754,"y":18.59391812865497},{"x":93.91293505694061,"y":18.69535241612804},{"x":94.01436934441368,"y":18.69535241612804},{"x":94.11580363188675,"y":18.796786703601107},{"x":94.31867220683289,"y":18.796786703601107},{"x":94.31867220683289,"y":18.898220991074176},{"x":94.42010649430595,"y":18.898220991074176},{"x":94.72440935672516,"y":18.898220991074176},{"x":94.82584364419823,"y":18.898220991074176},{"x":95.02871221914437,"y":18.898220991074176},{"x":95.13014650661744,"y":18.999655278547245},{"x":95.33301508156357,"y":18.999655278547245},{"x":95.43444936903664,"y":18.999655278547245},{"x":95.53588365650971,"y":18.999655278547245},{"x":95.73875223145585,"y":19.101089566020313},{"x":95.94162080640199,"y":19.101089566020313},{"x":96.14448938134812,"y":19.202523853493382},{"x":96.34735795629426,"y":19.30395814096645},{"x":96.44879224376733,"y":19.30395814096645},{"x":96.65166081871347,"y":19.30395814096645},{"x":96.75309510618654,"y":19.30395814096645},{"x":97.15883225607881,"y":19.30395814096645},{"x":97.36170083102495,"y":19.30395814096645},{"x":97.56456940597108,"y":19.30395814096645},{"x":97.86887226839029,"y":19.30395814096645},{"x":97.97030655586336,"y":19.30395814096645},{"x":98.1731751308095,"y":19.30395814096645},{"x":98.27460941828257,"y":19.30395814096645},{"x":98.37604370575563,"y":19.30395814096645},{"x":98.37604370575563,"y":19.30395814096645},{"x":98.57891228070177,"y":19.30395814096645},{"x":98.68034656817484,"y":19.30395814096645},{"x":98.78178085564791,"y":19.30395814096645},{"x":98.88321514312098,"y":19.30395814096645},{"x":98.98464943059405,"y":19.30395814096645},{"x":99.08608371806712,"y":19.202523853493382},{"x":99.18751800554018,"y":19.202523853493382},{"x":99.28895229301325,"y":19.202523853493382},{"x":99.49182086795939,"y":19.202523853493382},{"x":99.59325515543246,"y":19.202523853493382},{"x":99.59325515543246,"y":19.202523853493382},{"x":99.69468944290553,"y":19.101089566020313},{"x":99.7961237303786,"y":19.101089566020313},{"x":99.89755801785167,"y":19.101089566020313},{"x":99.99899230532473,"y":18.999655278547245},{"x":99.99899230532473,"y":18.999655278547245},{"x":100.1004265927978,"y":18.999655278547245},{"x":100.20186088027087,"y":18.898220991074176},{"x":100.30329516774394,"y":18.898220991074176},{"x":100.40472945521701,"y":18.898220991074176},{"x":100.40472945521701,"y":18.898220991074176},{"x":100.60759803016315,"y":18.898220991074176},{"x":100.70903231763621,"y":18.898220991074176},{"x":100.81046660510928,"y":18.898220991074176},{"x":100.81046660510928,"y":18.898220991074176},{"x":100.91190089258235,"y":18.898220991074176},{"x":101.01333518005542,"y":18.898220991074176},{"x":101.11476946752849,"y":18.898220991074176},{"x":101.21620375500156,"y":18.898220991074176},{"x":101.21620375500156,"y":18.898220991074176},{"x":101.31763804247463,"y":18.898220991074176},{"x":101.4190723299477,"y":18.898220991074176},{"x":101.52050661742076,"y":18.898220991074176},{"x":101.62194090489383,"y":18.898220991074176},{"x":101.62194090489383,"y":18.898220991074176},{"x":101.7233751923669,"y":18.898220991074176},{"x":101.82480947983997,"y":18.898220991074176},{"x":101.92624376731304,"y":18.898220991074176},{"x":102.02767805478611,"y":18.898220991074176},{"x":102.02767805478611,"y":18.898220991074176},{"x":102.12911234225918,"y":18.898220991074176},{"x":102.23054662973225,"y":18.898220991074176},{"x":102.33198091720531,"y":18.898220991074176},{"x":102.43341520467838,"y":18.898220991074176},{"x":102.43341520467838,"y":18.898220991074176},{"x":102.53484949215145,"y":18.898220991074176},{"x":102.63628377962452,"y":18.898220991074176},{"x":102.73771806709759,"y":18.898220991074176},{"x":102.83915235457066,"y":18.898220991074176},{"x":102.83915235457066,"y":18.898220991074176},{"x":102.94058664204373,"y":18.898220991074176},{"x":103.0420209295168,"y":18.898220991074176},{"x":103.14345521698986,"y":18.898220991074176},{"x":103.24488950446293,"y":18.898220991074176},{"x":103.24488950446293,"y":18.898220991074176},{"x":103.34632379193599,"y":18.898220991074176},{"x":103.44775807940906,"y":18.796786703601107},{"x":103.54919236688212,"y":18.796786703601107},{"x":103.6506266543552,"y":18.796786703601107},{"x":103.6506266543552,"y":18.796786703601107},{"x":103.75206094182826,"y":18.796786703601107},{"x":103.85349522930133,"y":18.796786703601107}],"parkourConfig":{"dim1":0,"dim2":-1,"dim3":0,"smoothing":15,"waterLevel":0},"creepersConfig":{"width":0.3,"height":5,"spacing":1.5,"type":"Swingable"}},"agents":[{"morphology":"bipedal","name":"Joe","age": "adult","path":"policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1","init_pos":{"x":4.617414269085923,"y":5.71317566524438}},{"morphology":"bipedal","name":"Susan","age": "adult","path":"policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5","init_pos":{"x":4.617785214621425,"y":5.713167020358285}},{"morphology":"chimpanzee","name":"Caesar","age": "adult","path":"policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2","init_pos":{"x":4.667968244565546,"y":14.961059192992844}},{"morphology":"chimpanzee","name":"Jack","age": "adult","path":"policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15","init_pos":{"x":4.667997703147381,"y":14.961059162733482}}],"description":{"EN": {"name":"Hard parkour","text":"This environment features a pretty hard parkour to resolve for both bipedal walkers and chimpanzees."}, "FR": {"name":"Parkour difficile","text":"Ce parkour est assez difficile à résoudre aussi bien pour les bipèdes que pour les chimpanzés."}},"image":"data:image/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAACHYAAAMgCAYAAABMW3cjAAAgAElEQVR4XuzdB3jdV3k/8FdbspZtDW9nJ5CETPZsyyirLS3jT9kllA0tBUoIBAgB0gCB7D1w9t5kFQIk8Yhn4hUnjuMhybIlL8myLdmy/H+uAi5gJ9GV7pXu+Oh5eAD7nPec93N+Sizrq/Mr+MEPfrAnfBAgQIAAAQIECBAgQIAAAQIECBAgQCDHBVq7uuLyefOj6Y7f7tPpzQ8/EI/+5p54RWNjjitojwABAgQIECBAgACBbBMoEOzItiOzXwIECBAgQIAAAQIECBAgQIAAAQIEkhVIhDoWbOmMr3383+Mtx75yn+kzFj0R0268Mk5sqEu2tPEECBAgQIAAAQIECBBIq4BgR1p5FSdAgAABAgQIECBAgAABAgQIECBAYKQFtnR3x3WLFsUV3zszXnnEUfvdzqp1a+PUc8+INzXWj/R2rU+AAAECBAgQIECAAIG/EBDs8EAQIECAAAECBAgQIECAAAECBAgQIJDzAjcsWRq/u+ymF+xzV29vfPDkL8W7J0/MeQsNEiBAgAABAgQIECCQXQKCHdl1XnZLgAABAgQIECBAgAABAgQIECBAgECSAtt27YorFzwRi66/90VnfvbHp8ThxRE1ZWVJrmA4AQIECBAgQIAAAQIE0icg2JE+W5UJECBAgAABAgQIECBAgAABAgQIEMgQgasWLoyZV972orv58ZUXRHfTiphSW5shu7YNAgQIECBAgAABAgQIRAh2eAoIECBAgAABAgQIECBAgAABAgQIEMh5gUsXLIi50+580T5v/M19MePhX8fRjY0576FBAgQIECBAgAABAgSyR0CwI3vOyk4JECBAgAABAgQIECBAgAABAgQIEBikwOVPLozZV734jR2PLZwf19x0VZzYUD/IVUwjQIAAAQIECBAgQIBA6gUEO1JvqiIBAgQIECBAgAABAgQIECBAgAABAhkmcM2SpfHoZTe96K5Wrm2O759/ZryxUbAjw47PdggQIECAAAECBAjktYBgR14fv+YJECBAgAABAgQIECBAgAABAgQI5L7ArHXrY1Fbe8y58pYXbbZn18748Le/Gu+aPCH3UXRIgAABAgQIECBAgEDWCAh2ZM1R2SgBAgQIECBAgAABAgQIECBAgAABAskKPLxyZbzyVW+Mb3zsMwOa+pkfnRwvLymM6rKyAY03iAABAgQIECBAgAABAukWEOxIt7D6BAgQIECAAAECBAgQIECAAAECBAiMiMDG7dvj18uXx2NX3T7g9U+/4vzY1bIyJtfUDHiOgQQIECBAgAABAgQIEEingGBHOnXVJkCAAAECBAgQIECAAAECBAgQIEBgxAQSwY7Za9fGHedfM+A9XPfgvTH7kQfiqIaGAc8xkAABAgQIECBAgAABAukUEOxIp67aBAgQIECAAAECBAgQIECAAAECBAiMmMCStrZ4rKkp5l1z94D38MiT8+L6m38VJzTUD3iOgQQIECBAgAABAgQIEEingGBHOnXVJkCAAAECBAgQIECAAAECBAgQIEBgxAQSN3bMXbs2bkvixo4VLU1x2gU/jTc2CnaM2MFZmAABAgQIECBAgACBvxAQ7PBAECBAgAABAgQIECBAgAABAgQIECCQkwKJGztmNDfHnKvvGnB/3Tt74iPf+Y9456QJA55jIAECBAgQIECAAAECBNIpINiRTl21CRAgQIAAAQIECBAgQIAAAQIECBAYMYHEjR0zm5vj7guvS2oPJ53+rTiqrDiqSkuTmmcwAQIECBAgQIAAAQIE0iEg2JEOVTUJECBAgAABAgQIECBAgAABAgQIEBhxgSfXr48/rFoVi2+4L6m9nHbZudHXujom1dQkNc9gAgQIECBAgAABAgQIpENAsCMdqmoSIECAAAECBAgQIECAAAECBAgQIDDiAokbO363cmU8dNnNSe3lmgfuinmP/m8c2dCQ1DyDCRAgQIAAAQIECBAgkA4BwY50qKpJgAABAgQIECBAgAABAgQIECBAgMCICzR1dsZja9bE7y6/Jam9/OGJOXHDLdfECQ11Sc0zmAABAgQIECBAgAABAukQEOxIh6qaBAgQIECAAAECBAgQIECAAAECBAiMuED7tm3xu1Wr4jdJ3tixvHlN/OjCn8cbGgU7RvwQbYAAAQIECBAgQIAAgRDs8BAQIECAAAECBAgQIECAAAECBAgQIJCTAolXsfx+9ep48JIbk+pve3d3fPzU/4y/nzQhqXkGEyBAgAABAgQIECBAIB0Cgh3pUFWTAAECBAgQIECAAAECBAgQIECAAIERF3hu8+aY3tQUj155W9J7+bfT/jteUVESVaWlSc81gQABAgQIECBAgAABAqkUEOxIpaZaBAgQIECA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gAABAgQIvJiAYIfngwABAgQIECBAgAABAgQIECBAgACBnBRo7uiIB1asiNlX35Wy/n4985G4796b49iGhpTVVIgAAQIECBAgQIAAAQIvJiDY4fkgQIAAAQIECBAgQIAAAQIECBAgQCAnBRKvYnl0zZq47+IbUtbfE8uXxfm/ujBe3VCXspoKESBAgAABAgQIECBA4MUEBDs8HwQIECBAgAABAgQIECBAgAABAgQI5KTAMxs3xoymppS+iqVt86b4jzNPjb8d35iTZpoiQIAAAQIECBAgQCDzBAQ7Mu9M7IgAAQIECBAgQIAAAQIECBAgQIAAgRQIJG7smNnSEndfcG0Kqv1fiQ+e/OX4m8a6KCksTGldxQgQIECAAAECBAgQILA/AcEOzwUBAgQIECBAgAABAgQIECBAgAABAjkpsLStLaY3NcWca+5OaX9f+8WPoqF7a9SPGpXSuooRIECAAAECBAgQIEBgfwKCHZ4LAgQIECBAgAABAgQIECBAgAABAgRyUiBxY8fc1ta47byrU9rfOTdNi7VLF8QhY8aktK5iBAgQIECAAAECBAgQ2J+AYIfnggABAgQIECBAgAABAgQIECBAgACBnBRY3NYWM5qaYm6Kb+y4Z/rv44Ff3xrHNjbkpJumCBAgQIAAAQIECBDILAHBjsw6D7shQIAAAQIECBAgQIAAAQIECBAgQCBFAokbO+asXRu3n39Niio+X2b+M0vjwmkXx6sb6lJaVzECBAgQIECAAAECBAjsT0Cww3NBgAABAgQIECBAgAABAgQIECBAgEBOCsxpaYlH16yJZTc9kNL+1m/aEF/76Q/ib8a7sSOlsIoRIECAAAECBAgQILBfAcEODwYBAgQIECBAgAABAgQIECBAgAABAjkpkLixY0Zzc9xz4XUp7+/93/pivHVcQxQXFqa8toIECBAgQIAAAQIECBD4cwHBDs8DAQIECBAgQIAAAQIECBAgQIAAAQI5KfDspk0xvakppl91e8r7+4+zfhjjd26PuoqKlNdWkAABAgQIECBAgAABAn8uINjheSBAgAABAgQIECBAgAABAgQIECBAICcFEjd2PLJ6ddx/yY0p7++XN1wV65c9GQePGZPy2goSIECAAAECBAgQIEDgzwUEOzwPBAgQIECAAAECBAgQIECAAAECBAjkpEBrV1c8smpV/PbyW1Le392P/S4evO/WOLaxMeW1FSRAgAABAgQIECBAgMCfCwh2eB4IECBAgAABAgQIECBAgAABAgQIEMhJgdatW+MPq1fHw2kIdsxdtiQuufaSeFV9XU7aaYoAAQIECBAgQIAAgcwREOzInLOwEwIECBAgQIAAAQIECBAgQIAAAQIEUijQ/yqWNWvi/otvSGHV50u1bmyPr//8tPibcQ0pr60gAQIECBAgQIAAAQIE/lxAsMPzQIAAAQIECBAgQIAAAQIECBAgQIBATgo8u3FjTG9ujulX3Z6W/v75m1+Id0xojKLCwrTUV5QAAQIECBAgQIAAAQIJAcEOzwEBAgQIECBAgAABAgQIECBAgAABAjkpkLixY2Zzc9x94XVp6e8rPzstJvXuiLEVFWmprygBAgQIECBAgAABAgQSAoIdngMCBAgQIECAAAECBAgQIECAAAECBHJSYE5LSzy6Zk0su+mBtPR31nVXxIbli+Og0aPTUl9RAgQIECBAgAABAgQIJAQEOzwHBAgQIECAAAECBAgQIECAAAECBAjkpEDixo45ra1x+3lXp6W/Ox99OH5z/21xTGNjWuorSoAAAQIECBAgQIAAgYSAYIfngAABAgQIECBAgAABAgQIECBAgACBnBRY0tYW05uaYu41d6elvzlPLY5Lr7s0XlVfl5b6ihIgQIAAAQIECBAgQCAhINjhOSBAgAABAgQIECBAgAABAgQIECBAICcFEjd2zG1dF7edNy0t/bW0t8V//+KH8ZZxDWmprygBAgQIECBAgAABAgQSAoIdngMCBAgQIECAAAECBAgQIECAAAECBHJSIBHsmL9ufdxy7q/S1t/7vvG5eOekCVFYUJC2NRQmQIAAAQIECBAgQCC/BQQ78vv8dU+AAAECBAgQIECAAAECBAgQIEAgZwWGI9jx5Z9+P6b07Ywx5eU566gxAgQIECBAgAABAgRGVkCwY2T9rU6AAAECBAgQIECAAAECBAgQIECAQJoEntm4MWY2N8f0q25P0woRP7v2stj87NI4cPTotK2hMAECBAgQIECAAAEC+S0g2JHf5697AgQIECBAgAABAgQIECBAgAABAjkrkLix49GmprjvouvT1uPtf/hNPPzAHXHMuMa0raEwAQIECBAgQIAAAQL5LSDYkd/nr3sCBAgQIECAAAECBAgQIECAAAECOSvQ1NERDz73XMyedmfaenx86cK44vrL45X1dWlbQ2ECBAgQIECAAAECBPJbQLAjv89f9wQIECBAgAABAgQIECBAgAABAgRyVqCtqyvuW/FczLjqtrT12NS2Lr79yx/Fm8c1pG0NhQkQIECAAAECBAgQyG8BwY78Pn/dEyBAgAABAgQIECBAgAABAgQIEMhZgcSrWB5paor70/gqlr49ffG+b3w+3jN5YhQUFOSspcYIECBAgAABAgQIEBg5AcGOkbO3MgECBAgQIECAAAECBAgQIECAAAECaRRYsWlTzFy7Nh65/JY0rhLxxf85NQ6M3hhdXp7WdRQnQIAAAQIECBAgQCA/BQQ78vPcdU2AAAECBAgQIECAAAECBAgQIEAg5wUSN3bMam2Nu867Oq29nnn1JdG58uk4oLY2resoToAAAQIECBAgQIBAfgoIduTnueuaAAECBAgQIECAAAECBAgQIECAQM4LPNXeHjNb1sasX92e1l5v/f1D8fsH74xjxo1L6zqKEyBAgAABAgQIECCQnwKCHfl57romQIAAAQIECBAgQIAAAQIECBAgkPMCiRs75re1xy1nX5nWXmcueTJ+dcMVcWJ9XVrXUZwAAQIECBAgQIAAgfwUEOzIz3PXNQECBAgQIECAAAECBAgQIECAAIGcF1jS1hYzWlpizrQ709rrmvWtcco5P4k3N9andR3FCRAgQIAAAQIECBDITwHBjvw8d10TIECAAAECBAgQIECAAAECBAgQyHmBxI0dT27YFDf+4rK09tq7e3e8/7+/EO+ZMimt6yhOgAABAgQIECBAgEB+Cgh25Oe565oAAQIECBAgQIAAAQIECBAgQIBAzgs83twcjzU3x9M33p/2Xj9/xnfjkILdUVtenva1LECAAAECBAgQIECAQH4JCHbk13nrlgABAgQIECBAgAABAgQIECBAgEDeCCRu7Hhi05a46eeXpL3nM351UWxbvTym1tamfS0LECBAgAABAgQIECCQXwKCHfl13rolQIAAAQIECBAgQIAAAQIECBAgkDcCT2/YEHPWt8Ujl92U9p5vfvj+ePQ398YrGhvTvpYFCBAgQIAAAQIECBDILwHBjvw6b90SIECAAAECBAgQIECAAAECBAgQyBuBxI0d8zZujlvPujTtPc9YtCCm3XhVnNhQl/a1LECAAAECBAgQIECAQH4JCHbk13nrlgABAgQI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"} \ No newline at end of file diff --git a/demo.css b/demo.css new file mode 100644 index 0000000000000000000000000000000000000000..81265440475f690daf7d995783413cd1355b6cf0 --- /dev/null +++ b/demo.css @@ -0,0 +1,94 @@ +.ib{ + display: inline-block; + margin-right: 30px; +} + +#creepers{ + position: relative; + bottom: 25px; +} + +.btn-asset{ + background-color: #885C00; + color: white; +} + +btn-asset:hover{ + background-color: #885C00; + color: white; +} + +.btn-outline-asset{ + background-color: white; + color: #885C00; + border-color: #885C00; +} + +.btn-outline-asset:hover{ + background-color: #885C00; + color: white; +} + +#agents_list_container{ + height: 400px; + overflow-y: scroll; +} + +.list-group-item{ + border-color: white; +} + +.list-group-item.active{ + background-color: #FFC700; + border-color: #FFC700; +} + +.list-group-item.disabled{ + background-color: lightgrey; + border-color: lightgrey; +} + +hr.solid { + border-top: 2px solid #999; +} + +.card > img{ + height: 125px; + object-fit: cover; + object-position: 5% 0%; +} + +.introjs-tooltip { + font-size: 20px; + min-width: 400px; + max-width: 600px; +} + +.introjs-tooltip-title { + font-size: 22px; + color: #0a41c9; +} + +.introjs-hintReference > .introjs-tooltip{ + font-size: 16px; +} + +.introjs-tooltip ul { + margin-left: 8px; + list-style-type: disc; +} + +.nav-link { + color: black; + font-weight: bold; +} + +.about-text { + font-size: 18px; +} + +.about-subsection { + font-size: 26px; + font-weight: bold; + color: #0a41c9; +} diff --git a/images/about/rl_demo_diagram_EN.png b/images/about/rl_demo_diagram_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..8f973a0d14f204b8d2784936127f1d99bca6de11 Binary files /dev/null and b/images/about/rl_demo_diagram_EN.png differ diff --git a/images/about/rl_demo_diagram_FR.png b/images/about/rl_demo_diagram_FR.png new file mode 100644 index 0000000000000000000000000000000000000000..89d8910d0acadd0c0161eeab30e41e6f7b3c8dce Binary files /dev/null and b/images/about/rl_demo_diagram_FR.png differ diff --git a/images/about/rl_diagram_fr.png b/images/about/rl_diagram_fr.png new file mode 100644 index 0000000000000000000000000000000000000000..f9eb521d16ebe84b86d786d4c33d6a294acf241f Binary files /dev/null and b/images/about/rl_diagram_fr.png differ diff --git a/images/about/rl_diagram_transparent_bg.png b/images/about/rl_diagram_transparent_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b12b211d00949ac2d31a1f4ff63f171d1b5363 Binary files /dev/null and b/images/about/rl_diagram_transparent_bg.png differ diff --git a/images/agents_thumbnails/bipedal_thumbnail.png b/images/agents_thumbnails/bipedal_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..cbd703ef8c4cbe26abaad346afc606c43666a8ad Binary files /dev/null and b/images/agents_thumbnails/bipedal_thumbnail.png differ diff --git a/images/agents_thumbnails/chimpanzee_thumbnail.png b/images/agents_thumbnails/chimpanzee_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..97a64d211eedac141a1083c15251e0172ac4867f Binary files /dev/null and b/images/agents_thumbnails/chimpanzee_thumbnail.png differ diff --git a/images/agents_thumbnails/fish_thumbnail.png b/images/agents_thumbnails/fish_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..b6fb1c0fb42446d90e3e5230985d46c7cb698499 Binary files /dev/null and b/images/agents_thumbnails/fish_thumbnail.png differ diff --git a/images/agents_thumbnails/spider_thumbnail.png b/images/agents_thumbnails/spider_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..78989574ac03014a44acf3294bf5726f9b0dfcf6 Binary files /dev/null and b/images/agents_thumbnails/spider_thumbnail.png differ diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8df0e3aa19ba6f18daf6ed3dd8e5ac05264069e4 Binary files /dev/null and b/images/favicon.ico differ diff --git a/index.html b/index.html index 918e851d9dd1baf9e4fb4f067fd979d432472161..c4ec1f0c2dbacb1d5dab301bc1e39c17b6c20830 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,612 @@ - - - - My static Space - - - -
-

Welcome to your static Space!

-

- You can modify this app directly by editing index.html in the - Files and versions tab. -

-

- Also don't forget to check the - Spaces documentation. -

-
- + + + + + Interactive Deep Reinforcement Learning Demo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Interactive Deep Reinforcement Learning Demo

+
+
+ +
+
+ +
+ +
+
+ + +
+ + +
+
+ +
+
+ +
+ +
+ + + +
+
+
+ + +
+

List of running agents

+
    +
    +
    + + + + +
    +
    + + + + +
    + + +
    + +

    To begin you can select one of the following environments to load it into the simulation.

    + +
    + +
    + +
    +
    +

    In this section you can store your own custom environments by saving them thanks to the button above or by uploading them from a JSON file.

    + +
    +
    + + + +
    +
    + + +
    + +
    +
    +
    +

    Terrain Generation

    +
    +
    + +
    +
    + +
    + +
    +
    +
    + +
    +

    + Here you can draw your own parkour! +

    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +

    + Select the Ground or Ceiling button to start drawing the corresponding terrain shape with the mouse.
    + Be careful not to draw more than one line at different heights if you want the result to be optimal. + You can use the Erase button if you need to correct your drawing or the Clear one to clear all your drawing.
    + When you are satisfied with the result, just click the Generate Terrain button. +

    +
    +
    + +
    + +
    +

    + You can also use these three sliders to generate the terrain shapes automatically. +

    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + General parameters +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    + + +
    +
    +
    + Creepers +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + + +
    + +
    + +
    +

    Rendering Options

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + + +
    +
    +

    Assets

    +

    Here you can find several types of assets, which are objects that you can add to the simulation using the mouse.

    +
    + + + More assets coming soon... +
    +
    +
    + + +
    +
    + +

    Purpose of the demo

    + +
    +

    + The goal of this demo is to showcase the challenge of generalization to unknown tasks + for Deep Reinforcement Learning (DRL) agents. +

    + +

    + DRL is a machine learning approach for teaching virtual agents + how to solve tasks by combining Reinforcement Learning and Deep Learning methods. + This approach has been used for a diverse set of applications including robotics (e.g. Solving Rubik's Cube), + video games and boardgames (e.g. AlphaGo). +

    + +

    + In this demo, all the agents have been autonomously trained to learn an efficient behaviour to navigate through a 2D environment, + combining different methods so that they can be able to generalize their behaviour to never-seen-before situations. +

    + +

    + The demo provides different tools to customize the environment in order to test and challenge the + robustness of the agents on different situations. +

    +
    + + +

    Reinforcement Learning

    + +
    +

    + Reinforcement Learning (RL) is the study of agents and how they learn by trial and error. + The main idea is to reward or punish an agent according to the actions it takes in order to teach it an efficient behavior to reach an objective. +
    + The RL approaches generally feature an agent which evolves and interacts with a world. + At each interaction step, the agent sees a partial observation of the current state of the environment and decides of an action to take. + Each action taken by the agent changes the state of the world. + The agent also receives a reward signal at each step, that indicates how good or bad the current state is + according to the objective the agent has to reach. +

    + +
    +
    +

    + The diagram on the right presents this interaction process between the agent and the environment, + with the different information they exchange at each step. +
    + Maximizing the reward over steps is a way for the agent to learn a behaviour, also called policy, + to achieve its objective. +

    +
    +
    + RL diagram +
    +
    +
    + +

    Deep RL

    + +
    +

    + In order to remember and improve the actions taken by the agent, DRL algorithms utilizes artificial neural networks. + With training, these neural networks are able to learn to predict an optimal action to take at each step from the observation received, + and relying on all the observations and rewards previously received after each action during training. + Thanks to this, DRL algorithms are able to produce behaviours that are very effective in situations similar to those they were trained on. +

    + +
    + RL demo diagram +
    + +

    + However, in real-world applications, the environment rarely remains still and frequently evolves. Therefore one would + want DRL agents to be able to generalize their behaviour to previously unseen changes of the environment so that + they can adapt to a large range of situations. +

    +
    + +

    Automatic Curriculum Learning

    + +
    +

    + One solution to handle this challenge is to train DRL agents on procedurally generated environments. +
    + Procedural generation is a method of automatically creating environments according to some parameters. + Using this method, DRL agents can be trained on a very wide range of environments, hence allowing them + to generalize their behaviour to more different situations. +

    + +

    + However, randomly generating environments during training implies the risk to generate environments that are too difficult or too easy to resolve + for the agents, preventing them to continuously learn in an efficient way. +
    + Therefore, one would need smarter training strategies that propose relevant environments tailored to the current learning progress of the student (DRL agent). + This method is called Automatic Curriculum Learning (ACL) and is embodied by a teacher algorithm which is trained to learn to generate + the most relevant environments throughout the entire training process according to the student performances. +
    + This way, the teacher proposes easy environments to the student at the beginning and gradually increases the difficulty + and the diversity of the tasks in order to guarantee that the student is progressing while not always facing the same situation or forgetting what it has already learned. +

    +
    + +

    About the demo

    + +
    +

    + In this demo, all the available agents were trained using Soft Actor Critic + as the DRL student algorithm alongside different ACL teacher algorithms such as ALP-GMM. +
    + They successfully learned efficient behaviours to move through the environment and to generalize to never-seen-before situations. +

    + +

    + The physics of the simulation are supported by box2d.js + which is a direct port of the Box2D physics engine to JavaScript. +
    + The pre-trained policies (agents behaviours) are loaded in the browser thanks to TensorFlow.js. +

    +
    + +

    Credits

    + +
    +

    + This demo was designed by Paul Germon as part of an internship within Flowers + research team at Inria. This internship was monitored by Rémy Portelas and Clément Romac, + and supervised by Pierre-Yves Oudeyer. Special thanks to Nikita Melkozerov for its very helpful contribution. + Recommended citation format: +

    +                                    @misc{germon2021demo,  
    +                                      title={Interactive Deep Reinforcement Learning Demo},  
    +                                      author={Germon, Paul and Romac, Clément and Portelas, Rémy and Pierre-Yves, Oudeyer},  
    +                                      url={https://developmentalsystems.org/Interactive_DeepRL_Demo/},  
    +                                      year={2021}
    +                                    }
    +                                    
    +

    + +
      +
    • The code of this demo is open-source and can be found on this github repository.
    • +
    • The code of the environment and agents is adapted from the TeachMyAgent benchmark's Python code to JavaScript.
    • +
    +
    + +

    References

    + +
    +
      +
    • [1] OpenAI, Ilge Akkaya, Marcin Andrychowicz, Maciek Chociej, Mateusz Litwin, Bob McGrew, Arthur Petron, Alex Paino, Matthias Plappert, Glenn Powell, Raphael Ribas, Jonas Schneider, Nikolas Tezak, Jerry Tworek, Peter Welinder, Lilian Weng, Qiming Yuan, Wojciech Zaremba, Lei Zhang: + Solving Rubik's Cube with a Robot Hand (2019). https://arxiv.org/abs/1910.07113
    • +
    • [2] Silver, D., Huang, A., Maddison, C. et al. Mastering the game of Go with deep neural networks and tree search. Nature 529, 484–489 (2016). https://doi.org/10.1038/nature16961
    • +
    • [3] Portelas, R., Colas, C., Weng, L., Hofmann, K., & Oudeyer, P. Y. (2020). Automatic curriculum learning for deep rl: A short survey (2020). https://arxiv.org/abs/2003.04664
    • +
    • [4] Haarnoja, T., Zhou, A., Abbeel, P., & Levine, S. (2018, July). Soft actor-critic: Off-policy maximum entropy deep reinforcement learning with a stochastic actor. In International conference on machine learning (pp. 1861-1870). PMLR https://arxiv.org/abs/1801.01290
    • +
    • [5] Portelas, R., Colas, C., Hofmann, K., & Oudeyer, P. Y. (2020, May). Teacher algorithms for curriculum learning of deep rl in continuously parameterized environments. In Conference on Robot Learning (pp. 835-853). PMLR. https://arxiv.org/abs/1910.07224
    • +
    • [6] Romac, C., Portelas, R., Hofmann, K., & Oudeyer, P. Y. (2021). TeachMyAgent: a Benchmark for Automatic Curriculum Learning in Deep RL. https://arxiv.org/abs/2103.09815
    • +
    +
    +
    +
    +
    +
    + +
    + +

    Add an agent

    +

    Here you can add an agent to the simulation with the morphology of your choice.

    +
      +
      +
      +
      + + + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000000000000000000000000000000000000..109fd3133051b93143a26da59a5d3664c586128a --- /dev/null +++ b/index.js @@ -0,0 +1,661 @@ +/* GLOBAL VARIABLES */ + +window.erasing_radius = 15; +window.asset_size = 8; + +// Lists of points {x, y} composing the terrain shapes +window.ground = []; +window.ceiling = []; + +// Lists of raw points {x, y} drawn by the user for the terrain shapes +window.terrain = { + ground: [], + ceiling: [] +}; + +// Parameters to handle the alignment of the terrain to the startpad according to the situation +window.align_terrain = { + align: true, + ceiling_offset: null, + ground_offset: null, + smoothing: null +}; + +/* INIT FUNCTIONS */ + +/** + * Initializes the game. + * @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN + * @param water_level {number} + * @param creepers_width {number} + * @param creepers_height {number} + * @param creepers_spacing {number} + * @param smoothing {number} + * @param creepers_type {boolean} + * @param ground {Array} - List of points {x, y} composing the ground + * @param ceiling {Array} - List of points {x, y} composing the ceiling + * @param align {Object} + * @param zoom {number} - Zoom to apply to the environment + * @param scroll {{x: number, y:number}} - Scroll to apply to the environment + */ +function init_game(cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, + smoothing, creepers_type, ground, ceiling, align, zoom=null, scroll=null) { + + let agents = { + morphologies: [], + policies: [], + positions: [] + } + + // Pauses the game if it already exists and gets the information about the running agents + if(window.game != null){ + window.game.pause(); + agents.morphologies = [...window.game.env.agents.map(a => a.morphology)]; + agents.policies = [...window.game.env.agents.map(a => a.policy)]; + agents.positions = [...window.game.env.agents.map(agent => agent.agent_body.reference_head_object.GetPosition())]; + } + window.game = new Game(agents, cppn_input_vector, water_level, creepers_width, creepers_height, + creepers_spacing, smoothing, creepers_type, ground, ceiling, align); + window.set_agent_selected(-1); + window.asset_selected = null; + + if(zoom == null){ + window.game.env.set_zoom(INIT_ZOOM); + } + else { + window.game.env.set_zoom(zoom); + } + + if(scroll == null){ + window.game.env.set_scroll(window.agent_selected, INIT_SCROLL_X, 0); + } + else{ + window.game.env.set_scroll(window.agent_selected, scroll[0], scroll[1]); + } + window.game.env.render(); +} + +/** + * Indicates if the creepers type is 'Swingable' or not. + * @returns {boolean} + */ +function getCreepersType() { + return document.getElementById("creepersType").value == 'Swingable'; +} + +/** + * First function called after the code is entirely loaded. + * Loads the model of the CPPN, initializes the game by default, loads the default environmnent and starts the language selection. + * @returns {Promise} + */ +async function onLoadInit() { + window.cppn_model = await tf.loadGraphModel('./js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/model.json'); + window.init_default(); + window.loadDefaultEnv(); + window.langIntroSetUp(); +} + +// Calls onLoadInit() when all the files are loaded +window.addEventListener("load", onLoadInit, false); + +/* IN-CANVAS MOUSE INTERACTIONS */ + +/** + * Converts the given position relative to the canvas to the environment scale. + * @param x_pos {number} - X-coordinate inside the canvas. + * @param y_pos {number} - Y-coordinate inside the canvas. + * @returns {{x: number, y: number}} - Position inside the environment. + */ +function convertPosCanvasToEnv(x_pos, y_pos){ + let x = Math.max(-window.canvas.width * 0.01, Math.min(x_pos, window.canvas.width * 1.01)); + let y = Math.max(0, Math.min(y_pos, window.canvas.height)); + + x += window.game.env.scroll[0]; + y = -(y - window.game.env.scroll[1]); + + x = x / (window.game.env.scale * window.game.env.zoom); + y = y / (window.game.env.scale * window.game.env.zoom); + + y += (1 - window.game.env.scale * window.game.env.zoom) * RENDERING_VIEWER_H/(window.game.env.scale * window.game.env.zoom) + + (window.game.env.zoom - 1) * (window.game.env.ceiling_offset)/window.game.env.zoom * 1/3 + RENDERING_VIEWER_H; + + return {x: x, y: y}; +} + +/** + * Converts the given position relative to the environment to the canvas scale. + * @param x_pos {number} - X-coordinate inside the environment. + * @param y_pos {number} - Y-coordinate inside the environment. + * @returns {{x: number, y: number}} - Position inside the canvas. + */ +function convertPosEnvToCanvas(x_pos, y_pos){ + let x = x_pos * window.game.env.scale * window.game.env.zoom - window.game.env.scroll[0]; + let y = window.game.env.scroll[1] - (y_pos - RENDERING_VIEWER_H) * window.game.env.scale * window.game.env.zoom + + (1 - window.game.env.scale * window.game.env.zoom) * RENDERING_VIEWER_H + + (window.game.env.zoom - 1) * window.game.env.ceiling_offset * window.game.env.scale * 1/3; + + return {x: x, y: y}; +} + +/** + * Checks if the given position is inside the given body. + * Used for clicking on assets. + * @param pos {{x: number, y: number}} + * @param body {b2Body} - A Box2D body + * @returns {boolean} + */ +function isPosInsideBody(pos, body){ + let shape = body.GetFixtureList().GetShape(); + + if(shape.m_type == b2.Shape.e_circle){ + let center = body.GetWorldCenter(); + return Math.pow(center.x - pos.x, 2) + Math.pow(center.y - pos.y, 2) <= Math.pow(shape.m_radius, 2); + } +} + +/** + * Handles actions when mouse is pressed. + */ +function mousePressed(){ + + // Hides all the tooltips when mouse pressed + document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + let tooltip = bootstrap.Tooltip.getInstance(el); + tooltip.hide(); + }); + + // Case mouse is pressed inside the canvas + if(mouseX >= 0 && mouseX <= window.canvas.width + && mouseY >= 0 && mouseY <= window.canvas.height){ + + // Stores the current position of the mouse, used when dragging + window.prevMouseX = mouseX; + window.prevMouseY = mouseY; + + // Creates a circle asset at the mouse position and render the environment + if(window.is_drawing_circle()){ + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + window.game.env.create_circle_asset(mousePos, window.asset_size * 2 / window.game.env.scale); + + if(window.agent_selected != null){ + window.agent_selected.is_selected = false; + window.set_agent_selected(-1); + } + window.game.env.render(); + } + + // Handles agents and assets selection + else if(!window.is_drawing()){ + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + + // Selects an agent in the canvas if the mouse is clicked over its body + let one_agent_touched = false; + for(let i = 0; i < window.game.env.agents.length; i++){ + let agent = window.game.env.agents[i]; + + // Checks if the agent is touched by the mouse + let is_agent_touched = agent.agent_body.isPosInside(mousePos); + + // If the agent is touched and not selected yet, it is now selected and all other agents are deselected + if(is_agent_touched){ + one_agent_touched = true; + + if(!agent.is_selected) { + agent.is_selected = true; + window.set_agent_selected(i); + for (let other_agent of window.game.env.agents) { + if (other_agent != agent) { + other_agent.is_selected = false; + } + } + } + break; + } + // If the agent is not touched it is deselected + else { + agent.is_selected = false; + } + } + + // If no agent is touched, the selected agent is set to null + if(!one_agent_touched && window.agent_selected != null){ + window.set_agent_selected(-1); + } + + // Selects an asset in the canvas if the mouse is clicked over its body and no agent has been touched + if(!one_agent_touched){ + let one_asset_touched = false; + for(let asset of window.game.env.assets_bodies){ + + // Checks if the asset is touched by the mouse + let is_asset_touched = isPosInsideBody(mousePos, asset.body); + + // If the asset is touched and not selected yet, it is now selected and all other assets are deselected + if(is_asset_touched){ + one_asset_touched = true; + + if(!asset.is_selected){ + asset.is_selected = true; + window.asset_selected = asset; + for(let other_asset of window.game.env.assets_bodies){ + if(other_asset != asset){ + other_asset.is_selected = false; + } + } + break; + } + } + // If the asset is not touched it is deselected + else if(!is_asset_touched){ + asset.is_selected = false; + } + } + + // If no asset is touched, the selected asset is set to null + if(!one_asset_touched && window.asset_selected != null){ + window.asset_selected = null; + } + } + + window.game.env.render(); + } + } +} + +// Handles clicks outside canvas when drawing (deselect drawing buttons) +document.addEventListener('mousedown', (event) => { + if(window.is_drawing() || window.is_drawing_circle()){ + let canvas_id = "#" + window.canvas.canvas.id; + + // Elements that can be clicked without deselecting drawing buttons: canvas + ground, ceiling, erase buttons + let authorized_elements = [ + document.querySelector(canvas_id), + document.querySelector('#drawGroundButton'), + document.querySelector('#drawCeilingButton'), + document.querySelector('#eraseButton') + ]; + + // If + if(authorized_elements.indexOf(event.target) == -1) { + window.deselectDrawingButtons(); + } + } +}); + +/** + * Handles actions when mouse is dragged. + * @returns {boolean} + */ +function mouseDragged(){ + + // Case mouse is dragged inside the canvas + if(mouseX >= 0 && mouseX <= window.canvas.width + && mouseY >= 0 && mouseY <= window.canvas.height) { + + // DRAWING + if(window.is_drawing()) { + + // Gets the position of the mouse in the environment scale + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + + // Vertical offset to shift the drawing, trace and forbidden canvas in order to align them to the environment + let y_offset = SCROLL_Y_MAX - window.game.env.scroll[1]; + + // Drawing ground to the right of the terrain startpad + if(window.is_drawing_ground() && mousePos.x > (INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP){ + drawing_canvas.push(); + drawing_canvas.stroke("#66994D"); + drawing_canvas.strokeWeight(4); + // Draws a ground line between the current and previous positions of the mouse + drawing_canvas.line(mouseX, mouseY + y_offset, window.prevMouseX, window.prevMouseY + y_offset); + drawing_canvas.pop(); + window.terrain.ground.push(mousePos); + } + + // Drawing ceiling to the right of the terrain startpad + else if(window.is_drawing_ceiling() && mousePos.x > (INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP){ + drawing_canvas.push(); + drawing_canvas.stroke("#808080"); + drawing_canvas.strokeWeight(4); + // Draws a ceiling line between the current and previous positions of the mouse + drawing_canvas.line(mouseX, mouseY + y_offset, window.prevMouseX, window.prevMouseY + y_offset); + drawing_canvas.pop(); + window.terrain.ceiling.push(mousePos); + } + + // Erasing to the right of the terrain startpad + else if(window.is_erasing() && mousePos.x > INITIAL_TERRAIN_STARTPAD * TERRAIN_STEP){ + + // Draws a circle trace at the mouse position to show the erasing radius + trace_canvas.clear(); + trace_canvas.noStroke(); + trace_canvas.fill(255); + trace_canvas.circle(mouseX, mouseY + y_offset, window.erasing_radius * 2); + + // Removes the points that are within the circle's radius from the ground and ceiling lists + window.terrain.ground = window.terrain.ground.filter(function(point, index, array){ + return Math.pow(point.x - mousePos.x, 2) + Math.pow(point.y - mousePos.y, 2) > Math.pow(window.erasing_radius / (window.game.env.scale * window.game.env.zoom), 2); + }); + window.terrain.ceiling = window.terrain.ceiling.filter(function(point, index, array){ + return Math.pow(point.x - mousePos.x, 2) + Math.pow(point.y - mousePos.y, 2) > Math.pow(window.erasing_radius / (window.game.env.scale * window.game.env.zoom), 2); + }); + + // Erases the drawing canvas inside the circle's radius + drawing_canvas.erase(); + drawing_canvas.circle(mouseX, mouseY + y_offset, window.erasing_radius * 2); + drawing_canvas.noErase(); + } + + // Dragging to scroll + else{ + cursor(MOVE); + window.game.env.set_scroll(null, window.game.env.scroll[0] + window.prevMouseX - mouseX, window.game.env.scroll[1] + mouseY - prevMouseY); + + // Re-draws the terrain shapes according to the new scroll + window.refresh_drawing(); + y_offset = SCROLL_Y_MAX - window.game.env.scroll[1]; + } + + // Renders the environment and displays the off-screen canvas on top of it + window.game.env.render(); + image(drawing_canvas, 0, -y_offset); + image(trace_canvas, 0, -y_offset); + image(forbidden_canvas, 0, -y_offset); + } + + // DRAGGING + else{ + cursor(MOVE); + + // Dragging an agent + for (let agent of window.game.env.agents) { + + // Drags the selected agent + if (agent.is_selected) { + + // Computes the terrain's length according to the agent's morphology + let terrain_length; + if (agent.agent_body.body_type == BodyTypesEnum.CLIMBER) { + terrain_length = window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x; + } + else if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { + terrain_length = window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x; + } + else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, + window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); + } + + // Gets the mouse position inside the environment and clamps it horizontally to the edges of the terrain + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + let x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; + + // Sets the position of the agent to the mouse position + window.game.env.set_agent_position(agent, x, mousePos.y); + window.game.env.render(); + window.is_dragging_agent = true; + break; + } + } + + // Dragging an asset + for(let asset of window.game.env.assets_bodies){ + + // Drags the selected asset + if (asset.is_selected && !window.is_dragging_agent) { + let terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, + window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); + + // Gets the mouse position inside the environment and clamps it horizontally to the edges of the terrain + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + mousePos.x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; + + // Sets the position of the asset to the mouse position + window.game.env.set_asset_position(asset, mousePos); + window.game.env.render(); + window.is_dragging_asset = true; + } + } + + // Dragging to scroll + if(!window.is_dragging_agent && !window.is_dragging_asset){ + + // Scrolling manually cancels agent following + if(window.agent_followed != null){ + window.set_agent_followed(-1); + } + window.game.env.set_scroll(null, window.game.env.scroll[0] + window.prevMouseX - mouseX, window.game.env.scroll[1] + mouseY - prevMouseY); + window.game.env.render(); + } + } + } + + // Dragging an agent horizontally out of canvas + else if(window.is_dragging_agent + && mouseY >= 0 && mouseY < window.canvas.height){ + + if(mouseX < 0){ + window.dragging_side = "left"; + } + else if(mouseX > window.canvas.width){ + window.dragging_side = "right"; + } + + cursor(MOVE); + + // Dragging an agent + for (let agent of window.game.env.agents) { + + // Drags the selected agent + if (agent.is_selected) { + + // Scrolls horizontally according to the dragging side to follow the agent + window.game.env.set_scroll(null); + + // Computes the terrain's length according to the agent's morphology + let terrain_length; + if (agent.agent_body.body_type == BodyTypesEnum.CLIMBER) { + terrain_length = window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x; + } + else if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { + terrain_length = window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x; + } + else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, + window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); + } + + // Gets the mouse position inside the environment and clamps it horizontally to the edges of the terrain + let mousePos = convertPosCanvasToEnv(mouseX, mouseY); + let x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; + + // Sets the position of the agent to the mouse position + window.game.env.set_agent_position(agent, x, mousePos.y); + window.game.env.render(); + break; + } + } + + // Prevents default behaviour when dragging the mouse + return false; + } + + window.prevMouseX = mouseX; + window.prevMouseY = mouseY; +} + +/** + * Handles actions when mouse is released. + */ +function mouseReleased(){ + cursor(); + window.is_dragging_agent = false; + window.is_dragging_asset = false; + window.dragging_side = null; +} + +/** + * Handles actions when mouse is moved. + */ +function mouseMoved(){ + + // Draws the trace of the circle asset at the mouse position + if(window.is_drawing_circle()){ + trace_canvas.clear(); + if(mouseX >= 0 && mouseX <= window.canvas.width + && mouseY >= 0 && mouseY <= window.canvas.height) { + trace_canvas.noStroke(); + trace_canvas.fill(136, 92, 0, 180); + trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.asset_size * 4 * window.game.env.zoom); + } + window.game.env.render(); + image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + + // Draws the trace of the eraser at the mouse position + else if (window.is_erasing()) { + trace_canvas.clear(); + if (mouseX >= 0 && mouseX <= window.canvas.width + && mouseY >= 0 && mouseY <= window.canvas.height) { + trace_canvas.noStroke(); + trace_canvas.fill(255, 180); + trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.erasing_radius * 2); + } + window.game.env.render(); + image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } +} + +/** + * Handles actions when a mouse wheel event is detected (actual mouse wheel or touchpad). + * @param event {WheelEvent} + * @returns {boolean} + */ +function mouseWheel(event){ + if(mouseX >= 0 && mouseX <= window.canvas.width + && mouseY >= 0 && mouseY <= window.canvas.height) { + + trace_canvas.clear(); + + // Resizes circle asset radius + if(window.is_drawing_circle()){ + window.asset_size = Math.max(3, Math.min(window.asset_size - event.delta / 100, 30)); + trace_canvas.noStroke(); + trace_canvas.fill(136, 92, 0, 180); + trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.asset_size * 4 * window.game.env.zoom); + window.game.env.render(); + image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + + // Resizes erasing radius + else if(window.is_erasing()){ + window.erasing_radius = Math.max(5, Math.min(window.erasing_radius - event.delta / 100, 30)); + trace_canvas.noStroke(); + trace_canvas.fill(255, 180); + trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.erasing_radius * 2); + window.game.env.render(); + image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + + // Zooms in or out + else { + window.game.env.set_zoom(window.game.env.zoom - event.delta / 2000); + // TODO: scroll on the mouse position + window.game.env.set_scroll(null, window.game.env.scroll[0], window.game.env.scroll[1]); + + // If drawing mode, re-draws the terrain shapes according to the new zoom + if(window.is_drawing()){ + window.refresh_drawing(); + window.game.env.render(); + image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + else{ + window.game.env.render(); + } + + } + + // Prevents default behaviour for mouse wheel events inside the canvas + return false; + } +} + +/** + * Handles actions when a key is pressed. + * @returns {boolean} + */ +function keyPressed(){ + // Deletes the agent or asset selected when pressing the delete key + if(keyCode == DELETE){ + if(window.agent_selected != null){ + window.delete_agent(agent_selected); + window.agent_selected(null); + return false; + } + else if(window.asset_selected != null){ + window.game.env.delete_asset(window.asset_selected); + window.asset_selected = null; + window.game.env.render(); + return false; + } + } +} + +/** + * Handles actions when the window is resized. + */ +function windowResized(){ + + let canvas_container = document.querySelector('#canvas_container'); + + // Recomputes RENDERING_VIEWER_W, INIT_ZOOM and THUMBNAIL_ZOOM + RENDERING_VIEWER_W = canvas_container.offsetWidth; + INIT_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 1.05 * TERRAIN_STEP * SCALE); + THUMBNAIL_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 0.99 * TERRAIN_STEP * SCALE); + + // Resizes the main canvas + resizeCanvas(RENDERING_VIEWER_W, RENDERING_VIEWER_H); + drawing_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + trace_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + forbidden_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + + // Generates the terrain from the drawing + if(is_drawing()){ + window.refresh_drawing(); + window.game.env.render(); + image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + // Re-initializes the environment + else{ + window.init_default(); + } +} + +window.downloadObjectAsJson = (exportObj, exportName) => { + let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); + let downloadAnchorNode = document.createElement('a'); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", exportName + ".json"); + document.body.appendChild(downloadAnchorNode); // required for firefox + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +} + +window.strUcFirst = (a) => { + return (a+'').charAt(0).toUpperCase()+a.substr(1); +} + +window.draw_forbidden_area = () => { + forbidden_canvas.clear(); + forbidden_canvas.stroke("#FF0000"); + forbidden_canvas.strokeWeight(3); + forbidden_canvas.fill(255, 50, 0, 75); + let w = convertPosEnvToCanvas((INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP, 0).x; + forbidden_canvas.rect(0, 0, w, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); +} diff --git a/js/Box2D_dynamics/climbing_dynamics.js b/js/Box2D_dynamics/climbing_dynamics.js new file mode 100644 index 0000000000000000000000000000000000000000..66c14f8ce29f43bb668d0415b81da888dfe6a30f --- /dev/null +++ b/js/Box2D_dynamics/climbing_dynamics.js @@ -0,0 +1,175 @@ +/** + * @classdesc Class that handles the climbing dynamics. + */ +class ClimbingDynamics { + constructor(){}; + + /** + * Prepares the agent's sensors to grasp or release according to the actions. + * @param actions {Array} - Actions of the agent + * @param agent_body {Object} - Climber morphology + * @param world - {Object} - Box2D world + */ + before_step_climbing_dynamics(actions, agent_body, world){ + for(let i = 0; i < agent_body.sensors.length; i++){ + let action_to_check = actions[actions.length - i - 1]; + let sensor_to_check = agent_body.sensors[agent_body.sensors.length - i - 1]; + if(action_to_check > 0){ // Check whether the sensor should grasp or release + sensor_to_check.GetUserData().ready_to_attach = true; + } + else { + sensor_to_check.GetUserData().ready_to_attach = false; + if(sensor_to_check.GetUserData().has_joint){ // if released and it had a joint => destroys it + sensor_to_check.GetUserData().has_joint = false; + + // Gets a list of all the joints of the sensor body + let sensor_joints = []; + let _joint = sensor_to_check.GetJointList(); + while(_joint != null){ + sensor_joints.push(_joint.joint); + _joint = _joint.next; + } + // Finds the index of the first revolute joint + const isRevolute = (s) => s.m_type == b2.Joint.e_revoluteJoint; + let idx_to_destroy = sensor_joints.findIndex(isRevolute); + if(idx_to_destroy != -1){ + world.DestroyJoint(sensor_joints[idx_to_destroy]); + } + } + } + } + } + + /** + * Creates joints between sensors ready to grasp if collision with graspable area was detected + * @param contact_detector {Object} + * @param world {Object} - Box2D world + */ + after_step_climbing_dynamics(contact_detector, world){ + // Adds climbing joints if needed + for(let i = 0; i < contact_detector.contact_dictionaries.sensors.length; i++){ + let sensor = contact_detector.contact_dictionaries.sensors[i]; + if(contact_detector.contact_dictionaries.bodies[i].length > 0 + && sensor.GetUserData().ready_to_attach + && !sensor.GetUserData().has_joint){ + let other_bodies = [...contact_detector.contact_dictionaries.bodies[i]]; + for(let other_body of other_bodies){ + + // Checks if still overlapping after solver + // Super coarse yet fast way, mainly useful for creepers + let other_body_shape = other_body.GetFixtureList().GetShape(); + let x_values = []; + let y_values = []; + if(other_body_shape.m_type == b2.Shape.e_polygon){ + for(let i = 0; i < other_body_shape.m_count; i++) { + x_values.push(other_body.GetWorldPoint(other_body_shape.m_vertices[i]).x); + y_values.push(other_body.GetWorldPoint(other_body_shape.m_vertices[i]).y); + } + } + else if(other_body_shape.m_type == b2.Shape.e_edge){ + x_values = [other_body_shape.m_vertex1.x, other_body_shape.m_vertex2.x]; + y_values = [other_body_shape.m_vertex1.y, other_body_shape.m_vertex2.y]; + } + + let radius = sensor.GetFixtureList().GetShape().m_radius + 0.01; + let sensor_world_center = sensor.GetWorldCenter(); + + if(sensor_world_center.x + radius > Math.min(...x_values) + && sensor_world_center.x - radius < Math.max(...x_values) + && sensor_world_center.y + radius > Math.min(...y_values) + && sensor_world_center.y - radius < Math.max(...y_values)){ + + let rjd = new b2.RevoluteJointDef(); + rjd.Initialize(sensor, other_body, sensor_world_center); + let joint = world.CreateJoint(rjd); + joint.SetUserData(new CustomBodyUserData(false, false, "grip")); + joint.GetBodyA().GetUserData().joint = joint; + sensor.GetUserData().has_joint = true; + break; + } + else { + // Removes other_body from the list of bodies in contact with the sensor + let sensor_idx = contact_detector.contact_dictionaries.sensors.indexOf(sensor); + if(sensor_idx != -1){ + let other_idx = contact_detector.contact_dictionaries.bodies[sensor_idx].indexOf(other_body); + contact_detector.contact_dictionaries.bodies[sensor_idx].splice(other_idx, 1); + + if(contact_detector.contact_dictionaries.bodies[sensor_idx].length == 0){ + sensor.GetUserData().has_contact = false; + } + } + } + } + } + } + } +} + +/** + * @classdesc Stores contacts between sensors and graspable surfaces in a dictionaries associated to the sensor. + * @constructor + */ +function ClimbingContactDetector() { + b2.ContactListener.call(this); + this.contact_dictionaries = { + sensors: [], + bodies: [] + }; +} + +ClimbingContactDetector.prototype = Object.create(b2.ContactListener.prototype); +ClimbingContactDetector.prototype.constructor = ClimbingContactDetector; +ClimbingContactDetector.prototype.BeginContact = function (contact) { + let bodies = [contact.GetFixtureA().GetBody(), contact.GetFixtureB().GetBody()]; + for(let i = 0; i < bodies.length; i++){ + let body = bodies[i]; + if(body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_SENSOR + && body.GetUserData().check_contact){ + let other_body = bodies[(i + 1) % 2]; + if(other_body.GetUserData().object_type == CustomUserDataObjectTypes.GRIP_TERRAIN + || other_body.GetUserData().object_type == CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN){ + body.GetUserData().has_contact = true; + let idx = this.contact_dictionaries.sensors.indexOf(body); + if(idx != -1){ + this.contact_dictionaries.bodies[idx].push(other_body); + } + else{ + this.contact_dictionaries.sensors.push(body); + this.contact_dictionaries.bodies.push([other_body]); + } + } + else{ + return; + } + } + } +}; + +ClimbingContactDetector.prototype.EndContact = function (contact){ + let bodies = [contact.GetFixtureA().GetBody(), contact.GetFixtureB().GetBody()]; + for(let i = 0; i < bodies.length; i++) { + let body = bodies[i]; + let other_body = bodies[(i + 1) % 2]; + if(body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_SENSOR && + body.GetUserData().check_contact && body.GetUserData().has_contact){ + let body_idx = this.contact_dictionaries.sensors.indexOf(body); + if (body_idx != -1) { + let other_idx = this.contact_dictionaries.bodies[body_idx].indexOf(other_body); + if(other_idx != -1){ + this.contact_dictionaries.bodies[body_idx].splice(other_idx, 1); + } + + if(this.contact_dictionaries.bodies[body_idx].length == 0){ + body.GetUserData().has_contact = false; + } + } + + } + } +}; + +ClimbingContactDetector.prototype.Reset = function(){ + this.contact_dictionaries = { + body: [] + }; +}; \ No newline at end of file diff --git a/js/Box2D_dynamics/contact_detector.js b/js/Box2D_dynamics/contact_detector.js new file mode 100644 index 0000000000000000000000000000000000000000..17fc2b982fbe3e8381fcb2019d0521d861c29c41 --- /dev/null +++ b/js/Box2D_dynamics/contact_detector.js @@ -0,0 +1,88 @@ +/** + * @classdesc Class that derives from b2.ContactListener and that handles both water and climbing collisions. + * @param env {Object} + * @constructor + */ +function ContactDetector (env){ + b2.ContactListener.call(this); + this.water_contact_detector = new WaterContactDetector(); + this.climbing_contact_detector = new ClimbingContactDetector(); + this.env = env; +} + +ContactDetector.prototype = Object.create(b2.ContactListener.prototype); +ContactDetector.prototype.constructor = ContactDetector; +ContactDetector.prototype.BeginContact = function (contact){ + let bodies = [contact.GetFixtureA().GetBody(), contact.GetFixtureB().GetBody()]; + const anyWater = (body) => body.GetUserData().object_type == CustomUserDataObjectTypes.WATER; + const anySensor = (body) => body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_SENSOR; + if(bodies.some(anyWater)){ + this.water_contact_detector.BeginContact(contact); + } + else if(bodies.some(anySensor)){ + this.climbing_contact_detector.BeginContact(contact); + } + else{ + if(contact.GetFixtureA().IsSensor() || contact.GetFixtureB().IsSensor()){ + return; + } + + for(let i = 0; i < bodies.length; i++){ + let body = bodies[i]; + if(body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT && body.GetUserData().check_contact){ + body.GetUserData().has_contact = true; + } + } + } +}; + +ContactDetector.prototype.EndContact = function (contact){ + let bodies = [contact.GetFixtureA().GetBody(), contact.GetFixtureB().GetBody()]; + const anyWater = (body) => body.GetUserData().object_type == CustomUserDataObjectTypes.WATER; + const anySensor = (body) => body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_SENSOR; + if(bodies.some(anyWater)){ + this.water_contact_detector.EndContact(contact); + } + else if(bodies.some(anySensor)){ + this.climbing_contact_detector.EndContact(contact); + } + else { + for(let body of bodies){ + if(body.GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT && body.GetUserData().check_contact){ + body.GetUserData().has_contact = false; + } + } + } +}; + +ContactDetector.prototype.Reset = function (){ + this.water_contact_detector.Reset(); + this.climbing_contact_detector.Reset(); +} + +/** + * @classdesc Class that derives from b2.RayCastCallback and that handles lidars raycasts. + * @param agent_mask_filter + * @constructor + */ +function LidarCallback(agent_mask_filter){ + b2.RayCastCallback.call(this); + this.agent_mask_filter = agent_mask_filter; + this.fixture = null; + this.is_water_detected = false; + this.is_creeper_detected = false; +}; + +LidarCallback.prototype = Object.create(b2.RayCastCallback.prototype); +LidarCallback.prototype.constructor = LidarCallback; +LidarCallback.prototype.ReportFixture = function (fixture, point, normal, fraction){ + if((fixture.GetFilterData().categoryBits & this.agent_mask_filter) == 0){ + return -1; + } + + this.p2 = point; + this.fraction = fraction; + this.is_water_detected = fixture.GetBody().GetUserData().object_type == CustomUserDataObjectTypes.WATER; + this.is_creeper_detected = fixture.GetBody().GetUserData().object_type == CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN; + return fraction; +} diff --git a/js/Box2D_dynamics/water_dynamics.js b/js/Box2D_dynamics/water_dynamics.js new file mode 100644 index 0000000000000000000000000000000000000000..09662a9f3cd939093bc115908f982db40fd65005 --- /dev/null +++ b/js/Box2D_dynamics/water_dynamics.js @@ -0,0 +1,244 @@ +/** + * @classdesc Class that handles the water dynamics. + */ +class WaterDynamics { + constructor(gravity, drag_mod=0.25, lift_mod=0.25, push_mod=0.05, + max_drag=2000, max_lift=500, max_push=13){ + this.gravity = gravity; + this.drag_mod = drag_mod; + this.lift_mod = lift_mod; + this.max_drag = max_drag; + this.max_lift = max_lift; + this.push_mod = push_mod; + this.max_push = max_push; + } + + compute_centroids(vectors){ + let count = vectors.length; + console.assert(count >= 3); + + let c = new b2.Vec2(0, 0); + let area = 0; + let ref_point = new b2.Vec2(0, 0); + let inv3 = 1/3; + + for(let i = 0; i < count; i++){ + // Triangle vertices + let p1 = ref_point; + let p2 = vectors[i]; + let p3 = i + 1 < count ? vectors[i + 1] : vectors[0]; + + let e1 = b2.Vec2.Subtract(p2, p1); + let e2 = b2.Vec2.Subtract(p3, p1); + let d = b2.Cross_v2_v2(e1, e2); + let triangle_area = 0.5 * d; + area += triangle_area; + + // Area weighted centroid + c.Add(b2.Vec2.Multiply(triangle_area * inv3, b2.Vec2.Add(p1, b2.Vec2.Add(p2, p3)))); + } + + if(area > b2.epsilon){ + c.Multiply(1/area); + } + else{ + area = 0; + } + + return [c, area]; + } + + inside(cp1, cp2, p){ + return (cp2.x - cp1.x) * (p.y - cp1.y) > (cp2.y - cp1.y) * (p.x - cp1.x); + } + + intersection(cp1, cp2, s, e){ + let dc = new b2.Vec2(cp1.x - cp2.x, cp1.y - cp2.y); + let dp = new b2.Vec2(s.x - e.x, s.y - e.y); + let n1 = cp1.x * cp2.y - cp1.y * cp2.x; + let n2 = s.x * e.y - s.y * e.x; + let n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x); + return new b2.Vec2((n1 * dp.x - n2 * dc.x) * n3, (n1 * dp.y - n2 * dc.y) * n3); + } + + find_intersection(fixture_A, fixture_B){ + // TODO : assert polygons + let output_vertices = []; + let polygon_A = fixture_A.GetShape(); + let polygon_B = fixture_B.GetShape(); + + // fill 'subject polygon' from fixture_A polygon + for(let i = 0; i < polygon_A.m_count; i++){ + output_vertices.push(fixture_A.GetBody().GetWorldPoint(polygon_A.m_vertices[i])); + } + + // fill 'clip polygon' from fixture_B polygon + let clip_polygon = []; + for(let i = 0; i < polygon_B.m_count; i++){ + clip_polygon.push(fixture_B.GetBody().GetWorldPoint(polygon_B.m_vertices[i])); + } + + let cp1 = clip_polygon[clip_polygon.length - 1]; + for(let j = 0; j < clip_polygon.length; j++){ + let cp2 = clip_polygon[j]; + if(output_vertices.length == 0){ + break; + } + let input_list = output_vertices.slice(); + output_vertices = []; + + let s = input_list[input_list.length - 1]; + for(let i = 0; i < input_list.length; i++){ + let e = input_list[i]; + if(this.inside(cp1, cp2, e)){ + if(!this.inside(cp1, cp2, s)){ + output_vertices.push(this.intersection(cp1, cp2, s, e)); + } + output_vertices.push(e); + } + else if(this.inside(cp1, cp2, s)){ + output_vertices.push(this.intersection(cp1, cp2, s, e)); + } + s = e; + } + cp1 = cp2 + } + return [(output_vertices.length != 0), output_vertices]; + } + + calculate_forces(fixture_pairs){ + for(let pair of fixture_pairs){ + let density = pair[0].GetDensity(); + let [has_intersection, intersection_points] = this.find_intersection(pair[0], pair[1]); + if(has_intersection){ + let [centroid, area] = this.compute_centroids(intersection_points); + + // apply buoyancy force + let displaced_mass = pair[0].GetDensity() * area; + let buoyancy_force = b2.Vec2.Multiply(displaced_mass, b2.Vec2.Negate(this.gravity)); + pair[1].GetBody().ApplyForce(buoyancy_force, centroid, true); + + // apply complex drag + for(let i = 0; i < intersection_points.length; i++) { + let v0 = intersection_points[i]; + let v1 = intersection_points[(i + 1) % intersection_points.length]; + let mid_point = b2.Vec2.Multiply(0.5, b2.Vec2.Add(v0, v1)); + + // DRAG + // find relative velocity between object and fluid at edge midpoint + let vel_dir = b2.Vec2.Subtract(pair[1].GetBody().GetLinearVelocityFromWorldPoint(mid_point), + pair[0].GetBody().GetLinearVelocityFromWorldPoint(mid_point)); + let vel = vel_dir.Normalize(); + + let edge = b2.Vec2.Subtract(v1, v0); + let edge_length = edge.Normalize(); + let normal = b2.Cross_f_v2(-1, edge); + let drag_dot = b2.Dot_v2_v2(normal, vel_dir); + if(drag_dot >= 0){ // normal points backwards - this is not a leading edge + // apply drag + let drag_mag = drag_dot * this.drag_mod * edge_length * density * vel * vel; + drag_mag = Math.min(drag_mag, this.max_drag); + let drag_force = b2.Vec2.Multiply(drag_mag, b2.Vec2.Negate(vel_dir)); + pair[1].GetBody().ApplyForce(drag_force, mid_point, true); + + // apply lift + let lift_dot = b2.Dot_v2_v2(edge, vel_dir); + let lift_mag = drag_dot * lift_dot * this.lift_mod * edge_length * density * vel * vel; + lift_mag = Math.min(lift_mag, this.max_lift); + let lift_dir = b2.Cross_f_v2(1, vel_dir); + let lift_force = b2.Vec2.Multiply(lift_mag, lift_dir); + pair[1].GetBody().ApplyForce(lift_force, mid_point, true); + } + + // PUSH + let body_to_check = pair[1].GetBody(); + // Simplification /!\ + let joints_to_check = []; + let joint_edge = body_to_check.GetJointList(); + while(joint_edge != null){ + if(joint_edge.joint.GetBodyB() == body_to_check){ + joints_to_check.push(joint_edge.joint); + } + joint_edge = joint_edge.next; + } + + for(let joint of joints_to_check){ + if(joint.GetLowerLimit() < joint.GetJointAngle() && joint.GetJointAngle() < joint.GetUpperLimit()){ + let torque = joint.GetMotorTorque(60); + + // Calculate angular inertia of the object + let moment_of_inertia = body_to_check.GetInertia(); + let angular_velocity = body_to_check.GetAngularVelocity(); + let angular_inertia = moment_of_inertia * angular_velocity; + + // Calculate the force applied to the object + let world_center = body_to_check.GetWorldCenter(); + let anchor = joint.GetAnchorB(); + let lever_vector = b2.Vec2.Subtract(world_center, anchor); // vector from pivot to point of application of the force + let force_applied_at_center = b2.Cross_v2_f(lever_vector, -torque); + + let push_dot = b2.Dot_v2_v2(normal, force_applied_at_center); + if(push_dot > 0){ + vel = torque + angular_inertia; + // Wrong approximation /!\ + let push_mag = push_dot * this.push_mod * edge_length * density * vel * vel; + let force = b2.Vec2.Multiply(push_mag, b2.Vec2.Negate(force_applied_at_center)); + let clip_force_x = Math.max(-this.max_push, Math.min(force.x, this.max_push)); + let clip_force_y = Math.max(-this.max_push, Math.min(force.y, this.max_push)) + let push_force = new b2.Vec2(clip_force_x, clip_force_y); + body_to_check.ApplyForce(push_force, joint.GetAnchorB(), true); + } + } + } + + } + + } + + } + } +} + +/** + * @classdesc Stores fixtures of objects in contact with water. + * @constructor + */ +function WaterContactDetector() { + b2.ContactListener.call(this); + this.fixture_pairs = []; +} + +WaterContactDetector.prototype = Object.create(b2.ContactListener.prototype); +WaterContactDetector.prototype.constructor = WaterContactDetector; +WaterContactDetector.prototype.BeginContact = function (contact){ + if(contact.GetFixtureA().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.WATER + && contact.GetFixtureB().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT){ + this.fixture_pairs.push([contact.GetFixtureA(), contact.GetFixtureB()]); + } + else if(contact.GetFixtureB().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.WATER + && contact.GetFixtureA().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT){ + this.fixture_pairs.push([contact.GetFixtureB(), contact.GetFixtureA()]); + } +}; + +WaterContactDetector.prototype.EndContact = function (contact) { + if(contact.GetFixtureA().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.WATER + && contact.GetFixtureB().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT){ + let index = this.fixture_pairs.indexOf([contact.GetFixtureA(), contact.GetFixtureB()]); + if (index !== -1) { + this.fixture_pairs.splice(index, 1); + } + } + else if(contact.GetFixtureB().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.WATER + && contact.GetFixtureA().GetBody().GetUserData().object_type == CustomUserDataObjectTypes.BODY_OBJECT){ + let index = this.fixture_pairs.indexOf([contact.GetFixtureB(), contact.GetFixtureA()]); + if (index !== -1) { + this.fixture_pairs.splice(index, 1); + } + } +}; + +WaterContactDetector.prototype.Reset = function (){ + this.fixture_pairs = []; +}; + diff --git a/js/CPPN/cppn.js b/js/CPPN/cppn.js new file mode 100644 index 0000000000000000000000000000000000000000..0d9f996704fe15b2a7c7a33b1f204b98a4434a41 --- /dev/null +++ b/js/CPPN/cppn.js @@ -0,0 +1,33 @@ +/** + * @classdesc CPPN class. + */ +class CPPN { + + /** + * @constructor + * @param x_dim {number} - Number of terrain steps to generate + * @param input_dim {number} - Dimension of the input encoding vector + */ + constructor(x_dim, input_dim){ + this.x_dim = x_dim; + this.input_dim = input_dim; + this.cppn_model = window.cppn_model; + } + + /** + * Generates the terrain shapes with the CPPN model. + * @param input_vector {Array} - 3-dimensional array that encodes the CPPN + * @returns {Array} - Array of y-coordinates of the terrain shapes : [[y_ground, y_ceiling] + */ + generate(input_vector){ + let x = [...Array(this.x_dim).keys()]; + let scaled_x = x.map(e => e / (this.x_dim - 1)); + let x_vec = scaled_x.map(e => [e]); + let final_input = []; + for(let i = 0; i < this.x_dim; i++){ + final_input.push([x_vec[i].concat(input_vector)]); + } + final_input = tf.tensor(final_input); + return this.cppn_model.predict(final_input.reshape([this.x_dim, this.input_dim + 1])); + } +} \ No newline at end of file diff --git a/js/CPPN/weights/ground_cppn/.data-00000-of-00001 b/js/CPPN/weights/ground_cppn/.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..61827bf386d84753cd5f8e0cf5f6ac675ee1c5d1 Binary files /dev/null and b/js/CPPN/weights/ground_cppn/.data-00000-of-00001 differ diff --git a/js/CPPN/weights/ground_cppn/.index b/js/CPPN/weights/ground_cppn/.index new file mode 100644 index 0000000000000000000000000000000000000000..6a1664474b938afc6d107ef2a3a30d9b2d50a6f6 Binary files /dev/null and b/js/CPPN/weights/ground_cppn/.index differ diff --git a/js/CPPN/weights/ground_cppn/.meta b/js/CPPN/weights/ground_cppn/.meta new file mode 100644 index 0000000000000000000000000000000000000000..69f1769e790514da360328938579cea61aba0a4b Binary files /dev/null and b/js/CPPN/weights/ground_cppn/.meta differ diff --git a/js/CPPN/weights/ground_cppn/checkpoint b/js/CPPN/weights/ground_cppn/checkpoint new file mode 100644 index 0000000000000000000000000000000000000000..2619d8b007c68157f1253fc4100c4a3437d60d44 --- /dev/null +++ b/js/CPPN/weights/ground_cppn/checkpoint @@ -0,0 +1,3 @@ +model_checkpoint_path: "." +all_model_checkpoint_paths: "." +all_model_checkpoint_paths: "." diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/.data-00000-of-00001 b/js/CPPN/weights/same_ground_ceiling_cppn/.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..f9f444da5052fca5d0235338353c8b086251384b Binary files /dev/null and b/js/CPPN/weights/same_ground_ceiling_cppn/.data-00000-of-00001 differ diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/.index b/js/CPPN/weights/same_ground_ceiling_cppn/.index new file mode 100644 index 0000000000000000000000000000000000000000..fd5b58b392ff2d36a5fed03f6cc1db3c79f9c1d9 Binary files /dev/null and b/js/CPPN/weights/same_ground_ceiling_cppn/.index differ diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/.meta b/js/CPPN/weights/same_ground_ceiling_cppn/.meta new file mode 100644 index 0000000000000000000000000000000000000000..fa68b13bbf2ca7e817359af87d631ee20f46f13d Binary files /dev/null and b/js/CPPN/weights/same_ground_ceiling_cppn/.meta differ diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/checkpoint b/js/CPPN/weights/same_ground_ceiling_cppn/checkpoint new file mode 100644 index 0000000000000000000000000000000000000000..2619d8b007c68157f1253fc4100c4a3437d60d44 --- /dev/null +++ b/js/CPPN/weights/same_ground_ceiling_cppn/checkpoint @@ -0,0 +1,3 @@ +model_checkpoint_path: "." +all_model_checkpoint_paths: "." +all_model_checkpoint_paths: "." diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/frozen_model/saved_model.pb b/js/CPPN/weights/same_ground_ceiling_cppn/frozen_model/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..e53fc8df2e73c432608d3af90180e517d9e98507 Binary files /dev/null and b/js/CPPN/weights/same_ground_ceiling_cppn/frozen_model/saved_model.pb differ diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/group1-shard1of1.bin b/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..05516f42de8fb42b9b8e4d184bf499eede39a149 --- /dev/null +++ b/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26132af7a3f2d2209504d78a3079b88fbf4d971d1de5485d41bc1cd7e272890c +size 50688 diff --git a/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/model.json b/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/model.json new file mode 100644 index 0000000000000000000000000000000000000000..d0458340fc92882b9cce74884f06f50caa73a712 --- /dev/null +++ b/js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.0", "convertedBy": "TensorFlow.js Converter v3.3.0", "signature": {"outputs": {"Reshape": {"name": "Reshape"}}}, "modelTopology": {"node": [{"name": "Placeholder", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "200"}, {"size": "4"}]}}}}, {"name": "Variable", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}, {"size": "64"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Variable_4", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "64"}, {"size": "2"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Variable_1", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "64"}, {"size": "64"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Variable_2", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "64"}, {"size": "64"}]}}}}}, {"name": "Variable_3", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "64"}, {"size": "64"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "MatMul", "op": "MatMul", "input": ["Placeholder", "Variable"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "Tanh", "op": "Tanh", "input": ["MatMul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "MatMul_1", "op": "MatMul", "input": ["Tanh", "Variable_1"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "Softplus", "op": "Softplus", "input": ["MatMul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "MatMul_2", "op": "MatMul", "input": ["Softplus", "Variable_2"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "Tanh_1", "op": "Tanh", "input": ["MatMul_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "MatMul_3", "op": "MatMul", "input": ["Tanh_1", "Variable_3"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "Softplus_1", "op": "Softplus", "input": ["MatMul_3"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "MatMul_4", "op": "MatMul", "input": ["Softplus_1", "Variable_4"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "Reshape", "op": "Identity", "input": ["MatMul_4"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "Variable", "shape": [4, 64], "dtype": "float32"}, {"name": "Variable_4", "shape": [64, 2], "dtype": "float32"}, {"name": "Variable_1", "shape": [64, 64], "dtype": "float32"}, {"name": "Variable_2", "shape": [64, 64], "dtype": "float32"}, {"name": "Variable_3", "shape": [64, 64], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/js/bodies/abstract_body.js b/js/bodies/abstract_body.js new file mode 100644 index 0000000000000000000000000000000000000000..9809566e3ff2c4086678001641ccca022a957411 --- /dev/null +++ b/js/bodies/abstract_body.js @@ -0,0 +1,161 @@ +/** + * @classdesc Abstract class for agent's morphologies + */ +class AbstractBody { + + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + */ + constructor(scale, motors_torque){ + this.SCALE = scale; + this.MOTORS_TORQUE = motors_torque; + this.body_parts = []; + this.motors = []; + this.is_selected = false; + } + + /** + * Gets the size of the motors state. + * @return {number} + */ + get_state_size(){ + return this.get_motors_state().length; + } + + /** + * Gets the motors state. + * @return {Array} + */ + get_motors_state(){ + let state = []; + for(let motor of this.motors){ + let motor_info = motor.GetUserData(); + if(motor_info.check_contact){ + let s = [ + motor.GetJointAngle() + motor_info.angle_correction, + motor.GetJointSpeed() / motor_info.speed_control, + 0.0 + ] + if(motor_info.contact_body.GetUserData().has_contact){ + s[2] = 1.0; + } + state = state.concat(s); + } + else{ + state = state.concat([ + motor.GetJointAngle() + motor_info.angle_correction, + motor.GetJointSpeed() / motor_info.speed_control + ]) + } + } + return state; + } + + /** + * Gets the size of the action space. + * @return {number} + */ + get_action_size(){ + return this.motors.length; + } + + /** + * Activates the motors according to the given actions by setting the motors speed and torque. + * @param actions {Array} + */ + activate_motors(actions){ + for(let i = 0; i < this.motors.length; i++){ + this.motors[i].SetMotorSpeed(this.motors[i].GetUserData().speed_control * Math.sign(actions[i])); + let clamp01 = Math.max(0, Math.min(Math.abs(actions[i]), 1)); + this.motors[i].SetMaxMotorTorque(this.MOTORS_TORQUE * clamp01); + } + } + + /** + * Creates the Box2D body parts, joints and sensors of the agent. + * @param world {Object} - Box2D world + * @param init_x {number} + * @param init_y {number} + * @param force_to_center {number} + */ + draw(world, init_x, init_y, force_to_center){} + + /** + * Gets all the body parts + * @return {Array} + */ + get_elements_to_render(){ + return this.body_parts; + } + + /** + * Checks if the given position is inside the agent's morphology + * @param pos {{x: number, y: number}} + * @return {boolean} + */ + isPosInside(pos){ + for(let body of this.body_parts){ + let shape = body.GetFixtureList().GetShape(); + let vertices = []; + for(let i = 0; i < shape.m_count; i++){ + let world_pos = body.GetWorldPoint(shape.m_vertices[i]); + vertices.push({x: world_pos.x, y: world_pos.y}); + } + + // Counts the number of intersections between the edges of the polygon and the line of equation y = pos.y which are to the right of pos.x + let nb_intersections = 0; + for(let i = 0; i < vertices.length; i++){ + let v1 = vertices[i]; + let v2; + if(i == vertices.length - 1){ + v2 = vertices[0]; + } + else { + v2 = vertices[i+1]; + } + + // Checks if the edge between v1 and v2 cross the mouse y-coordinate + if(pos.y >= Math.min(v1.y, v2.y) && pos.y <= Math.max(v1.y, v2.y)){ + let intersection_x; + + // Computes the equation of the line between v1 and v2 + let a = (v2.y - v1.y) / (v2.x - v1.x); + let b = v1.y - a * v1.x; + + // Computes the x-coordinate of the intersection point + if(Math.abs(a) == Infinity){ + intersection_x = v1.x; + } + else{ + intersection_x = (pos.y - b) / a; + } + + // Increases the number of intersection only if the intersection point is to the right of the mouse x-coordinate + if(intersection_x >= pos.x) { + nb_intersections += 1; + } + } + } + + // The pos is inside the agent's body if there is an odd number of intersections, else it is outside + if(nb_intersections % 2 != 0){ + return true; + } + } + return false; + } + + /** + * Destroys all the body parts of the agents. + * @param world {Object} - Box2D world + */ + destroy(world){ + for(let body of this.body_parts){ + world.DestroyBody(body); + } + this.body_parts = []; + this.motors = []; + } +} \ No newline at end of file diff --git a/js/bodies/bodies_enum.js b/js/bodies/bodies_enum.js new file mode 100644 index 0000000000000000000000000000000000000000..fa09136f02c609c6ae58bf9b07521a8689f2c8ac --- /dev/null +++ b/js/bodies/bodies_enum.js @@ -0,0 +1,7 @@ +let BodyTypesEnum = { + WALKER: 0, + SWIMMER: 1, + CLIMBER: 2, + AMPHIBIAN: 3, +}; + diff --git a/js/bodies/climbers/climber_abstract_body.js b/js/bodies/climbers/climber_abstract_body.js new file mode 100644 index 0000000000000000000000000000000000000000..05fe0f907109ee352a084c08252150789c9f52f3 --- /dev/null +++ b/js/bodies/climbers/climber_abstract_body.js @@ -0,0 +1,60 @@ +/** + * @classdesc Abstract class for climber morphologies. + */ +class ClimberAbstractBody extends WalkerAbstractBody { + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param nb_steps_under_water {number} + */ + constructor(scale, motors_torque, nb_steps_under_water){ + super(scale, motors_torque, nb_steps_under_water); + + this.body_type = BodyTypesEnum.CLIMBER; + this.sensors = []; + this.SENSOR_FD = new b2.FixtureDef(); + this.SENSOR_FD.shape = new b2.CircleShape(); + this.SENSOR_FD.shape.m_radius = 0.05; + this.SENSOR_FD.density = 1.0; + this.SENSOR_FD.restitution = 0.0; + this.SENSOR_FD.filter.categoryBits = 0x20; + this.SENSOR_FD.filter.maskBits = 0x1; + this.SENSOR_FD.isSensor = true; + } + + // States + get_state_size() { + return super.get_state_size() + this.get_sensors_state().length; + } + + get_sensors_state(){ + let state = []; + for(let sensor of this.sensors){ + state = state.concat([ + sensor.GetUserData().has_contact ? 1 : 0, + sensor.GetUserData().has_joint ? 1 : 0 + ]); + } + return state; + } + + // Actions + get_action_size() { + return super.get_action_size() + this.sensors.length; + } + + // Draw + get_elements_to_render() { + return super.get_elements_to_render().concat(this.sensors); + } + + // Destroy + destroy(world) { + super.destroy(world); + for(let sensor of this.sensors){ + world.DestroyBody(sensor); + } + this.sensors = []; + } +} \ No newline at end of file diff --git a/js/bodies/climbers/climbing_profile_chimpanzee.js b/js/bodies/climbers/climbing_profile_chimpanzee.js new file mode 100644 index 0000000000000000000000000000000000000000..a2eaf66234b09a741b442dba94997cf9238f0d1d --- /dev/null +++ b/js/bodies/climbers/climbing_profile_chimpanzee.js @@ -0,0 +1,293 @@ +const CHIMP_SPEED_HIP = 4; +const CHIMP_SPEED_KNEE = 6; +const CHIMP_SPEED_HAND = 8; + +/** + * @classdesc Chimpanzee morphology. + */ +class ClimbingProfileChimpanzee extends ClimberAbstractBody { + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param nb_steps_under_water {number} + */ + constructor(scale, motors_torque=100, nb_steps_under_water=600){ + super(scale, motors_torque, nb_steps_under_water); + + this.LEG_DOWN = 12 / this.SCALE; + this.ARM_UP = 22 / this.SCALE; + this.LIMB_W = 8 / this.SCALE; + this.LIMB_H = 28 / this.SCALE; + this.HAND_PART_W = 4 / this.SCALE; + this.HAND_PART_H = 8 / this.SCALE; + this.LEG_H = this.LIMB_H; + this.TORQUE_PENALTY = 0.00035 / 5; // Legs + arms + hands + this.BODY_HEIGHT = 45; + this.HEAD_HEIGHT = 20; + this.HEAD_UP = 2.5 / this.SCALE; // formerly 0.2 + + this.AGENT_WIDTH = 24 / this.SCALE; + this.AGENT_HEIGHT = this.BODY_HEIGHT / this.SCALE + + this.HEAD_HEIGHT / this.SCALE + + this.HEAD_UP + this.LEG_H * 2 + - this.LEG_DOWN; + this.AGENT_CENTER_HEIGHT = this.LEG_H * 2 + this.LEG_DOWN; + + this.remove_reward_on_head_angle = true; + } + + draw(world, init_x, init_y, force_to_center){ + + // Head + let head_fd = new b2.FixtureDef(); + head_fd.shape = new b2.PolygonShape(); + head_fd.shape.SetAsBox(5 / this.SCALE, 10 / this.SCALE); + /*head_fd.shape.Set([ + new b2.Vec2(-5 / this.SCALE, 10 / this.SCALE), + new b2.Vec2(5 / this.SCALE, 10 / this.SCALE), + new b2.Vec2(5 / this.SCALE, -10 / this.SCALE), + new b2.Vec2(-5 / this.SCALE, -10 / this.SCALE), + ], 4);*/ + head_fd.density = 5.0; + head_fd.friction = 0.1; + head_fd.filter.categoryBits = 0x20; + head_fd.filter.maskBits = 0x1; + + let head_bd = new b2.BodyDef(); + head_bd.type = b2.Body.b2_dynamicBody; + head_bd.position.Set(init_x, + init_y + this.BODY_HEIGHT / this.SCALE / 2 + this.HEAD_HEIGHT / this.SCALE / 2 + this.HEAD_UP); + let head = world.CreateBody(head_bd); + head.CreateFixture(head_fd); + head.color1 = "#806682"; // [0.5, 0.4, 0.9] + head.color2 = "#4D4D80"; + head.ApplyForceToCenter(new b2.Vec2(force_to_center, 0), true); + head.SetUserData(new CustomBodyUserData(true, true, "head")); + this.body_parts.push(head); + this.reference_head_object = head; + + // Body + let body_fd = new b2.FixtureDef(); + body_fd.shape = new b2.PolygonShape(); + body_fd.shape.Set([ + new b2.Vec2(-12 / this.SCALE, 25 / this.SCALE), + new b2.Vec2(12 / this.SCALE, 25 / this.SCALE), + new b2.Vec2(8 / this.SCALE, -20 / this.SCALE), + new b2.Vec2(-8 / this.SCALE, -20 / this.SCALE), + ], 4); + body_fd.density = 5.0; + body_fd.friction = 0.1; + body_fd.filter.categoryBits = 0x20; + body_fd.filter.maskBits = 0x1; // collide only with ground + + let body_bd = new b2.BodyDef(); + body_bd.type = b2.Body.b2_dynamicBody; + body_bd.position.Set(init_x, init_y); + let body = world.CreateBody(body_bd); + body.CreateFixture(body_fd); + body.color1 = "#806682"; // [0.5, 0.4, 0.9] + body.color2 = "#4D4D80"; // [0.3, 0.3, 0.5] + body.SetUserData(new CustomBodyUserData(true, true, "body")); + this.body_parts.push(body); + + // Revolute joint between head and body + let rjd = new b2.RevoluteJointDef(); + rjd.Initialize(head, body, new b2.Vec2(init_x, init_y + this.BODY_HEIGHT / this.SCALE / 2)); + rjd.enableMotor = false; + rjd.enableLimit = true; + rjd.lowerAngle = -0.1 * Math.PI; + rjd.upperAngle = 0.1 * Math.PI; + let joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("neck", 0, false)); + this.neck_joint = joint_motor; + + // Limbs FixtureDef + let UPPER_LIMB_FD = new b2.FixtureDef(); + UPPER_LIMB_FD.shape = new b2.PolygonShape(); + UPPER_LIMB_FD.shape.SetAsBox(this.LIMB_W / 2, this.LIMB_H / 2); + UPPER_LIMB_FD.density = 1.0; + UPPER_LIMB_FD.restitution = 0; + UPPER_LIMB_FD.filter.categoryBits = 0x20; + UPPER_LIMB_FD.filter.maskBits = 0x1; + + let LOWER_LIMB_FD = new b2.FixtureDef(); + LOWER_LIMB_FD.shape = new b2.PolygonShape(); + LOWER_LIMB_FD.shape.SetAsBox(0.8 * this.LIMB_W / 2, this.LIMB_H / 2); + LOWER_LIMB_FD.density = 1.0; + LOWER_LIMB_FD.restitution = 0; + LOWER_LIMB_FD.filter.categoryBits = 0x20; + LOWER_LIMB_FD.filter.maskBits = 0x1; + + let HAND_PART_FD = new b2.FixtureDef(); + HAND_PART_FD.shape = new b2.PolygonShape(); + HAND_PART_FD.shape.SetAsBox(this.HAND_PART_W / 2, this.HAND_PART_H / 2); + HAND_PART_FD.density = 1.0; + HAND_PART_FD.restitution = 0; + HAND_PART_FD.filter.categoryBits = 0x20; + HAND_PART_FD.filter.maskBits = 0x1; + + // Legs + for(let i = 0; i < 2; i++){ + + // Upper leg + let upper_bd = new b2.BodyDef(); + upper_bd.type = b2.Body.b2_dynamicBody; + upper_bd.position.Set(init_x, init_y - this.LIMB_H / 2 - this.LEG_DOWN); + let upper = world.CreateBody(upper_bd); + upper.CreateFixture(UPPER_LIMB_FD); + upper.color1 = "#964A7D"; // [0.59, 0.29, 0.49] + upper.color2 = "#63304A"; // [0.39, 0.19, 0.29] + upper.SetUserData(new CustomBodyUserData(false, false, "upper_leg")); + this.body_parts.push(upper); + + // Revolute joint between body and upper leg + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(body, upper, new b2.Vec2(init_x, init_y - this.LEG_DOWN)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.3 * Math.PI; + rjd.upperAngle = 0.6 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", CHIMP_SPEED_HIP, false)); + this.motors.push(joint_motor); + + // Lower leg + let lower_bd = new b2.BodyDef(); + lower_bd.type = b2.Body.b2_dynamicBody; + lower_bd.position.Set(init_x, init_y - this.LIMB_H * 3/2 - this.LEG_DOWN); + let lower = world.CreateBody(lower_bd); + lower.CreateFixture(LOWER_LIMB_FD); + lower.color1 = "#964A7D"; // [0.59, 0.29, 0.49] + lower.color2 = "#63304A"; // [0.39, 0.19, 0.29] + lower.SetUserData(new CustomBodyUserData(true, true, "lower_leg")); + this.body_parts.push(lower); + + // Revolute joint between upper and lower leg + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(upper, lower, new b2.Vec2(init_x, init_y - this.LEG_H - this.LEG_DOWN)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.75 * Math.PI; + rjd.upperAngle = -0.1; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("knee", + CHIMP_SPEED_KNEE, + true, + 1, + lower)); + this.motors.push(joint_motor); + } + + // Arms + for(let i = 0; i < 2; i++){ + // Upper arm + let upper_bd = new b2.BodyDef(); + upper_bd.type = b2.Body.b2_dynamicBody; + upper_bd.position.Set(init_x, init_y + this.LIMB_H / 2 + this.ARM_UP); + let upper = world.CreateBody(upper_bd); + upper.CreateFixture(UPPER_LIMB_FD); + upper.color1 = "#9C4F82"; // [0.61, 0.31, 0.51] + upper.color2 = "#69364F"; // [0.41, 0.21, 0.31] + upper.SetUserData(new CustomBodyUserData(false, false, "upper_arm")); + this.body_parts.push(upper); + + // Revolute joint between body and upper arm + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(body, upper, new b2.Vec2(init_x, init_y + this.ARM_UP)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.75 * 2 * Math.PI; + rjd.upperAngle = 0; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("shoulder", CHIMP_SPEED_HIP, false)); + this.motors.push(joint_motor); + + // Lower arm + let lower_bd = new b2.BodyDef(); + lower_bd.type = b2.Body.b2_dynamicBody; + lower_bd.position.Set(init_x, init_y + this.LIMB_H * 3/2 + this.ARM_UP); + let lower = world.CreateBody(lower_bd); + lower.CreateFixture(LOWER_LIMB_FD); + lower.color1 = "#9C4F82"; // [0.61, 0.31, 0.51] + lower.color2 = "#69364F"; // [0.41, 0.21, 0.31] + lower.SetUserData(new CustomBodyUserData(false, false, "lower_arm")); + this.body_parts.push(lower); + + // Revolute joint between upper arm and lower arm + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(upper, lower, new b2.Vec2(init_x, init_y + this.LIMB_H + this.ARM_UP)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = 0; + rjd.upperAngle = 0.75 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("elbow", + CHIMP_SPEED_HIP, + false)); + this.motors.push(joint_motor); + + // Hand + let prev_part = lower; + let initial_y = init_y + this.LIMB_H * 2 + this.ARM_UP; + let angle_boundaries = [[-0.5, 0.5]]; + let nb_hand_parts = 1; + for(let u = 0; u < nb_hand_parts; u++){ + let hand_part_bd = new b2.BodyDef(); + hand_part_bd.type = b2.Body.b2_dynamicBody; + hand_part_bd.position.Set(init_x, initial_y + this.HAND_PART_H / 2 + this.HAND_PART_H * u); + let hand_part = world.CreateBody(hand_part_bd); + hand_part.CreateFixture(HAND_PART_FD); + hand_part.color1 = "#9C4F82"; // [0.61, 0.31, 0.51] + hand_part.color2 = "#69364F"; // [0.41, 0.21, 0.31] + hand_part.SetUserData(new CustomBodyUserData(true, false, "hand")); + this.body_parts.push(hand_part); + + // Revolute joint between prev_part and hand_part + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(prev_part, hand_part, new b2.Vec2(init_x, initial_y + this.HAND_PART_H * u)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = angle_boundaries[u][0] * Math.PI; + rjd.upperAngle = angle_boundaries[u][1] * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("hand", + CHIMP_SPEED_HAND, + true, + 0, + hand_part)); + this.motors.push(joint_motor); + + prev_part = hand_part; + } + + // Sensor + let hand_sensor_position = new b2.Vec2(init_x, initial_y + this.HAND_PART_H * nb_hand_parts); + let hand_sensor_part_bd = new b2.BodyDef(); + hand_sensor_part_bd.type = b2.Body.b2_dynamicBody; + hand_sensor_part_bd.position.Assign(hand_sensor_position); + let hand_sensor_part = world.CreateBody(hand_sensor_part_bd); + hand_sensor_part.CreateFixture(this.SENSOR_FD); + hand_sensor_part.color1 = "#FF0000"; // [1, 0, 0] + hand_sensor_part.color2 = "#FF0000"; // [1, 0, 0] + hand_sensor_part.SetUserData(new CustomBodySensorUserData(true, false, "hand_sensor")); + this.sensors.push(hand_sensor_part); + + let wjd = new b2.WeldJointDef(); + wjd.Initialize(prev_part, hand_sensor_part, hand_sensor_position); + world.CreateJoint(wjd); + } + + + } +} \ No newline at end of file diff --git a/js/bodies/swimmers/fish_body.js b/js/bodies/swimmers/fish_body.js new file mode 100644 index 0000000000000000000000000000000000000000..6d5b5563ff5141a614e5ed3e8c8d241ba1770465 --- /dev/null +++ b/js/bodies/swimmers/fish_body.js @@ -0,0 +1,248 @@ +// Head +HULL_POLYGON = [ + [-20, +12], [+6, +12], + [+15, +4], [+15, -4], + [+6, -12], [-20, -12] +]; + +BODY_P1 = [ + [-8, +9], [+8, +12], + [+8, -12], [-8, -9] +]; + +BODY_P2 = [ + [-8, +4], [+8, +9], + [+8, -9], [-8, -4] +]; + +// Tail +BODY_P3 = [ + [-4, +2], [+4, +4], + [+4, -4], [-4, -2] +]; + +FIN = [ + [-1, -10], [-1, +10], + [+1, +10], [+1, -10] +]; + +HULL_BOTTOM_WIDTH = 35; +const SPEED = 6; + +/** + * @classdesc Fish morphology. + */ +class FishBody extends SwimmerAbstractBody { + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param density {number} - Density of the agent's body. + * @param nb_steps_outside_water {number} + */ + constructor(scale, motors_torque=80, density, nb_steps_outside_water=600) { + super(scale, motors_torque, density, nb_steps_outside_water); + this.TORQUE_PENALTY = 0.00035; + + this.AGENT_WIDTH = HULL_BOTTOM_WIDTH / this.SCALE; + this.AGENT_HEIGHT = 18 / this.SCALE; + this.AGENT_CENTER_HEIGHT = 9 / this.SCALE; + + this.remove_reward_on_head_angle = true; + + this.fins = []; + this.tail = null; + } + + draw(world, init_x, init_y){ + + let vertices; + let rjd; + let joint_motor; + + // HULL + let hull_fd = new b2.FixtureDef(); + hull_fd.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of HULL_POLYGON){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + hull_fd.shape.Set(vertices, HULL_POLYGON.length); + hull_fd.density = this.DENSITY; + hull_fd.friction = 0.1; + hull_fd.filter.categoryBits = 0x20; + hull_fd.filter.maskBits = 0x000F; // 0.99 bouncy + + let hull_bd = new b2.BodyDef(); + hull_bd.type = b2.Body.b2_dynamicBody; + hull_bd.position.Set(init_x, init_y); + let hull = world.CreateBody(hull_bd); + hull.CreateFixture(hull_fd); + hull.color1 = "#806682"; // [0.5, 0.4, 0.9] + hull.color2 = "#4D4D80"; + hull.SetUserData(new CustomBodyUserData(true, false, "head")); + this.body_parts.push(hull); + this.reference_head_object = hull; + + // BODY_P1 + let body_p1_x = init_x - 35 / 2 / this.SCALE - 16 / 2 / this.SCALE; + let body_p1_fd = new b2.FixtureDef(); + body_p1_fd.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of BODY_P1){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + body_p1_fd.shape.Set(vertices, BODY_P1.length); + body_p1_fd.density = this.DENSITY; + body_p1_fd.restitution = 0.0; + body_p1_fd.filter.categoryBits = 0x20; + body_p1_fd.filter.maskBits = 0x000F; // 0.99 bouncy + + let body_p1_bd = new b2.BodyDef(); + body_p1_bd.type = b2.Body.b2_dynamicBody; + body_p1_bd.position.Set(body_p1_x, init_y); + let body_p1 = world.CreateBody(body_p1_bd); + body_p1.CreateFixture(body_p1_fd); + body_p1.color1 = "#806682"; // [0.5, 0.4, 0.9] + body_p1.color2 = "#4D4D80"; + body_p1.SetUserData(new CustomBodyUserData(true, false, "body")); + this.body_parts.push(body_p1); + + // Revolute joint between HULL and BODY_P1 + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(hull, body_p1, new b2.Vec2(init_x - 35 / 2 / this.SCALE, init_y)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.1 * Math.PI; + rjd.upperAngle = 0.2 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("neck", SPEED, true, 0.0, body_p1)); + this.motors.push(joint_motor); + + // BODY_P2 + let body_p2_x = body_p1_x - 16 / 2 / this.SCALE - 16 / 2 / this.SCALE; + let body_p2_fd = new b2.FixtureDef(); + body_p2_fd.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of BODY_P2){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + body_p2_fd.shape.Set(vertices, BODY_P2.length); + body_p2_fd.density = this.DENSITY; + body_p2_fd.restitution = 0.0; + body_p2_fd.filter.categoryBits = 0x20; + body_p2_fd.filter.maskBits = 0x000F; + + let body_p2_bd = new b2.BodyDef(); + body_p2_bd.type = b2.Body.b2_dynamicBody; + body_p2_bd.position.Set(body_p2_x, init_y); + let body_p2 = world.CreateBody(body_p2_bd); + body_p2.CreateFixture(body_p2_fd); + body_p2.color1 = "#806682"; // [0.5, 0.4, 0.9] + body_p2.color2 = "#4D4D80"; + body_p2.SetUserData(new CustomBodyUserData(true, false, "body")); + this.body_parts.push(body_p2); + + // Revolute joint between BODY_P1 and BODY_P2 + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(body_p1, body_p2, new b2.Vec2(body_p1_x - 16 / 2 / this.SCALE, init_y)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.15 * Math.PI; + rjd.upperAngle = 0.15 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", SPEED, true, 0.0, body_p2)); + this.motors.push(joint_motor); + + // BODY_P3 - TAIL + let body_p3_x = body_p2_x - 16 / 2 / this.SCALE - 8 / 2 / this.SCALE; + let body_p3_fd = new b2.FixtureDef(); + body_p3_fd.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of BODY_P3){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + body_p3_fd.shape.Set(vertices, BODY_P3.length); + body_p3_fd.density = this.DENSITY; + body_p3_fd.restitution = 0.0; + body_p3_fd.filter.categoryBits = 0x20; + body_p3_fd.filter.maskBits = 0x000F; + + let body_p3_bd = new b2.BodyDef(); + body_p3_bd.type = b2.Body.b2_dynamicBody; + body_p3_bd.position.Set(body_p3_x, init_y); + let body_p3 = world.CreateBody(body_p3_bd); + body_p3.CreateFixture(body_p3_fd); + body_p3.color1 = "#806682"; // [0.5, 0.4, 0.9] + body_p3.color2 = "#4D4D80"; + body_p3.SetUserData(new CustomBodyUserData(true, false, "body")); + this.body_parts.push(body_p3); + this.tail = body_p3; + + // Revolute joint between BODY_P2 and BODY_P3 + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(body_p2, body_p3, new b2.Vec2(body_p2_x - 16 / 2 / this.SCALE, init_y)); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.3 * Math.PI; + rjd.upperAngle = 0.3 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("knee", SPEED, true, 0.0, body_p3)); + this.motors.push(joint_motor); + + // FINS + let fin_fd = new b2.FixtureDef(); + fin_fd.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of FIN){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + fin_fd.shape.Set(vertices, FIN.length); + fin_fd.density = this.DENSITY; + fin_fd.restitution = 0.0; + fin_fd.filter.categoryBits = 0x20; + fin_fd.filter.maskBits = 0x000F; + + let fin_positions = [ + [init_x, init_y - 22 / 2 / this.SCALE + 0.2], + ]; + let fin_angle = -0.2 * Math.PI; + let middle_fin_x_distance = Math.sin(fin_angle) * 20 / 2 / this.SCALE; + let middle_fin_y_distance = Math.cos(fin_angle) * 20 / 2 / this.SCALE; + + for(let fin_pos of fin_positions){ + let current_fin_x = fin_pos[0] + middle_fin_x_distance; + let current_fin_y = fin_pos[1] - middle_fin_y_distance; + + let fin_bd = new b2.BodyDef(); + fin_bd.type = b2.Body.b2_dynamicBody; + fin_bd.position.Set(current_fin_x, current_fin_y); + let fin = world.CreateBody(fin_bd); + fin.CreateFixture(fin_fd); + fin.color1 = "#806682"; // [0.5, 0.4, 0.9] + fin.color2 = "#4D4D80"; + fin.SetUserData(new CustomBodyUserData(true, false, "fin")); + this.body_parts.push(fin); + this.fins.push(fin); + + // Revolute joint between HULL and FIN + rjd = new b2.RevoluteJointDef(); + rjd.Initialize(hull, fin, new b2.Vec2(fin_pos[0], fin_pos[1])); + rjd.enableMotor = true; + rjd.enableLimit = true; + rjd.maxMotorTorque = this.MOTORS_TORQUE; + rjd.motorSpeed = 1; + rjd.lowerAngle = -0.3 * Math.PI; + rjd.upperAngle = 0.2 * Math.PI; + joint_motor = world.CreateJoint(rjd); + joint_motor.SetUserData(new CustomMotorUserData("shoulder", SPEED, true, 0.0, fin)); + this.motors.push(joint_motor); + } + } +} \ No newline at end of file diff --git a/js/bodies/swimmers/swimmer_abstract_body.js b/js/bodies/swimmers/swimmer_abstract_body.js new file mode 100644 index 0000000000000000000000000000000000000000..44c6b7d312da552647da9f4a98e340600bdca8e0 --- /dev/null +++ b/js/bodies/swimmers/swimmer_abstract_body.js @@ -0,0 +1,26 @@ +/** + * @classdesc Abstract class for swimmer morphologies. + */ +class SwimmerAbstractBody extends AbstractBody{ + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param density {number} - Density of the agent's body. + * @param nb_steps_outside_water {number} + */ + constructor(scale, motors_torque, density, nb_steps_outside_water) { + super(scale, motors_torque); + this.body_type = BodyTypesEnum.SWIMMER; + this.nb_steps_can_survive_outside_water = nb_steps_outside_water; + + // set the embodiment's density to the same value as water so that it will be in a zero-gravity setup + this.DENSITY = density - 0.01; // Make it a little lighter such that it slowly goes up when no action is done + } + + destroy(world) { + super.destroy(world); + this.fins = []; + this.tail = null; + } +} \ No newline at end of file diff --git a/js/bodies/walkers/classic_bipedal_body.js b/js/bodies/walkers/classic_bipedal_body.js new file mode 100644 index 0000000000000000000000000000000000000000..12b574a722fb6510c78789fbdd6202a426c7ee4b --- /dev/null +++ b/js/bodies/walkers/classic_bipedal_body.js @@ -0,0 +1,140 @@ +HULL_POLYGONS = [ + [[-30, +9], [+6, +9], [+34, +1], [+34, -8], [-30, -8]] +]; +HULL_BOTTOM_WIDTH = 64; +const SPEED_HIP = 4; +const SPEED_KNEE = 6; + +/** + * @classdesc Bipedal Walker morphology. + */ +class ClassicBipedalBody extends WalkerAbstractBody { + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param nb_steps_under_water {number} + * @param reset_on_hull_critical_contact {boolean} + */ + constructor(scale, motors_torque=80, nb_steps_under_water=600, reset_on_hull_critical_contact=false) { + super(scale, motors_torque, nb_steps_under_water); + + this.LEG_DOWN = 3 / this.SCALE; // 0 = center of hull + this.LEG_W = 8 / this.SCALE; + this.LEG_H = 34 / this.SCALE; + this.TORQUE_PENALTY = 0.00035; + this.reset_on_hull_critical_contact = reset_on_hull_critical_contact; + + this.AGENT_WIDTH = HULL_BOTTOM_WIDTH / this.SCALE; + this.AGENT_HEIGHT = 17 / this.SCALE + this.LEG_H * 2 - this.LEG_DOWN; + this.AGENT_CENTER_HEIGHT = this.LEG_H * 2 + this.LEG_DOWN; + + this.old_morphology = false; + } + + draw(world, init_x, init_y, force_to_center){ + let HULL_FIXTURES = []; + let fd_polygon; + let vertices; + let y_offset = 0;//10/this.SCALE; + + for(let polygon of HULL_POLYGONS){ + fd_polygon = new b2.FixtureDef(); + fd_polygon.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of polygon){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + fd_polygon.shape.Set(vertices, polygon.length); + fd_polygon.density = 5.0; + fd_polygon.friction = 0.1; + fd_polygon.filter.categoryBits = 0x20; + fd_polygon.filter.maskBits = 0x000F; // 0.99 bouncy + HULL_FIXTURES.push(fd_polygon); + } + + let LEG_FD = new b2.FixtureDef(); + LEG_FD.shape = new b2.PolygonShape(); + LEG_FD.shape.SetAsBox(this.LEG_W / 2, this.LEG_H / 2); + LEG_FD.density = 1.0; + LEG_FD.restitution = 0.0; + LEG_FD.filter.categoryBits = 0x20; + LEG_FD.filter.maskBits = 0x000F; + + let LOWER_FD = new b2.FixtureDef(); + LOWER_FD.shape = new b2.PolygonShape(); + LOWER_FD.shape.SetAsBox(0.8 * this.LEG_W / 2, this.LEG_H / 2); + LOWER_FD.density = 1.0; + LOWER_FD.restitution = 0.0; + LOWER_FD.filter.categoryBits = 0x20; + LOWER_FD.filter.maskBits = 0x000F; + + let hull_bd = new b2.BodyDef(); + hull_bd.type = b2.Body.b2_dynamicBody; + hull_bd.position.Set(init_x, init_y + y_offset); + let hull = world.CreateBody(hull_bd); + for(let fd of HULL_FIXTURES){ + hull.CreateFixture(fd); + } + hull.color1 = "#806682"; // [0.5, 0.4, 0.9] + hull.color2 = "#4D4D80"; // [0.3, 0.3, 0.5] + hull.ApplyForceToCenter(new b2.Vec2(force_to_center, 0), true); + hull.SetUserData(new CustomBodyUserData(true, this.reset_on_hull_critical_contact, "hull")); + this.body_parts.push(hull); + this.reference_head_object = hull; + + // Leg and lower bodies and joints + for(let i of [-1, +1]){ + + // Leg body + let leg_bd = new b2.BodyDef(); + leg_bd.type = b2.Body.b2_dynamicBody; + leg_bd.position.Set(init_x, init_y - this.LEG_H / 2 - this.LEG_DOWN + y_offset); + //leg_bd.angle = i * 0.05; // 2° + let leg = world.CreateBody(leg_bd); + leg.CreateFixture(LEG_FD); + leg.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49] + leg.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29] + leg.SetUserData(new CustomBodyUserData(false, false,"leg")); + this.body_parts.push(leg); + + // Leg joint motor + let leg_rjd = new b2.RevoluteJointDef(); + leg_rjd.Initialize(hull, leg, new b2.Vec2(init_x, init_y - this.LEG_DOWN + y_offset)); + leg_rjd.enableMotor = true; + leg_rjd.enableLimit = true; + leg_rjd.maxMotorTorque = this.MOTORS_TORQUE; + leg_rjd.motorSpeed = i; + leg_rjd.lowerAngle = - 0.8; + leg_rjd.upperAngle = 1.1; + let joint_motor = world.CreateJoint(leg_rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", SPEED_HIP, false)); + this.motors.push(joint_motor); + + // lower body + let lower_bd = new b2.BodyDef(); + lower_bd.type = b2.Body.b2_dynamicBody; + lower_bd.position.Set(init_x, init_y - this.LEG_H * 3 / 2 - this.LEG_DOWN + y_offset); + //lower_bd.angle = i * 0.05; // 2° + let lower = world.CreateBody(lower_bd); + lower.CreateFixture(LOWER_FD); + lower.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49] + lower.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29] + lower.SetUserData(new CustomBodyUserData(true, false,"lower")); + this.body_parts.push(lower); + + // lower joint motor + let lower_rjd = new b2.RevoluteJointDef(); + lower_rjd.Initialize(leg, lower, new b2.Vec2(init_x, init_y - this.LEG_DOWN - this.LEG_H + y_offset)); + lower_rjd.enableMotor = true; + lower_rjd.enableLimit = true; + lower_rjd.maxMotorTorque = this.MOTORS_TORQUE; + lower_rjd.motorSpeed = 1; + lower_rjd.lowerAngle = - 1.6; + lower_rjd.upperAngle = -0.1; + joint_motor = world.CreateJoint(lower_rjd); + joint_motor.SetUserData(new CustomMotorUserData("knee", SPEED_KNEE, true, 1.0, lower)); + this.motors.push(joint_motor); + } + } +} \ No newline at end of file diff --git a/js/bodies/walkers/old_classic_bipedal_body.js b/js/bodies/walkers/old_classic_bipedal_body.js new file mode 100644 index 0000000000000000000000000000000000000000..0abb3b49a56e4b2efa3b9d34162ecad46c8321da --- /dev/null +++ b/js/bodies/walkers/old_classic_bipedal_body.js @@ -0,0 +1,140 @@ +HULL_POLYGONS = [ + [[-30, +9], [+6, +9], [+34, +1], [+34, -8], [-30, -8]] +]; +HULL_BOTTOM_WIDTH = 64; +SPEED_HIP = 4; +SPEED_KNEE = 6; + +class OldClassicBipedalBody extends WalkerAbstractBody{ + constructor(scale, nb_steps_under_water=600, reset_on_hull_critical_contact=true){ + super(scale, 80, nb_steps_under_water); + + this.LEG_DOWN = -8 / this.SCALE; // 0 = center of hull + this.LEG_W = 8 / this.SCALE; + this.LEG_H = 34 / this.SCALE; + this.TORQUE_PENALTY = 0.00035; + this.reset_on_hull_critical_contact = reset_on_hull_critical_contact; + + // Approximative... + this.AGENT_WIDTH = HULL_BOTTOM_WIDTH / this.SCALE; + this.AGENT_HEIGHT = 17 / this.SCALE + this.LEG_H * 2 - this.LEG_DOWN + 0.5; + this.AGENT_CENTER_HEIGHT = this.LEG_H * 2 + this.LEG_DOWN + 0.5; + + this.old_morphology = true; + + this.body_parts = []; + this.nb_motors = 4; + this.motors = []; + this.state_size = this.nb_motors * 2 + 2; + } + + draw(world, init_x, init_y, force_to_center){ + let HULL_FIXTURES = []; + let fd_polygon; + let vertices; + let y_offset = 0//10/this.SCALE; + + for(let polygon of HULL_POLYGONS){ + fd_polygon = new b2.FixtureDef(); + fd_polygon.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of polygon){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + fd_polygon.shape.Set(vertices, polygon.length); + fd_polygon.density = 5.0; + fd_polygon.friction = 0.1; + fd_polygon.filter.categoryBits = 0x20; + fd_polygon.filter.maskBits = 0x000F; // 0.99 bouncy + HULL_FIXTURES.push(fd_polygon); + } + + let LEG_FD = new b2.FixtureDef(); + LEG_FD.shape = new b2.PolygonShape(); + LEG_FD.shape.SetAsBox(this.LEG_W / 2, this.LEG_H / 2); + LEG_FD.density = 1.0; + LEG_FD.restitution = 0.0; + LEG_FD.filter.categoryBits = 0x20; + LEG_FD.filter.maskBits = 0x000F; + + let LOWER_FD = new b2.FixtureDef(); + LOWER_FD.shape = new b2.PolygonShape(); + LOWER_FD.shape.SetAsBox(0.8 * this.LEG_W / 2, this.LEG_H / 2); + LOWER_FD.density = 1.0; + LOWER_FD.restitution = 0.0; + LOWER_FD.filter.categoryBits = 0x20; + LOWER_FD.filter.maskBits = 0x000F; + + let hull_bd = new b2.BodyDef(); + hull_bd.type = b2.Body.b2_dynamicBody; + hull_bd.position.Set(init_x, init_y + y_offset); + let hull = world.CreateBody(hull_bd); + for(let fd of HULL_FIXTURES){ + hull.CreateFixture(fd); + } + hull.color1 = "#806682"; // [0.5, 0.4, 0.9] + hull.color2 = "#4D4D80"; // [0.3, 0.3, 0.5] + //hull.ApplyForceToCenter(new b2.Vec2(force_to_center, 0), true); + hull.SetUserData(new CustomBodyUserData(true, this.reset_on_hull_critical_contact, "hull")); + this.body_parts.push(hull); + this.reference_head_object = hull; + + // Leg and lower bodies and joints + for(let i of [-1, +1]){ + + // Leg body + let leg_bd = new b2.BodyDef(); + leg_bd.type = b2.Body.b2_dynamicBody; + leg_bd.position.Set(init_x, init_y - this.LEG_H / 2 - this.LEG_DOWN + y_offset); + leg_bd.angle = i * 0.05; // 2° + let leg = world.CreateBody(leg_bd); + leg.CreateFixture(LEG_FD); + leg.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49] + leg.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29] + leg.SetUserData(new CustomBodyUserData(false, false,"leg")); + this.body_parts.push(leg); + + // Leg joint motor + let leg_rjd = new b2.RevoluteJointDef(); + leg_rjd.Initialize(hull, leg, new b2.Vec2(init_x, init_y - this.LEG_DOWN + y_offset)); + leg_rjd.localAnchorA = new b2.Vec2(0, this.LEG_DOWN); + leg_rjd.localAnchorB = new b2.Vec2(0, this.LEG_H / 2); + leg_rjd.enableMotor = true; + leg_rjd.enableLimit = true; + leg_rjd.maxMotorTorque = this.MOTORS_TORQUE; + leg_rjd.motorSpeed = i; + leg_rjd.lowerAngle = - 0.8; + leg_rjd.upperAngle = 1.1; + let joint_motor = world.CreateJoint(leg_rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", SPEED_HIP, false)); + this.motors.push(joint_motor); + + // lower body + let lower_bd = new b2.BodyDef(); + lower_bd.type = b2.Body.b2_dynamicBody; + lower_bd.position.Set(init_x, init_y - this.LEG_H * 3 / 2 - this.LEG_DOWN + y_offset); + lower_bd.angle = i * 0.05; // 2° + let lower = world.CreateBody(lower_bd); + lower.CreateFixture(LOWER_FD); + lower.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49] + lower.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29] + lower.SetUserData(new CustomBodyUserData(true, false,"lower")); + this.body_parts.push(lower); + + // lower joint motor + let lower_rjd = new b2.RevoluteJointDef(); + lower_rjd.Initialize(leg, lower, new b2.Vec2(init_x, init_y - this.LEG_DOWN - this.LEG_H + y_offset)); + lower_rjd.localAnchorA = new b2.Vec2(0, - this.LEG_H / 2); + lower_rjd.localAnchorB = new b2.Vec2(0, this.LEG_H / 2); + lower_rjd.enableMotor = true; + lower_rjd.enableLimit = true; + lower_rjd.maxMotorTorque = this.MOTORS_TORQUE; + lower_rjd.motorSpeed = 1; + lower_rjd.lowerAngle = - 1.6; + lower_rjd.upperAngle = -0.1; + joint_motor = world.CreateJoint(lower_rjd); + joint_motor.SetUserData(new CustomMotorUserData("knee", SPEED_KNEE, true, 1.0, lower)); + this.motors.push(joint_motor); + } + } +} \ No newline at end of file diff --git a/js/bodies/walkers/spider_body.js b/js/bodies/walkers/spider_body.js new file mode 100644 index 0000000000000000000000000000000000000000..83121b88c8956b392bb59922ee2c9a94e38db44f --- /dev/null +++ b/js/bodies/walkers/spider_body.js @@ -0,0 +1,189 @@ +const MAIN_BODY_POLYGONS = [ + [[-10, +10], [+10, +10], [+10, -10], [-10, -10]] +] +const MAIN_BODY_BOTTOM_WIDTH = 20 +const SPIDER_SPEED_HIP = 4 +const SPIDER_SPEED_KNEE = 6 + +/** + * @classdesc Spider morphology. + */ +class SpiderBody extends WalkerAbstractBody { + + constructor(scale, motors_torque=100, nb_pairs_of_legs=2, + nb_steps_under_water=600, reset_on_hull_critical_contact=false){ + super(scale, motors_torque, nb_steps_under_water); + + this.LEG_DOWN = 4 / this.SCALE; + this.LEG_W = 6 / this.SCALE; + this.LEG_H = 20 / this.SCALE; + this.reset_on_critical_contact = reset_on_hull_critical_contact; + + this.nb_pairs_of_legs = nb_pairs_of_legs; + + this.TORQUE_PENALTY = 0.00035 / this.nb_pairs_of_legs; + + // not exacts but works + this.AGENT_WIDTH = MAIN_BODY_BOTTOM_WIDTH / this.SCALE + this.LEG_H * 4; + this.AGENT_HEIGHT = 20 / this.SCALE + this.LEG_H * 2; + this.AGENT_CENTER_HEIGHT = this.LEG_H + this.LEG_DOWN; + } + + draw(world, init_x, init_y, force_to_center){ + + let fd_polygon; + let vertices; + + /* Creates the different fixtures */ + + let MAIN_BODY_FIXTURES = []; + for(let polygon of MAIN_BODY_POLYGONS){ + fd_polygon = new b2.FixtureDef(); + fd_polygon.shape = new b2.PolygonShape(); + vertices = []; + for(let vertex of polygon){ + vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE)); + } + fd_polygon.shape.Set(vertices, polygon.length); + fd_polygon.density = 5.0; + fd_polygon.friction = 0.1; + fd_polygon.filter.categoryBits = 0x20; + fd_polygon.filter.maskBits = 0x000F; + MAIN_BODY_FIXTURES.push(fd_polygon); + } + + let LEG_FD = new b2.FixtureDef(); + LEG_FD.shape = new b2.PolygonShape(); + LEG_FD.shape.SetAsBox(this.LEG_W / 2, this.LEG_H / 2); + LEG_FD.density = 1.0; + LEG_FD.restitution = 0.0; + LEG_FD.filter.categoryBits = 0x20; + LEG_FD.filter.maskBits = 0x000F; + + let LOWER_FD = new b2.FixtureDef(); + LOWER_FD.shape = new b2.PolygonShape(); + LOWER_FD.shape.SetAsBox(0.8 * this.LEG_W / 2, this.LEG_H / 2); + LOWER_FD.density = 1.0; + LOWER_FD.restitution = 0.0; + LOWER_FD.filter.categoryBits = 0x20; + LOWER_FD.filter.maskBits = 0x000F; + + /* Creates the different bodies */ + + // Main body + let main_body_bd = new b2.BodyDef(); + main_body_bd.type = b2.Body.b2_dynamicBody; + main_body_bd.position.Set(init_x, init_y); + let main_body = world.CreateBody(main_body_bd); + for(let fd of MAIN_BODY_FIXTURES){ + main_body.CreateFixture(fd); + } + main_body.color1 = "#803366"; // [0.5, 0.2, 0.4] + main_body.color2 = "#4D1A33"; // [0.3, 0.1, 0.2] + main_body.ApplyForceToCenter(new b2.Vec2(force_to_center, 0), true); + main_body.SetUserData(new CustomBodyUserData(true, this.reset_on_hull_critical_contact, "main_body")); + this.body_parts.push(main_body); + this.reference_head_object = main_body; + + // Legs bodies and joints + let legs_coef = []; + for(let i = 0; i < this.nb_pairs_of_legs; i++){ + legs_coef.push(+1, -1); + } + for(let i of legs_coef){ + + // First part of the leg + let upper_leg_angle = 0.25 * Math.PI * i; + let upper_leg_x_distance = Math.sin(upper_leg_angle) * this.LEG_H / 2; + let upper_leg_y_distance = Math.cos(upper_leg_angle) * this.LEG_H / 2; + let upper_leg_x = init_x - i * MAIN_BODY_BOTTOM_WIDTH / this.SCALE / 2 - upper_leg_x_distance; + let upper_leg_y = init_y + upper_leg_y_distance - this.LEG_DOWN; + + let upper_leg_bd = new b2.BodyDef(); + upper_leg_bd.type = b2.Body.b2_dynamicBody; + upper_leg_bd.position.Set(upper_leg_x, upper_leg_y); + upper_leg_bd.angle = upper_leg_angle; + let upper_leg = world.CreateBody(upper_leg_bd); + upper_leg.CreateFixture(LEG_FD); + upper_leg.color1 = "#B36699"; // [0.7, 0.4, 0.6] + upper_leg.color2 = "#804D66"; // [0.5, 0.3, 0.4] + upper_leg.SetUserData(new CustomBodyUserData(false, false,"upper_leg")); + this.body_parts.push(upper_leg); + + // Upper leg joint motor + let upper_leg_rjd = new b2.RevoluteJointDef(); + upper_leg_rjd.Initialize(main_body, upper_leg, new b2.Vec2(init_x - i * MAIN_BODY_BOTTOM_WIDTH / this.SCALE / 2, init_y - this.LEG_DOWN)); + upper_leg_rjd.enableMotor = true; + upper_leg_rjd.enableLimit = true; + upper_leg_rjd.maxMotorTorque = this.MOTORS_TORQUE; + upper_leg_rjd.motorSpeed = 1; + upper_leg_rjd.lowerAngle = - 0.1 * Math.PI; + upper_leg_rjd.upperAngle = 0.1 * Math.PI; + let joint_motor = world.CreateJoint(upper_leg_rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", SPIDER_SPEED_HIP, false)); + this.motors.push(joint_motor); + + // Second part of the leg + let middle_leg_angle = 0.7 * Math.PI * i; + let middle_leg_x_distance = Math.sin(middle_leg_angle) * this.LEG_H / 2; + let middle_leg_y_distance = - Math.cos(middle_leg_angle) * this.LEG_H / 2; + let middle_leg_x = upper_leg_x - upper_leg_x_distance - middle_leg_x_distance; + let middle_leg_y = upper_leg_y + upper_leg_y_distance - middle_leg_y_distance; + + let middle_leg_bd = new b2.BodyDef(); + middle_leg_bd.type = b2.Body.b2_dynamicBody; + middle_leg_bd.position.Set(middle_leg_x, middle_leg_y); + middle_leg_bd.angle = middle_leg_angle; + let middle_leg = world.CreateBody(middle_leg_bd); + middle_leg.CreateFixture(LEG_FD); + middle_leg.color1 = "#B36699"; // [0.7, 0.4, 0.6] + middle_leg.color2 = "#804D66"; // [0.5, 0.3, 0.4] + middle_leg.SetUserData(new CustomBodyUserData(false, false,"middle_leg")); + this.body_parts.push(middle_leg); + + // middle_leg joint motor + let middle_leg_rjd = new b2.RevoluteJointDef(); + middle_leg_rjd.Initialize(upper_leg, middle_leg, new b2.Vec2(upper_leg_x - upper_leg_x_distance, upper_leg_y + upper_leg_y_distance)); + middle_leg_rjd.enableMotor = true; + middle_leg_rjd.enableLimit = true; + middle_leg_rjd.maxMotorTorque = this.MOTORS_TORQUE; + middle_leg_rjd.motorSpeed = 1; + middle_leg_rjd.lowerAngle = - 0.15 * Math.PI; + middle_leg_rjd.upperAngle = 0.15 * Math.PI; + joint_motor = world.CreateJoint(middle_leg_rjd); + joint_motor.SetUserData(new CustomMotorUserData("hip", SPIDER_SPEED_HIP,false)); + this.motors.push(joint_motor); + + // Third part of the leg + let lower_leg_angle = 0.9 * Math.PI * i; + let lower_leg_x_distance = Math.sin(lower_leg_angle) * this.LEG_H / 2; + let lower_leg_y_distance = - Math.cos(lower_leg_angle) * this.LEG_H / 2; + let lower_leg_x = middle_leg_x - middle_leg_x_distance - lower_leg_x_distance; + let lower_leg_y = middle_leg_y - middle_leg_y_distance - lower_leg_y_distance; + + let lower_leg_bd = new b2.BodyDef(); + lower_leg_bd.type = b2.Body.b2_dynamicBody; + lower_leg_bd.position.Set(lower_leg_x, lower_leg_y); + lower_leg_bd.angle = lower_leg_angle; + let lower_leg = world.CreateBody(lower_leg_bd); + lower_leg.CreateFixture(LOWER_FD); + lower_leg.color1 = "#B36699"; // [0.7, 0.4, 0.6] + lower_leg.color2 = "#804D66"; // [0.5, 0.3, 0.4] + lower_leg.SetUserData(new CustomBodyUserData(true, false,"lower_leg")); + this.body_parts.push(lower_leg); + + // lower_leg joint motor + let lower_leg_rjd = new b2.RevoluteJointDef(); + lower_leg_rjd.Initialize(middle_leg, lower_leg, new b2.Vec2(middle_leg_x - middle_leg_x_distance, middle_leg_y - middle_leg_y_distance)); + lower_leg_rjd.enableMotor = true; + lower_leg_rjd.enableLimit = true; + lower_leg_rjd.maxMotorTorque = this.MOTORS_TORQUE; + lower_leg_rjd.motorSpeed = 1; + lower_leg_rjd.lowerAngle = - 0.2 * Math.PI; + lower_leg_rjd.upperAngle = 0.2 * Math.PI; + joint_motor = world.CreateJoint(lower_leg_rjd); + joint_motor.SetUserData(new CustomMotorUserData("knee", SPIDER_SPEED_KNEE,true, 0.0, lower_leg)); + this.motors.push(joint_motor); + } + } +}; \ No newline at end of file diff --git a/js/bodies/walkers/walker_abstract_body.js b/js/bodies/walkers/walker_abstract_body.js new file mode 100644 index 0000000000000000000000000000000000000000..6ae12640f34b30156ceac8c06c22d351d55820f1 --- /dev/null +++ b/js/bodies/walkers/walker_abstract_body.js @@ -0,0 +1,16 @@ +/** + * @classdesc Abstract class for walker morphologies. + */ +class WalkerAbstractBody extends AbstractBody{ + /** + * @constructor + * @param scale {number} - Scale of the environment + * @param motors_torque {number} + * @param nb_steps_under_water {number} + */ + constructor(scale, motors_torque, nb_steps_under_water) { + super(scale, motors_torque); + this.body_type = BodyTypesEnum.WALKER; + this.nb_steps_can_survive_under_water = nb_steps_under_water; + } +} \ No newline at end of file diff --git a/js/box2d.js b/js/box2d.js new file mode 100644 index 0000000000000000000000000000000000000000..b4a2f283f700fb7c91d828806a0dcfdef87ba43c --- /dev/null +++ b/js/box2d.js @@ -0,0 +1,11581 @@ +/** https://github.com/kripken/box2d.js v2.3.1 */ + +var performance = { + now: function () { + return +new Date() + } +} +Function.prototype._extend = function (parent) { + this.prototype.parent = parent; + for (var x in parent.prototype) { + if (!this.prototype[x]) { + this.prototype[x] = parent.prototype[x] + } + } +}; +Function.prototype._implement = function (parent) { + return this._extend(parent) +}; +var b2Profiler = (function () { + + function profileStruct(name, parent) { + this.name = name; + this.parent = parent; + this.children = {}; + this.startTime = 0; + this.elapsedTime = 0; + this.totalTime = 0; + this.running = false; + this.childrenCount = 0 + } + profileStruct.prototype = { + start: function () { + this.startTime = performance.now(); + this.running = true + }, + stop: function (reset) { + if (!this.running) { + return + } + this.running = false; + this.elapsedTime += performance.now() - this.startTime; + if (reset) { + this.start() + } + for (var x in this.children) { + this.children[x].stop() + } + }, + reset: function (dontRun) { + if (!dontRun) { + this.running = true; + this.totalTime += this.elapsedTime; + this.start() + } + this.elapsedTime = 0; + for (var x in this.children) { + this.children[x].reset(true) + } + } + }; + var profiles = []; + var root = new profileStruct("root"); + + function create(name, parent) { + if (!profiles) { + throw new Error("late profile creation not allowed") + } + var s = new profileStruct(name, parent || "root"); + profiles.push(s); + return s + } + + function destroy(profile) { + profile.childrenCount--; + delete profile.children[profile.name] + } + + function recursiveParentCheck(node, profile) { + if (node.name === profile.parent) { + return node + } + for (var x in node.children) { + var n; + if (n = recursiveParentCheck(node.children[x], profile)) { + return n + } + } + return null + } + + function init() { + while (profiles.length) { + var p = profiles.pop(); + if (!(p.parentNode = recursiveParentCheck(root, p))) { + profiles.unshift(p) + } else { + p.parentNode.children[p.name] = p; + p.parentNode.childrenCount++ + } + } + profiles = null + } + + function resetAll() { + root.reset(true) + } + return { + create: create, + destroy: destroy, + init: init, + reset: resetAll, + profileRoot: root + } +}()); +"use strict"; +var b2_maxFloat = Number.MAX_VALUE; +var b2_epsilon = 2.220446049250313e-16; +var b2_pi = Math.PI; +var b2_maxManifoldPoints = 2; +var b2_maxPolygonVertices = 8; +var b2_aabbExtension = 0.1; +var b2_aabbMultiplier = 2; +var b2_linearSlop = 0.005; +var b2_angularSlop = (2 / 180 * b2_pi); +var b2_polygonRadius = (2 * b2_linearSlop); +var b2_maxSubSteps = 8; +var b2_maxTOIContacts = 32; +var b2_velocityThreshold = 1; +var b2_maxLinearCorrection = 0.2; +var b2_maxAngularCorrection = (8 / 180 * b2_pi); +var b2_maxTranslation = 2; +var b2_maxTranslationSquared = (b2_maxTranslation * b2_maxTranslation); +var b2_maxRotation = (0.5 * b2_pi); +var b2_maxRotationSquared = (b2_maxRotation * b2_maxRotation); +var b2_baumgarte = 0.2; +var b2_toiBaugarte = 0.75; +var b2_timeToSleep = 0.5; +var b2_linearSleepTolerance = 0.01; +var b2_angularSleepTolerance = (2 / 180 * b2_pi); + +function b2Version(ma, mi, re) { + this.major = ma; + this.minor = mi; + this.revision = re +} +b2Version.prototype = { + toString: function () { + return this.major + "." + this.minor + "." + this.revision + } +}; +var b2_version = new b2Version(2, 3, 1); +"use strict"; + +function b2IsValid(x) { + return isFinite(x) && !isNaN(x) +} +var sqrtf = Math.sqrt; +var atan2f = Math.atan2; +var sinf = Math.sin; +var cosf = Math.cos; +var floorf = Math.floor; +var ceilf = Math.ceil; +var b2Sqrt = sqrtf; +var b2Atan2 = atan2f; + +function b2InvSqrt(x) { + return 1 / sqrtf(x) +} + +function b2Vec2(x, y) { + if (typeof (x) !== "undefined") { + this.x = x; + this.y = y + } else { + this.x = this.y = 0 + } +} +b2Vec2.prototype = { + Clone: function () { + return new b2Vec2(this.x, this.y) + }, + SetZero: function () { + this.x = 0; + this.y = 0; + return this + }, + Set: function (x_, y_) { + this.x = x_; + this.y = y_; + return this + }, + Assign: function (l) { + this.x = l.x; + this.y = l.y; + return this + }, + Negate: function () { + var v = new b2Vec2(); + v.Set(-this.x, -this.y); + return v + }, + get_i: function (i) { + switch (i) { + case 0: + return this.x; + case 1: + return this.y + } + }, + set_i: function (i, v) { + switch (i) { + case 0: + return this.x = v; + case 1: + return this.y = v + } + }, + Add: function (v) { + this.x += v.x; + this.y += v.y; + return this + }, + Subtract: function (v) { + this.x -= v.x; + this.y -= v.y; + return this + }, + Multiply: function (a) { + this.x *= a; + this.y *= a; + return this + }, + Length: function () { + return b2Sqrt(this.x * this.x + this.y * this.y) + }, + LengthSquared: function () { + return this.x * this.x + this.y * this.y + }, + Normalize: function () { + var length = this.Length(); + if (length < b2_epsilon) { + return 0 + } + var invLength = 1 / length; + this.x *= invLength; + this.y *= invLength; + return length + }, + IsValid: function () { + return b2IsValid(this.x) && b2IsValid(this.y) + }, + Skew: function () { + return new b2Vec2(-this.y, this.x) + }, + _serialize: function (out) { + var obj = out || []; + obj[0] = this.x; + obj[1] = this.y; + return obj + }, + _deserialize: function (data) { + this.x = data[0]; + this.y = data[1] + } +}; +b2Vec2.Add = function (a, b) { + return new b2Vec2(a.x + b.x, a.y + b.y) +}; +b2Vec2.Subtract = function (a, b) { + return new b2Vec2(a.x - b.x, a.y - b.y) +}; +b2Vec2.Equals = function (a, b) { + return a.x == b.x && a.y == b.y +}; +b2Vec2.Multiply = function (s, a) { + return new b2Vec2(s * a.x, s * a.y) +}; +b2Vec2.Negate = function (a) { + return new b2Vec2(-a.x, -a.y) +}; + +function b2Vec3(x, y, z) { + if (typeof (x) !== "undefined") { + this.x = x; + this.y = y; + this.z = z + } +} +b2Vec3.prototype = { + Clone: function () { + return new b2Vec3(this.x, this.y, this.z) + }, + SetZero: function () { + this.x = 0; + this.y = 0; + this.z = 0 + }, + Set: function (x_, y_, z_) { + this.x = x_; + this.y = y_; + this.z = z_ + }, + Negate: function () { + var v = new b2Vec3(); + v.Set(-this.x, -this.y, -this.z); + return v + }, + Add: function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z + }, + Subtract: function (v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z + }, + Multiply: function (s) { + this.x *= s; + this.y *= s; + this.z *= s + }, + x: 0, + y: 0, + z: 0 +}; +b2Vec3.Multiply = function (s, a) { + return new b2Vec3(s * a.x, s * a.y, s * a.z) +}; +b2Vec3.Add = function (a, b) { + return new b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z) +}; +b2Vec3.Subtract = function (a, b) { + return new b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z) +}; + +function b2Mat22(c1, c2) { + this.ex = c1 ? c1.Clone() : new b2Vec2(); + this.ey = c2 ? c2.Clone() : new b2Vec2() +} +b2Mat22.prototype = { + Set: function (c1, c2) { + this.ex.Assign(c1); + this.ey.Assign(c2) + }, + Assign: function (mat) { + this.ex.Assign(mat.ex); + this.ey.Assign(mat.ey) + }, + SetIdentity: function () { + this.ex.x = 1; + this.ey.x = 0; + this.ex.y = 0; + this.ey.y = 1 + }, + SetZero: function () { + this.ex.x = 0; + this.ey.x = 0; + this.ex.y = 0; + this.ey.y = 0 + }, + GetInverse: function () { + var a = this.ex.x, + b = this.ey.x, + c = this.ex.y, + d = this.ey.y; + var B = new b2Mat22(); + var det = a * d - b * c; + if (det != 0) { + det = 1 / det + } + B.ex.x = det * d; + B.ey.x = -det * b; + B.ex.y = -det * c; + B.ey.y = det * a; + return B + }, + Solve: function (b) { + var a11 = this.ex.x, + a12 = this.ey.x, + a21 = this.ex.y, + a22 = this.ey.y; + var det = a11 * a22 - a12 * a21; + if (det != 0) { + det = 1 / det + } + var x = new b2Vec2(); + x.x = det * (a22 * b.x - a12 * b.y); + x.y = det * (a11 * b.y - a21 * b.x); + return x + } +}; +b2Mat22.Add = function (A, B) { + return new b2Mat22(b2Vec2.Add(A.ex, B.ex), b2Vec2.Add(A.ey, B.ey)) +}; + +function b2Mat33(c1, c2, c3) { + this.ex = c1 ? c1.Clone() : new b2Vec3(); + this.ey = c2 ? c2.Clone() : new b2Vec3(); + this.ez = c3 ? c3.Clone() : new b2Vec3() +} +b2Mat33.prototype = { + SetZero: function () { + this.ex.SetZero(); + this.ey.SetZero(); + this.ez.SetZero() + }, + Solve33: function (b) { + var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); + if (det != 0) { + det = 1 / det + } + var x = new b2Vec3(); + x.x = det * b2Dot_v3_v3(b, b2Cross_v3_v3(this.ey, this.ez)); + x.y = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(b, this.ez)); + x.z = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, b)); + return x + }, + Solve22: function (b) { + var a11 = this.ex.x, + a12 = this.ey.x, + a21 = this.ex.y, + a22 = this.ey.y; + var det = a11 * a22 - a12 * a21; + if (det != 0) { + det = 1 / det + } + var x = new b2Vec2(); + x.x = det * (a22 * b.x - a12 * b.y); + x.y = det * (a11 * b.y - a21 * b.x); + return x + }, + GetInverse22: function (M) { + var a = this.ex.x, + b = this.ey.x, + c = this.ex.y, + d = this.ey.y; + var det = a * d - b * c; + if (det != 0) { + det = 1 / det + } + M.ex.x = det * d; + M.ey.x = -det * b; + M.ex.z = 0; + M.ex.y = -det * c; + M.ey.y = det * a; + M.ey.z = 0; + M.ez.x = 0; + M.ez.y = 0; + M.ez.z = 0 + }, + GetSymInverse33: function (M) { + var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); + if (det != 0) { + det = 1 / det + } + var a11 = this.ex.x, + a12 = this.ey.x, + a13 = this.ez.x; + var a22 = this.ey.y, + a23 = this.ez.y; + var a33 = this.ez.z; + M.ex.x = det * (a22 * a33 - a23 * a23); + M.ex.y = det * (a13 * a23 - a12 * a33); + M.ex.z = det * (a12 * a23 - a13 * a22); + M.ey.x = M.ex.y; + M.ey.y = det * (a11 * a33 - a13 * a13); + M.ey.z = det * (a13 * a12 - a11 * a23); + M.ez.x = M.ex.z; + M.ez.y = M.ey.z; + M.ez.z = det * (a11 * a22 - a12 * a12) + } +}; + +function b2Rot(angle, c) { + if (typeof (c) !== "undefined") { + this.s = angle; + this.c = c + } else { + if (typeof (angle) !== "undefined") { + this.Set(angle) + } + } +} +b2Rot.prototype = { + Clone: function () { + return new b2Rot(this.s, this.c) + }, + Assign: function (l) { + this.s = l.s; + this.c = l.c + }, + Set: function (x) { + this.s = sinf(x); + this.c = cosf(x) + }, + SetIdentity: function () { + this.s = 0; + this.c = 1 + }, + GetAngle: function () { + return b2Atan2(this.s, this.c) + }, + GetXAxis: function () { + return new b2Vec2(this.c, this.s) + }, + GetYAxis: function () { + return new b2Vec2(-this.s, this.c) + }, + s: 0, + c: 1 +}; + +function b2Transform(position, rotation) { + this.p = new b2Vec2(); + this.q = new b2Rot(); + if (position) { + this.p.Assign(position); + this.q.Assign(rotation) + } +} +b2Transform.prototype = { + Clone: function () { + var xf = new b2Transform(this.p, this.q); + return xf + }, + Assign: function (xf) { + this.p.Assign(xf.p); + this.q.Assign(xf.q) + }, + SetIdentity: function () { + this.p.SetZero(); + this.q.SetIdentity() + }, + Set: function (position, angle) { + this.p.Assign(position); + this.q.Set(angle) + } +}; + +function b2Sweep() { + this.localCenter = new b2Vec2(); + this.c0 = new b2Vec2(); + this.c = new b2Vec2() +} +b2Sweep.prototype = { + Assign: function (sweep) { + this.localCenter.Assign(sweep.localCenter); + this.c0.Assign(sweep.c0); + this.c.Assign(sweep.c); + this.a = sweep.a; + this.a0 = sweep.a0; + this.alpha0 = sweep.alpha0 + }, + Clone: function () { + var sweep = new b2Sweep(); + sweep.localCenter.Assign(this.localCenter); + sweep.c0.Assign(this.c0); + sweep.c.Assign(this.c); + sweep.a = this.a; + sweep.a0 = this.a0; + sweep.alpha0 = this.alpha0; + return sweep + }, + GetTransform: function (xf, beta) { + xf.p.x = ((1 - beta) * this.c0.x) + (beta * this.c.x); + xf.p.y = ((1 - beta) * this.c0.y) + (beta * this.c.y); + var angle = (1 - beta) * this.a0 + beta * this.a; + xf.q.Set(angle); + xf.p.x -= xf.q.c * this.localCenter.x - xf.q.s * this.localCenter.y; + xf.p.y -= xf.q.s * this.localCenter.x + xf.q.c * this.localCenter.y + }, + Advance: function (alpha) { + var beta = (alpha - this.alpha0) / (1 - this.alpha0); + this.c0.Add(b2Vec2.Multiply(beta, b2Vec2.Subtract(this.c, this.c0))); + this.a0 += beta * (this.a - this.a0); + this.alpha0 = alpha + }, + Normalize: function () { + var twoPi = 2 * b2_pi; + var d = twoPi * floorf(this.a0 / twoPi); + this.a0 -= d; + this.a -= d + }, + a0: 0, + a: 0, + alpha0: 0 +}; + +function b2Dot_v2_v2(a, b) { + return a.x * b.x + a.y * b.y +} + +function b2Cross_v2_v2(a, b) { + return a.x * b.y - a.y * b.x +} + +function b2Cross_v2_f(a, s) { + return new b2Vec2(s * a.y, -s * a.x) +} + +function b2Cross_f_v2(s, a) { + return new b2Vec2(-s * a.y, s * a.x) +} + +function b2Mul_m22_v2(A, v) { + return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) +} + +function b2MulT_m22_v2(A, v) { + return new b2Vec2(b2Dot_v2_v2(v, A.ex), b2Dot_v2_v2(v, A.ey)) +} + +function b2Distance(a, b) { + var c = b2Vec2.Subtract(a, b); + return c.Length() +} + +function b2DistanceSquared(a, b) { + var c = b2Vec2.Subtract(a, b); + return b2Dot_v2_v2(c, c) +} + +function b2Dot_v3_v3(a, b) { + return a.x * b.x + a.y * b.y + a.z * b.z +} + +function b2Cross_v3_v3(a, b) { + return new b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x) +} + +function b2Mul_m22_m22(A, B) { + return new b2Mat22(b2Mul_m22_v2(A, B.ex), b2Mul_m22_v2(A, B.ey)) +} + +function b2MulT_m22_m22(A, B) { + var c1 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ex), b2Dot_v2_v2(A.ey, B.ex)); + var c2 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ey), b2Dot_v2_v2(A.ey, B.ey)); + return new b2Mat22(c1, c2) +} + +function b2Mul_m33_v3(A, v) { + return b2Vec3.Add(b2Vec3.Add(b2Vec3.Multiply(v.x, A.ex), b2Vec3.Multiply(v.y, A.ey)), b2Vec3.Multiply(v.z, A.ez)) +} + +function b2Mul22_m33_v2(A, v) { + return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) +} + +function b2Mul_r_r(q, r) { + var qr = new b2Rot(); + qr.s = q.s * r.c + q.c * r.s; + qr.c = q.c * r.c - q.s * r.s; + return qr +} + +function b2MulT_r_r(q, r) { + var qr = new b2Rot(); + qr.s = q.c * r.s - q.s * r.c; + qr.c = q.c * r.c + q.s * r.s; + return qr +} + +function b2Mul_r_v2(q, v) { + return new b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y) +} + +function b2MulT_r_v2(q, v) { + return new b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y) +} + +function b2Mul_t_v2(T, v) { + return new b2Vec2((T.q.c * v.x - T.q.s * v.y) + T.p.x, (T.q.s * v.x + T.q.c * v.y) + T.p.y) +} + +function b2MulT_t_v2(T, v) { + var px = v.x - T.p.x; + var py = v.y - T.p.y; + var x = (T.q.c * px + T.q.s * py); + var y = (-T.q.s * px + T.q.c * py); + return new b2Vec2(x, y) +} + +function b2Mul_t_t(A, B) { + var C = new b2Transform(); + C.q = b2Mul_r_r(A.q, B.q); + C.p = b2Vec2.Add(b2Mul_r_v2(A.q, B.p), A.p); + return C +} + +function b2MulT_t_t(A, B) { + var C = new b2Transform(); + C.q = b2MulT_r_r(A.q, B.q); + var tvx = B.p.x - A.p.x; + var tvy = B.p.y - A.p.y; + C.p.x = A.q.c * tvx + A.q.s * tvy; + C.p.y = -A.q.s * tvx + A.q.c * tvy; + return C +} +var b2Abs = Math.abs; + +function b2Abs_v2(a) { + return new b2Vec2(b2Abs(a.x), b2Abs(a.y)) +} + +function b2Abs_m22(A) { + return new b2Mat22(b2Abs_v2(A.ex), b2Abs_v2(A.ey)) +} +var b2Min = Math.min; + +function b2Min_v2(a, b) { + return new b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)) +} +var b2Max = Math.max; + +function b2Max_v2(a, b) { + return new b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)) +} + +function b2Clamp(a, low, high) { + return b2Max(low, b2Min(a, high)) +} + +function b2Clamp_v2(a, low, high) { + return b2Max_v2(low, b2Min_v2(a, high)) +} + +function b2NextPowerOfTwo(x) { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x + 1 +} + +function b2IsPowerOfTwo(x) { + var result = x > 0 && (x & (x - 1)) == 0; + return result +} +var RAND_LIMIT = 32767; + +function b2RandomFloat(lo, hi) { + var r = Math.random(); + if (typeof (lo) !== "undefined") { + r = (hi - lo) * r + lo + } else { + r = 2 * r - 1 + } + return r +} +"use strict"; + +function b2Color(r, g, b) { + this.r = r || 0; + this.g = g || 0; + this.b = b || 0 +} +b2Color.prototype = { + Set: function (r, g, b) { + this.r = r; + this.g = g; + this.b = b + } +}; + +function b2Draw() {} +b2Draw.prototype = { + SetFlags: function (flags) { + this.m_drawFlags = flags + }, + GetFlags: function () { + return this.m_drawFlags + }, + AppendFlags: function (flags) { + this.m_drawFlags |= flags + }, + ClearFlags: function (flags) { + this.m_drawFlags &= ~flags + }, + ToggleFlags: function (flags) { + this.m_drawFlags ^= flags + }, + DrawPolygon: function (vertices, vertexCount, color) {}, + DrawSolidPolygon: function (vertices, vertexCount, color) {}, + DrawCircle: function (center, radius, color) {}, + DrawSolidCircle: function (center, radius, axis, color) {}, + DrawSegment: function (p1, p2, color) {}, + DrawTransform: function (xf) {}, + m_drawFlags: 0 +}; +b2Draw.e_shapeBit = 1; +b2Draw.e_jointBit = 2; +b2Draw.e_aabbBit = 4; +b2Draw.e_centerOfMassBit = 8; +b2Draw.e_contactPoints = 16; +b2Draw.e_contactNormals = 32; +b2Draw.e_contactImpulses = 64; +b2Draw.e_frictionImpulses = 128; +b2Draw.e_statistics = 256; +b2Draw.e_profile = 512; +b2Draw.e_pairBit = 1024; + +"use strict"; +function b2Timer() { + this.Reset() +} +b2Timer.prototype = { + Reset: function () { + this.m_start = performance.now() + }, + GetMilliseconds: function () { + return performance.now() - this.m_start + } +}; +"use strict"; + +function b2MassData() { + this.mass = 0; + this.center = new b2Vec2(); + this.I = 0 +} + +function b2Shape() { + this.m_type = 0; + this.m_radius = 0 +} +b2Shape.prototype = { + Clone: function () {}, + GetType: function () { + return this.m_type + }, + GetChildCount: function () {}, + TestPoint: function (xf, p) {}, + RayCast: function (output, input, transform, childIndex) {}, + ComputeAABB: function (aabb, xf, childIndex) {}, + ComputeMass: function (massData, density) {}, + _serialize: function (out) { + var obj = out || {}; + obj.m_type = this.m_type; + obj.m_radius = this.m_radius; + return obj + }, + _deserialize: function (data) { + this.m_radius = data.m_radius + } +}; +b2Shape.e_circle = 0; +b2Shape.e_edge = 1; +b2Shape.e_polygon = 2; +b2Shape.e_chain = 3; +b2Shape.e_typeCount = 4; +"use strict"; + +function b2CircleShape() { + this.parent.call(this); + this.m_type = b2Shape.e_circle; + this.m_radius = 0; + this.m_p = new b2Vec2(); + Object.seal(this) +} +b2CircleShape.prototype = { + Clone: function () { + var shape = new b2CircleShape(); + shape.m_radius = this.m_radius; + shape.m_p = this.m_p.Clone(); + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + var center = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var d = b2Vec2.Subtract(p, center); + return b2Dot_v2_v2(d, d) <= this.m_radius * this.m_radius + }, + RayCast: function (output, input, transform, childIndex) { + var position = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var s = b2Vec2.Subtract(input.p1, position); + var b = b2Dot_v2_v2(s, s) - this.m_radius * this.m_radius; + var r = b2Vec2.Subtract(input.p2, input.p1); + var c = b2Dot_v2_v2(s, r); + var rr = b2Dot_v2_v2(r, r); + var sigma = c * c - rr * b; + if (sigma < 0 || rr < b2_epsilon) { + return false + } + var a = -(c + b2Sqrt(sigma)); + if (0 <= a && a <= input.maxFraction * rr) { + a /= rr; + output.fraction = a; + output.normal = b2Vec2.Add(s, b2Vec2.Multiply(a, r)); + output.normal.Normalize(); + return true + } + return false + }, + ComputeAABB: function (aabb, transform, childIndex) { + var px = transform.p.x + (transform.q.c * this.m_p.x - transform.q.s * this.m_p.y); + var py = transform.p.y + (transform.q.s * this.m_p.x + transform.q.c * this.m_p.y); + aabb.lowerBound.x = px - this.m_radius; + aabb.lowerBound.y = py - this.m_radius; + aabb.upperBound.x = px + this.m_radius; + aabb.upperBound.y = py + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = density * b2_pi * this.m_radius * this.m_radius; + massData.center = this.m_p; + massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + b2Dot_v2_v2(this.m_p, this.m_p)) + }, + GetSupport: function (d) { + return 0 + }, + GetSupportVertex: function (d) { + return this.m_p + }, + GetVertexCount: function () { + return 1 + }, + GetVertex: function (index) { + return this.m_p + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_p = this.m_p._serialize(); + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_p._deserialize(data.m_p) + } +}; +b2CircleShape._extend(b2Shape); +"use strict"; + +function b2EdgeShape() { + this.parent.call(this); + this.m_type = b2Shape.e_edge; + this.m_radius = b2_polygonRadius; + this.m_vertex0 = new b2Vec2(); + this.m_vertex1 = new b2Vec2(); + this.m_vertex2 = new b2Vec2(); + this.m_vertex3 = new b2Vec2(); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false; + Object.seal(this) +} +b2EdgeShape.prototype = { + Set: function (v1, v2) { + this.m_vertex1.Assign(v1); + this.m_vertex2.Assign(v2); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false + }, + Clone: function () { + var shape = new b2EdgeShape(); + shape.m_vertex0 = this.m_vertex0.Clone(); + shape.m_vertex1 = this.m_vertex1.Clone(); + shape.m_vertex2 = this.m_vertex2.Clone(); + shape.m_vertex3 = this.m_vertex3.Clone(); + shape.m_hasVertex0 = this.m_hasVertex0; + shape.m_hasVertex3 = this.m_hasVertex3; + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var v1 = this.m_vertex1; + var v2 = this.m_vertex2; + var e = b2Vec2.Subtract(v2, v1); + var normal = new b2Vec2(e.y, -e.x); + normal.Normalize(); + var numerator = b2Dot_v2_v2(normal, b2Vec2.Subtract(v1, p1)); + var denominator = b2Dot_v2_v2(normal, d); + if (denominator == 0) { + return false + } + var t = numerator / denominator; + if (t < 0 || input.maxFraction < t) { + return false + } + var q = b2Vec2.Add(p1, b2Vec2.Multiply(t, d)); + var r = b2Vec2.Subtract(v2, v1); + var rr = b2Dot_v2_v2(r, r); + if (rr == 0) { + return false + } + var s = b2Dot_v2_v2(b2Vec2.Subtract(q, v1), r) / rr; + if (s < 0 || 1 < s) { + return false + } + output.fraction = t; + if (numerator > 0) { + output.normal = b2Mul_r_v2(xf.q, normal).Negate() + } else { + output.normal = b2Mul_r_v2(xf.q, normal) + } + return true + }, + ComputeAABB: function (aabb, xf, childIndex) { + var v1x = (xf.q.c * this.m_vertex1.x - xf.q.s * this.m_vertex1.y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertex1.x + xf.q.c * this.m_vertex1.y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertex2.x - xf.q.s * this.m_vertex2.y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertex2.x + xf.q.c * this.m_vertex2.y) + xf.p.y; + var lowerx = b2Min(v1x, v2x); + var lowery = b2Min(v1y, v2y); + var upperx = b2Max(v1x, v2x); + var uppery = b2Max(v1y, v2y); + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center = b2Vec2.Multiply(0.5, b2Vec2.Add(this.m_vertex1, this.m_vertex2)); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_vertex1 = this.m_vertex1._serialize(); + obj.m_vertex2 = this.m_vertex2._serialize(); + obj.m_hasVertex0 = this.m_hasVertex0; + if (this.m_hasVertex0) { + obj.m_vertex0 = this.m_vertex0._serialize() + } + obj.m_hasVertex3 = this.m_hasVertex3; + if (this.m_hasVertex3) { + obj.m_vertex3 = this.m_vertex3._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_vertex1._deserialize(data.m_vertex1); + this.m_vertex2._deserialize(data.m_vertex2); + this.m_hasVertex0 = data.m_hasVertex0; + if (this.m_hasVertex0) { + this.m_vertex0._deserialize(data.m_vertex0) + } + this.m_hasVertex3 = data.m_hasVertex3; + if (this.m_hasVertex3) { + this.m_vertex3._deserialize(data.m_vertex3) + } + } +}; +b2EdgeShape._extend(b2Shape); +"use strict"; + +function b2ChainShape() { + this.parent.call(this); + this.m_type = b2Shape.e_chain; + this.m_radius = b2_polygonRadius; + this.m_vertices = null; + this.m_count = 0; + this.m_prevVertex = new b2Vec2(); + this.m_nextVertex = new b2Vec2(); + this.m_hasPrevVertex = false; + this.m_hasNextVertex = false; + Object.seal(this) +} +b2ChainShape.prototype = { + CreateLoop: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count + 1; + this.m_vertices = new Array(this.m_count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } + this.m_vertices[count] = this.m_vertices[0].Clone(); + this.m_prevVertex.Assign(this.m_vertices[this.m_count - 2]); + this.m_nextVertex.Assign(this.m_vertices[1]); + this.m_hasPrevVertex = true; + this.m_hasNextVertex = true + }, + CreateChain: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count; + this.m_vertices = new Array(count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } + this.m_hasPrevVertex = false; + this.m_hasNextVertex = false; + this.m_prevVertex.SetZero(); + this.m_nextVertex.SetZero() + }, + SetPrevVertex: function (prevVertex) { + this.m_prevVertex.Assign(prevVertex); + this.m_hasPrevVertex = true + }, + SetNextVertex: function (nextVertex) { + this.m_nextVertex.Assign(nextVertex); + this.m_hasNextVertex = true + }, + Clone: function () { + var shape = new b2ChainShape(); + shape.m_count = this.m_count; + shape.m_vertices = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone() + } + shape.m_prevVertex = this.m_prevVertex.Clone(); + shape.m_nextVertex = this.m_nextVertex.Clone(); + shape.m_hasPrevVertex = this.m_hasPrevVertex; + shape.m_hasNextVertex = this.m_hasNextVertex; + return shape + }, + GetChildCount: function () { + return this.m_count - 1 + }, + GetChildEdge: function (edge, index) { + edge.m_type = b2Shape.e_edge; + edge.m_radius = this.m_radius; + edge.m_vertex1 = this.m_vertices[index + 0]; + edge.m_vertex2 = this.m_vertices[index + 1]; + if (index > 0) { + edge.m_vertex0 = this.m_vertices[index - 1]; + edge.m_hasVertex0 = true + } else { + edge.m_vertex0 = this.m_prevVertex; + edge.m_hasVertex0 = this.m_hasPrevVertex + } + if (index < this.m_count - 2) { + edge.m_vertex3 = this.m_vertices[index + 2]; + edge.m_hasVertex3 = true + } else { + edge.m_vertex3 = this.m_nextVertex; + edge.m_hasVertex3 = this.m_hasNextVertex + } + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var edgeShape = new b2EdgeShape(); + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + edgeShape.m_vertex1 = this.m_vertices[i1].Clone(); + edgeShape.m_vertex2 = this.m_vertices[i2].Clone(); + return edgeShape.RayCast(output, input, xf, 0) + }, + ComputeAABB: function (aabb, xf, childIndex) { + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + var v1x = (xf.q.c * this.m_vertices[i1].x - xf.q.s * this.m_vertices[i1].y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertices[i1].x + xf.q.c * this.m_vertices[i1].y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertices[i2].x - xf.q.s * this.m_vertices[i2].y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertices[i2].x + xf.q.c * this.m_vertices[i2].y) + xf.p.y; + aabb.lowerBound.x = b2Min(v1x, v2x); + aabb.lowerBound.y = b2Min(v1y, v2y); + aabb.upperBound.x = b2Max(v1x, v2x); + aabb.upperBound.y = b2Max(v1y, v2y) + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center.SetZero(); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()) + } + obj.m_hasPrevVertex = this.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + obj.m_prevVertex = this.m_prevVertex._serialize() + } + obj.m_hasNextVertex = this.m_hasNextVertex; + if (this.m_hasNextVertex) { + obj.m_nextVertex = this.m_nextVertex._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]) + } + this.m_hasPrevVertex = data.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + this.m_prevVertex._deserialize(data.m_prevVertex) + } + this.m_hasNextVertex = data.m_hasNextVertex; + if (this.m_hasNextVertex) { + this.m_nextVertex._deserialize(data.m_nextVertex) + } + } +}; +b2ChainShape._extend(b2Shape); +"use strict"; + +function b2PolygonShape() { + this.parent.call(this); + this.m_type = b2Shape.e_polygon; + this.m_radius = b2_polygonRadius; + this.m_count = 0; + this.m_centroid = new b2Vec2(); + this.m_vertices = new Array(b2_maxPolygonVertices); + this.m_normals = new Array(b2_maxPolygonVertices); + Object.seal(this) +} +b2PolygonShape.prototype = { + Clone: function () { + var shape = new b2PolygonShape(); + shape.m_count = this.m_count; + shape.m_centroid = this.m_centroid.Clone(); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone(); + shape.m_normals[i] = this.m_normals[i].Clone() + } + return shape + }, + GetChildCount: function () { + return 1 + }, + Set: function (vertices, count) { + if (count < 3) { + this.SetAsBox(1, 1); + return + } + var n = b2Min(count, b2_maxPolygonVertices); + var ps = new Array(b2_maxPolygonVertices); + var tempCount = 0; + for (var i = 0; i < n; ++i) { + var v = vertices[i]; + var unique = true; + for (var j = 0; j < tempCount; ++j) { + if (b2DistanceSquared(v, ps[j]) < 0.5 * b2_linearSlop) { + unique = false; + break + } + } + if (unique) { + ps[tempCount++] = v.Clone() + } + } + n = tempCount; + if (n < 3) { + this.SetAsBox(1, 1); + return + } + var i0 = 0; + var x0 = ps[0].x; + for (i = 1; i < n; ++i) { + var x = ps[i].x; + if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) { + i0 = i; + x0 = x + } + } + var hull = new Array(b2_maxPolygonVertices); + var m = 0; + var ih = i0; + for (;;) { + hull[m] = ih; + var ie = 0; + for (j = 1; j < n; ++j) { + if (ie == ih) { + ie = j; + continue + } + var r = b2Vec2.Subtract(ps[ie], ps[hull[m]]); + var v = b2Vec2.Subtract(ps[j], ps[hull[m]]); + var c = b2Cross_v2_v2(r, v); + if (c < 0) { + ie = j + } + if (c == 0 && v.LengthSquared() > r.LengthSquared()) { + ie = j + } + }++m; + ih = ie; + if (ie == i0) { + break + } + } + this.m_count = m; + for (i = 0; i < m; ++i) { + this.m_vertices[i] = ps[hull[i]].Clone() + } + for (i = 0; i < m; ++i) { + var i1 = i; + var i2 = i + 1 < m ? i + 1 : 0; + var edge = b2Vec2.Subtract(this.m_vertices[i2], this.m_vertices[i1]); + this.m_normals[i] = b2Cross_v2_f(edge, 1).Clone(); + this.m_normals[i].Normalize() + } + this.m_centroid = b2PolygonShape.ComputeCentroid(this.m_vertices, m) + }, + SetAsBox: function (hx, hy, center, angle) { + this.m_count = 4; + this.m_vertices[0] = new b2Vec2(-hx, -hy); + this.m_vertices[1] = new b2Vec2(hx, -hy); + this.m_vertices[2] = new b2Vec2(hx, hy); + this.m_vertices[3] = new b2Vec2(-hx, hy); + this.m_normals[0] = new b2Vec2(0, -1); + this.m_normals[1] = new b2Vec2(1, 0); + this.m_normals[2] = new b2Vec2(0, 1); + this.m_normals[3] = new b2Vec2(-1, 0); + if (!center) { + return + } + this.m_centroid.Assign(center); + var xf = new b2Transform(); + xf.p = center; + xf.q.Set(angle); + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i].Assign(b2Mul_t_v2(xf, this.m_vertices[i])); + this.m_normals[i].Assign(b2Mul_r_v2(xf.q, this.m_normals[i])) + } + }, + TestPoint: function (xf, p) { + var pLocal = b2MulT_r_v2(xf.q, b2Vec2.Subtract(p, xf.p)); + for (var i = 0; i < this.m_count; ++i) { + var dot = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(pLocal, this.m_vertices[i])); + if (dot > 0) { + return false + } + } + return true + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var lower = 0, + upper = input.maxFraction; + var index = -1; + for (var i = 0; i < this.m_count; ++i) { + var numerator = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(this.m_vertices[i], p1)); + var denominator = b2Dot_v2_v2(this.m_normals[i], d); + if (denominator == 0) { + if (numerator < 0) { + return false + } + } else { + if (denominator < 0 && numerator < lower * denominator) { + lower = numerator / denominator; + index = i + } else { + if (denominator > 0 && numerator < upper * denominator) { + upper = numerator / denominator + } + } + } + if (upper < lower) { + return false + } + } + if (index >= 0) { + output.fraction = lower; + output.normal = b2Mul_r_v2(xf.q, this.m_normals[index]); + return true + } + return false + }, + ComputeAABB: function (aabb, xf, childIndex) { + var lowerx = (xf.q.c * this.m_vertices[0].x - xf.q.s * this.m_vertices[0].y) + xf.p.x; + var lowery = (xf.q.s * this.m_vertices[0].x + xf.q.c * this.m_vertices[0].y) + xf.p.y; + var upperx = lowerx; + var uppery = lowery; + for (var i = 1; i < this.m_count; ++i) { + var vx = (xf.q.c * this.m_vertices[i].x - xf.q.s * this.m_vertices[i].y) + xf.p.x; + var vy = (xf.q.s * this.m_vertices[i].x + xf.q.c * this.m_vertices[i].y) + xf.p.y; + lowerx = b2Min(lowerx, vx); + lowery = b2Min(lowery, vy); + upperx = b2Max(upperx, vx); + uppery = b2Max(uppery, vy) + } + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + var center = new b2Vec2(0, 0); + var area = 0; + var I = 0; + var s = new b2Vec2(0, 0); + for (var i = 0; i < this.m_count; ++i) { + s.Add(this.m_vertices[i]) + } + s.Multiply(1 / this.m_count); + var k_inv3 = 1 / 3; + for (var i = 0; i < this.m_count; ++i) { + var e1 = b2Vec2.Subtract(this.m_vertices[i], s); + var e2 = i + 1 < this.m_count ? b2Vec2.Subtract(this.m_vertices[i + 1], s) : b2Vec2.Subtract(this.m_vertices[0], s); + var D = b2Cross_v2_v2(e1, e2); + var triangleArea = 0.5 * D; + area += triangleArea; + center.Add(b2Vec2.Multiply(triangleArea * k_inv3, b2Vec2.Add(e1, e2))); + var ex1 = e1.x, + ey1 = e1.y; + var ex2 = e2.x, + ey2 = e2.y; + var intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2; + var inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2; + I += (0.25 * k_inv3 * D) * (intx2 + inty2) + } + massData.mass = density * area; + center.Multiply(1 / area); + massData.center = b2Vec2.Add(center, s); + massData.I = density * I; + massData.I += massData.mass * (b2Dot_v2_v2(massData.center, massData.center) - b2Dot_v2_v2(center, center)) + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + }, + Validate: function () { + for (var i = 0; i < this.m_count; ++i) { + var i1 = i; + var i2 = i < this.m_count - 1 ? i1 + 1 : 0; + var p = this.m_vertices[i1]; + var e = b2Vec2.Subtract(this.m_vertices[i2], p); + for (var j = 0; j < this.m_count; ++j) { + if (j == i1 || j == i2) { + continue + } + var v = b2Vec2.Subtract(this.m_vertices[j], p); + var c = b2Cross_v2_v2(e, v); + if (c < 0) { + return false + } + } + } + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_centroid = this.m_centroid._serialize(); + obj.m_vertices = []; + obj.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()); + obj.m_normals.push(this.m_normals[i]._serialize()) + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_centroid._deserialize(data.m_centroid); + this.m_vertices = []; + this.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]); + this.m_normals[i] = new b2Vec2(); + this.m_normals[i]._deserialize(data.m_normals[i]) + } + } +}; +b2PolygonShape.ComputeCentroid = function (vs, count) { + var c = new b2Vec2(); + var area = 0; + var pRef = new b2Vec2(0, 0); + var inv3 = 1 / 3; + for (var i = 0; i < count; ++i) { + var p1 = pRef; + var p2 = vs[i]; + var p3 = i + 1 < count ? vs[i + 1] : vs[0]; + var e1 = b2Vec2.Subtract(p2, p1); + var e2 = b2Vec2.Subtract(p3, p1); + var D = b2Cross_v2_v2(e1, e2); + var triangleArea = 0.5 * D; + area += triangleArea; + c.Add(b2Vec2.Multiply(triangleArea, b2Vec2.Multiply(inv3, b2Vec2.Add(b2Vec2.Add(p1, p2), p3)))) + } + c.Multiply(1 / area); + return c +}; +b2PolygonShape._extend(b2Shape); +"use strict"; + +function b2Pair() { + this.proxyIdA = 0; + this.proxyIdB = 0 +} + +function b2PairLessThan(pair1, pair2) { + if (pair1.proxyIdA == pair2.proxyIdA) { + return pair1.proxyIdB - pair2.proxyIdB + } + return pair1.proxyIdA - pair2.proxyIdA +} + +function b2BroadPhase() { + this.m_tree = new b2DynamicTree(); + this.m_queryProxyId = 0; + this.m_proxyCount = 0; + this.m_pairCount = 0; + this.m_pairBuffer = []; + this.m_moveCount = 0; + this.m_moveBuffer = [] +} +b2BroadPhase.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.m_tree.CreateProxy(aabb, userData); + ++this.m_proxyCount; + this.BufferMove(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.UnBufferMove(proxyId); + --this.m_proxyCount; + this.m_tree.DestroyProxy(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + var buffer = this.m_tree.MoveProxy(proxyId, aabb, displacement); + if (buffer) { + this.BufferMove(proxyId) + } + }, + TouchProxy: function (proxyId) { + this.BufferMove(proxyId) + }, + GetFatAABB: function (proxyId) { + return this.m_tree.GetFatAABB(proxyId) + }, + GetUserData: function (proxyId) { + return this.m_tree.GetUserData(proxyId) + }, + TestOverlap: function (proxyIdA, proxyIdB) { + var aabbA = this.m_tree.GetFatAABB(proxyIdA); + var aabbB = this.m_tree.GetFatAABB(proxyIdB); + return b2TestOverlap(aabbA, aabbB) + }, + GetProxyCount: function () { + return this.m_proxyCount + }, + UpdatePairs: function (callback) { + this.m_pairCount = 0; + this.m_pairBuffer.length = 0; + for (var i = 0; i < this.m_moveCount; ++i) { + this.m_queryProxyId = this.m_moveBuffer[i]; + if (this.m_queryProxyId == b2BroadPhase.e_nullProxy) { + continue + } + var fatAABB = this.m_tree.GetFatAABB(this.m_queryProxyId); + this.m_tree.Query(this, fatAABB) + } + this.m_moveCount = 0; + this.m_pairBuffer.sort(b2PairLessThan); + var i = 0; + while (i < this.m_pairCount) { + var primaryPair = this.m_pairBuffer[i]; + var userDataA = this.m_tree.GetUserData(primaryPair.proxyIdA); + var userDataB = this.m_tree.GetUserData(primaryPair.proxyIdB); + callback.AddPair(userDataA, userDataB); + ++i; + while (i < this.m_pairCount) { + var pair = this.m_pairBuffer[i]; + if (pair.proxyIdA != primaryPair.proxyIdA || pair.proxyIdB != primaryPair.proxyIdB) { + break + }++i + } + } + }, + Query: function (callback, aabb) { + this.m_tree.Query(callback, aabb) + }, + RayCast: function (callback, input) { + this.m_tree.RayCast(callback, input) + }, + GetTreeHeight: function () { + return this.m_tree.GetHeight() + }, + GetTreeBalance: function () { + return this.m_tree.GetMaxBalance() + }, + GetTreeQuality: function () { + return this.m_tree.GetAreaRatio() + }, + ShiftOrigin: function (newOrigin) { + this.m_tree.ShiftOrigin(newOrigin) + }, + BufferMove: function (proxyId) { + this.m_moveBuffer[this.m_moveCount] = proxyId; + ++this.m_moveCount + }, + UnBufferMove: function (proxyId) { + for (var i = 0; i < this.m_moveCount; ++i) { + if (this.m_moveBuffer[i] == proxyId) { + this.m_moveBuffer[i] = b2BroadPhase.e_nullProxy + } + } + }, + QueryCallback: function (proxyId) { + if (proxyId == this.m_queryProxyId) { + return true + } + this.m_pairBuffer[this.m_pairCount] = new b2Pair(); + this.m_pairBuffer[this.m_pairCount].proxyIdA = b2Min(proxyId, this.m_queryProxyId); + this.m_pairBuffer[this.m_pairCount].proxyIdB = b2Max(proxyId, this.m_queryProxyId); + ++this.m_pairCount; + return true + } +}; +b2BroadPhase.e_nullProxy = -1; +"use strict"; + +function b2DistanceProxy() { + this.m_vertices = null; + this.m_count = 0; + this.m_radius = 0 +} +b2DistanceProxy.prototype = { + Assign: function (l) { + this.m_vertices = l.m_vertices; + this.m_count = l.m_count; + this.m_radius = l.m_radius + }, + Set: function (shape, index) { + switch (shape.GetType()) { + case b2Shape.e_circle: + var circle = shape; + this.m_vertices = [circle.m_p]; + this.m_count = 1; + this.m_radius = circle.m_radius; + break; + case b2Shape.e_polygon: + var polygon = shape; + this.m_vertices = polygon.m_vertices; + this.m_count = polygon.m_count; + this.m_radius = polygon.m_radius; + break; + case b2Shape.e_chain: + var chain = shape; + this.m_vertices = [chain.m_vertices[index]]; + if (index + 1 < chain.m_count) { + this.m_vertices[1] = chain.m_vertices[index + 1] + } else { + this.m_vertices[1] = chain.m_vertices[0] + } + this.m_count = 2; + this.m_radius = chain.m_radius; + break; + case b2Shape.e_edge: + var edge = shape; + this.m_vertices = [edge.m_vertex1, edge.m_vertex2]; + this.m_count = 2; + this.m_radius = edge.m_radius; + break + } + }, + GetSupport: function (dx, dy) { + var bestIndex = 0; + var bestValue = this.m_vertices[0].x * dx + this.m_vertices[0].y * dy; + for (var i = 1; i < this.m_count; ++i) { + var value = this.m_vertices[i].x * dx + this.m_vertices[i].y * dy; + if (value > bestValue) { + bestIndex = i; + bestValue = value + } + } + return bestIndex + }, + GetSupportVertex: function (dx, dy) { + return this.m_vertices[this.GetSupport(dx, dy)] + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + } +}; + +function b2SimplexCache() { + this.metric = 0; + this.count = 0; + this.indexA = [0, 0, 0]; + this.indexB = [0, 0, 0] +} + +function b2DistanceInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.transformA = new b2Transform(); + this.transformB = new b2Transform(); + this.useRadii = false +} + +function b2DistanceOutput() { + this.pointA = new b2Vec2(); + this.pointB = new b2Vec2(); + this.distance = 0; + this.iterations = 0 +} + +function b2SimplexVertex() { + this.wA = new b2Vec2(); + this.wB = new b2Vec2(); + this.w = new b2Vec2(); + this.a = 0; + this.indexA = 0; + this.indexB = 0 +} +b2SimplexVertex.prototype = { + Assign: function (l) { + this.wA.x = l.wA.x; + this.wA.y = l.wA.y; + this.wB.x = l.wB.x; + this.wB.y = l.wB.y; + this.w.x = l.w.x; + this.w.y = l.w.y; + this.a = l.a; + this.indexA = l.indexA; + this.indexB = l.indexB + } +}; + +function b2Simplex() { + this.m_v = [new b2SimplexVertex(), new b2SimplexVertex(), new b2SimplexVertex()]; + this.m_count = 0 +} +b2Simplex.prototype = { + ReadCache: function (cache, proxyA, transformA, proxyB, transformB) { + this.m_count = cache.count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + var v = vertices[i]; + v.indexA = cache.indexA[i]; + v.indexB = cache.indexB[i]; + var wALocal = proxyA.GetVertex(v.indexA); + var wBLocal = proxyB.GetVertex(v.indexB); + v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 0 + } + if (this.m_count > 1) { + var metric1 = cache.metric; + var metric2 = this.GetMetric(); + if (metric2 < 0.5 * metric1 || 2 * metric1 < metric2 || metric2 < b2_epsilon) { + this.m_count = 0 + } + } + if (this.m_count == 0) { + var v = vertices[0]; + v.indexA = 0; + v.indexB = 0; + var wALocal = proxyA.GetVertex(0); + var wBLocal = proxyB.GetVertex(0); + v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 1; + this.m_count = 1 + } + }, + WriteCache: function (cache) { + cache.metric = this.GetMetric(); + cache.count = this.m_count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + cache.indexA[i] = vertices[i].indexA; + cache.indexB[i] = vertices[i].indexB + } + }, + GetSearchDirection: function (p) { + switch (this.m_count) { + case 1: + p.x = -this.m_v[0].w.x; + p.y = -this.m_v[0].w.y; + break; + case 2: + var e12x = this.m_v[1].w.x - this.m_v[0].w.x; + var e12y = this.m_v[1].w.y - this.m_v[0].w.y; + var sgn = e12x * -this.m_v[0].w.y - e12y * -this.m_v[0].w.x; + if (sgn > 0) { + p.x = -1 * e12y; + p.y = 1 * e12x + } else { + p.x = 1 * e12y; + p.y = -1 * e12x + } + break + } + }, + GetClosestPoint: function (p) { + switch (this.m_count) { + case 1: + p.x = this.m_v[0].w.x; + p.y = this.m_v[0].w.y; + break; + case 2: + p.x = (this.m_v[0].a * this.m_v[0].w.x) + (this.m_v[1].a * this.m_v[1].w.x); + p.y = (this.m_v[0].a * this.m_v[0].w.y) + (this.m_v[1].a * this.m_v[1].w.y); + break; + case 3: + p.x = p.y = 0; + break + } + }, + GetWitnessPoints: function (pA, pB) { + switch (this.m_count) { + case 1: + pA.x = this.m_v[0].wA.x; + pA.y = this.m_v[0].wA.y; + pB.x = this.m_v[0].wB.x; + pB.y = this.m_v[0].wB.y; + break; + case 2: + pA.x = (this.m_v[0].a * this.m_v[0].wA.x) + (this.m_v[1].a * this.m_v[1].wA.x); + pA.y = (this.m_v[0].a * this.m_v[0].wA.y) + (this.m_v[1].a * this.m_v[1].wA.y); + pB.x = (this.m_v[0].a * this.m_v[0].wB.x) + (this.m_v[1].a * this.m_v[1].wB.x); + pB.y = (this.m_v[0].a * this.m_v[0].wB.y) + (this.m_v[1].a * this.m_v[1].wB.y); + break; + case 3: + pA.x = (this.m_v[0].a, this.m_v[0].wA.x) + (this.m_v[1].a, this.m_v[1].wA.x) + (this.m_v[2].a, this.m_v[2].wA.x); + pA.y = (this.m_v[0].a, this.m_v[0].wA.y) + (this.m_v[1].a, this.m_v[1].wA.y) + (this.m_v[2].a, this.m_v[2].wA.y); + pB.x = pA.x; + pB.y = pA.y; + break + } + }, + GetMetric: function () { + switch (this.m_count) { + case 1: + return 0; + case 2: + return b2Distance(this.m_v[0].w, this.m_v[1].w); + case 3: + return (this.m_v[1].w.x - this.m_v[0].w.x) * (this.m_v[2].w.y - this.m_v[0].w.y) - (this.m_v[1].w.y - this.m_v[0].w.y) * (this.m_v[2].w.x - this.m_v[0].w.x) + } + }, + Solve2: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var d12_2 = -(w1.x * e12x + w1.y * e12y); + if (d12_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + var d12_1 = w2.x * e12x + w2.y * e12y; + if (d12_1 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + var inv_d12 = 1 / (d12_1 + d12_2); + this.m_v[0].a = d12_1 * inv_d12; + this.m_v[1].a = d12_2 * inv_d12; + this.m_count = 2 + }, + Solve3: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var w3 = this.m_v[2].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var w1e12 = w1.x * e12x + w1.y * e12y; + var w2e12 = w2.x * e12x + w2.y * e12y; + var d12_1 = w2e12; + var d12_2 = -w1e12; + var e13x = w3.x - w1.x; + var e13y = w3.y - w1.y; + var w1e13 = w1.x * e13x + w1.y * e13y; + var w3e13 = w3.x * e13x + w3.y * e13y; + var d13_1 = w3e13; + var d13_2 = -w1e13; + var e23x = w3.x - w2.x; + var e23y = w3.y - w2.y; + var w2e23 = w2.x * e23x + w2.y * e23y; + var w3e23 = w3.x * e23x + w3.y * e23y; + var d23_1 = w3e23; + var d23_2 = -w2e23; + var n123 = e12x * e13y - e12y * e13x; + var d123_1 = n123 * (w2.x * w3.y - w2.y * w3.x); + var d123_2 = n123 * (w3.x * w1.y - w3.y * w1.x); + var d123_3 = n123 * (w1.x * w2.y - w1.y * w2.x); + if (d12_2 <= 0 && d13_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + if (d12_1 > 0 && d12_2 > 0 && d123_3 <= 0) { + var inv_d12 = 1 / (d12_1 + d12_2); + this.m_v[0].a = d12_1 * inv_d12; + this.m_v[1].a = d12_2 * inv_d12; + this.m_count = 2; + return + } + if (d13_1 > 0 && d13_2 > 0 && d123_2 <= 0) { + var inv_d13 = 1 / (d13_1 + d13_2); + this.m_v[0].a = d13_1 * inv_d13; + this.m_v[2].a = d13_2 * inv_d13; + this.m_count = 2; + this.m_v[1].Assign(this.m_v[2]); + return + } + if (d12_1 <= 0 && d23_2 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + if (d13_1 <= 0 && d23_1 <= 0) { + this.m_v[2].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[2]); + return + } + if (d23_1 > 0 && d23_2 > 0 && d123_1 <= 0) { + var inv_d23 = 1 / (d23_1 + d23_2); + this.m_v[1].a = d23_1 * inv_d23; + this.m_v[2].a = d23_2 * inv_d23; + this.m_count = 2; + this.m_v[0].Assign(this.m_v[2]); + return + } + var inv_d123 = 1 / (d123_1 + d123_2 + d123_3); + this.m_v[0].a = d123_1 * inv_d123; + this.m_v[1].a = d123_2 * inv_d123; + this.m_v[2].a = d123_3 * inv_d123; + this.m_count = 3 + } +}; +var _b2Distance_simplex = new b2Simplex(); +var _b2Distance_normal = new b2Vec2(); +var _b2Distance_p = new b2Vec2(); + +function b2DistanceFunc(output, cache, input) { + ++b2DistanceFunc.b2_gjkCalls; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + var transformA = input.transformA; + var transformB = input.transformB; + _b2Distance_simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); + var vertices = _b2Distance_simplex.m_v; + var k_maxIters = 20; + var saveA = [0, 0, 0], + saveB = [0, 0, 0]; + var saveCount = 0; + var distanceSqr1 = b2_maxFloat; + var distanceSqr2 = distanceSqr1; + var iter = 0; + while (iter < k_maxIters) { + saveCount = _b2Distance_simplex.m_count; + for (var i = 0; i < saveCount; ++i) { + saveA[i] = vertices[i].indexA; + saveB[i] = vertices[i].indexB + } + switch (_b2Distance_simplex.m_count) { + case 1: + break; + case 2: + _b2Distance_simplex.Solve2(); + break; + case 3: + _b2Distance_simplex.Solve3(); + break + } + if (_b2Distance_simplex.m_count == 3) { + break + } + _b2Distance_simplex.GetClosestPoint(_b2Distance_p); + distanceSqr2 = _b2Distance_p.LengthSquared(); + if (distanceSqr2 >= distanceSqr1) {} + distanceSqr1 = distanceSqr2; + _b2Distance_simplex.GetSearchDirection(_b2Distance_p); + if (_b2Distance_p.LengthSquared() < b2_epsilon * b2_epsilon) { + break + } + var vertex = vertices[_b2Distance_simplex.m_count]; + vertex.indexA = proxyA.GetSupport(transformA.q.c * -_b2Distance_p.x + transformA.q.s * -_b2Distance_p.y, -transformA.q.s * -_b2Distance_p.x + transformA.q.c * -_b2Distance_p.y); + var pva = proxyA.GetVertex(vertex.indexA); + vertex.wA.x = (transformA.q.c * pva.x - transformA.q.s * pva.y) + transformA.p.x; + vertex.wA.y = (transformA.q.s * pva.x + transformA.q.c * pva.y) + transformA.p.y; + vertex.indexB = proxyB.GetSupport(transformB.q.c * _b2Distance_p.x + transformB.q.s * _b2Distance_p.y, -transformB.q.s * _b2Distance_p.x + transformB.q.c * _b2Distance_p.y); + var pvb = proxyB.GetVertex(vertex.indexB); + vertex.wB.x = (transformB.q.c * pvb.x - transformB.q.s * pvb.y) + transformB.p.x; + vertex.wB.y = (transformB.q.s * pvb.x + transformB.q.c * pvb.y) + transformB.p.y; + vertex.w.x = vertex.wB.x - vertex.wA.x; + vertex.w.y = vertex.wB.y - vertex.wA.y; + ++iter; + ++b2DistanceFunc.b2_gjkIters; + var duplicate = false; + for (var i = 0; i < saveCount; ++i) { + if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) { + duplicate = true; + break + } + } + if (duplicate) { + break + }++_b2Distance_simplex.m_count + } + b2DistanceFunc.b2_gjkMaxIters = b2Max(b2DistanceFunc.b2_gjkMaxIters, iter); + _b2Distance_simplex.GetWitnessPoints(output.pointA, output.pointB); + output.distance = b2Distance(output.pointA, output.pointB); + output.iterations = iter; + _b2Distance_simplex.WriteCache(cache); + if (input.useRadii) { + var rA = proxyA.m_radius; + var rB = proxyB.m_radius; + if (output.distance > rA + rB && output.distance > b2_epsilon) { + output.distance -= rA + rB; + _b2Distance_normal.x = output.pointB.x - output.pointA.x; + _b2Distance_normal.y = output.pointB.y - output.pointA.y; + _b2Distance_normal.Normalize(); + output.pointA.x += (rA * _b2Distance_normal.x); + output.pointA.y += (rA * _b2Distance_normal.y); + output.pointB.x -= (rB * _b2Distance_normal.x); + output.pointB.y -= (rB * _b2Distance_normal.y) + } else { + var px = (0.5 * (output.pointA.x + output.pointB.x)); + var py = (0.5 * (output.pointA.y + output.pointB.y)); + output.pointA.x = px; + output.pointA.y = py; + output.pointB.x = px; + output.pointB.y = py; + output.distance = 0 + } + } +} +b2DistanceFunc.b2_gjkCalls = 0; +b2DistanceFunc.b2_gjkIters = 0; +b2DistanceFunc.b2_gjkMaxIters = 0; +"use strict"; +var b2_nullFeature = 255; + +function b2ContactID() {} +b2ContactID.prototype = { + indexA: 0, + indexB: 0, + typeA: 0, + typeB: 0, + Reset: function () { + this.indexA = this.indexB = this.typeA = this.typeB = 0 + }, + Get: function () { + return this.indexA | (this.indexB << 8) | (this.typeA << 16) | (this.typeB << 24) + }, + Assign: function (k) { + this.indexA = k.indexA; + this.indexB = k.indexB; + this.typeA = k.typeA; + this.typeB = k.typeB + } +}; +b2ContactID.e_vertex = 0; +b2ContactID.e_face = 1; + +function b2ManifoldPoint() { + this.localPoint = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.id = new b2ContactID() +} +b2ManifoldPoint.prototype = { + Clone: function () { + var point = new b2ManifoldPoint(); + point.localPoint.x = this.localPoint.x; + point.localPoint.y = this.localPoint.y; + point.normalImpulse = this.normalImpulse; + point.tangentImpulse = this.tangentImpulse; + point.id.Assign(this.id); + return point + } +}; + +function b2Manifold() { + this.points = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.type = 0; + this.pointCount = 0 +} +b2Manifold.prototype = { + Clone: function () { + var manifold = new b2Manifold(); + manifold.pointCount = this.pointCount; + manifold.type = this.type; + manifold.localPoint.x = this.localPoint.x; + manifold.localPoint.y = this.localPoint.y; + manifold.localNormal.x = this.localNormal.x; + manifold.localNormal.y = this.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + manifold.points[i] = this.points[i].Clone() + } + return manifold + }, + Assign: function (manifold) { + this.pointCount = manifold.pointCount; + this.type = manifold.type; + this.localPoint.x = manifold.localPoint.x; + this.localPoint.y = manifold.localPoint.y; + this.localNormal.x = manifold.localNormal.x; + this.localNormal.y = manifold.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + this.points[i] = manifold.points[i].Clone() + } + } +}; +b2Manifold.e_circles = 0; +b2Manifold.e_faceA = 1; +b2Manifold.e_faceB = 2; +b2Manifold.b2_nullState = 0; +b2Manifold.b2_addState = 1; +b2Manifold.b2_persistState = 2; +b2Manifold.b2_removeState = 3; + +function b2WorldManifold() { + this.normal = new b2Vec2(); + this.points = new Array(b2_maxManifoldPoints); + this.separations = new Array(b2_maxManifoldPoints) +} +b2WorldManifold.prototype = { + Initialize: function (manifold, xfA, radiusA, xfB, radiusB) { + if (manifold.pointCount == 0) { + return + } + switch (manifold.type) { + case b2Manifold.e_circles: + this.normal.x = 1; + this.normal.y = 0; + var pointAx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * manifold.points[0].localPoint.x - xfB.q.s * manifold.points[0].localPoint.y) + xfB.p.x; + var pointBy = (xfB.q.s * manifold.points[0].localPoint.x + xfB.q.c * manifold.points[0].localPoint.y) + xfB.p.y; + var cx = pointAx - pointBx; + var cy = pointAy - pointBy; + if ((cx * cx + cy * cy) > b2_epsilon * b2_epsilon) { + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + this.normal.Normalize() + } + var cAx = pointAx + (radiusA * this.normal.x); + var cAy = pointAy + (radiusA * this.normal.y); + var cBx = pointBx - (radiusB * this.normal.x); + var cBy = pointBy - (radiusB * this.normal.y); + this.points[0] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[0] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * manifold.localNormal.x - xfA.q.s * manifold.localNormal.y; + this.normal.y = xfA.q.s * manifold.localNormal.x + xfA.q.c * manifold.localNormal.y; + var planePointx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfB.q.c * manifold.points[i].localPoint.x - xfB.q.s * manifold.points[i].localPoint.y) + xfB.p.x; + var clipPointy = (xfB.q.s * manifold.points[i].localPoint.x + xfB.q.c * manifold.points[i].localPoint.y) + xfB.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cAx = clipPointx + ((radiusA - d) * this.normal.x); + var cAy = clipPointy + ((radiusA - d) * this.normal.y); + var cBx = (clipPointx - (radiusB * this.normal.x)); + var cBy = (clipPointy - (radiusB * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y + } + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * manifold.localNormal.x - xfB.q.s * manifold.localNormal.y; + this.normal.y = xfB.q.s * manifold.localNormal.x + xfB.q.c * manifold.localNormal.y; + var planePointx = (xfB.q.c * manifold.localPoint.x - xfB.q.s * manifold.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * manifold.localPoint.x + xfB.q.c * manifold.localPoint.y) + xfB.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfA.q.c * manifold.points[i].localPoint.x - xfA.q.s * manifold.points[i].localPoint.y) + xfA.p.x; + var clipPointy = (xfA.q.s * manifold.points[i].localPoint.x + xfA.q.c * manifold.points[i].localPoint.y) + xfA.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cBx = clipPointx + ((radiusB - d) * this.normal.x); + var cBy = clipPointy + ((radiusB - d) * this.normal.y); + var cAx = (clipPointx - (radiusA * this.normal.x)); + var cAy = (clipPointy - (radiusA * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cAx - cBx) * this.normal.x + (cAy - cBy) * this.normal.y + } + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } +}; + +function b2GetPointStates(state1, state2, manifold1, manifold2) { + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + state1[i] = b2Manifold.b2_nullState; + state2[i] = b2Manifold.b2_nullState + } + for (var i = 0; i < manifold1.pointCount; ++i) { + var id = manifold1.points[i].id; + state1[i] = b2Manifold.b2_removeState; + for (var j = 0; j < manifold2.pointCount; ++j) { + if (manifold2.points[j].id.Get() == id.Get()) { + state1[i] = b2Manifold.b2_persistState; + break + } + } + } + for (var i = 0; i < manifold2.pointCount; ++i) { + var id = manifold2.points[i].id; + state2[i] = b2Manifold.b2_addState; + for (var j = 0; j < manifold1.pointCount; ++j) { + if (manifold1.points[j].id.Get() == id.Get()) { + state2[i] = b2Manifold.b2_persistState; + break + } + } + } +} + +function b2ClipVertex() { + this.v = new b2Vec2(); + this.id = new b2ContactID() +} + +function b2RayCastInput() { + this.p1 = new b2Vec2(), this.p2 = new b2Vec2(); + this.maxFraction = 0 +} + +function b2RayCastOutput() { + this.normal = new b2Vec2(); + this.fraction = 0 +} + +function b2AABB() { + this.lowerBound = new b2Vec2(); + this.upperBound = new b2Vec2() +} +b2AABB.prototype = { + Assign: function (other) { + this.lowerBound.x = other.lowerBound.x; + this.lowerBound.y = other.lowerBound.y; + this.upperBound.x = other.upperBound.x; + this.upperBound.y = other.upperBound.y + }, + Clone: function () { + var clone = new b2AABB(); + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + return clone + }, + IsValid: function () { + return (this.upperBound.x - this.lowerBound.x) >= 0 && (this.upperBound.y - this.lowerBound.y) >= 0 && this.lowerBound.IsValid() && this.upperBound.IsValid() + }, + GetCenter: function () { + return new b2Vec2(0.5 * (this.lowerBound.x + this.upperBound.x), 0.5 * (this.lowerBound.y + this.upperBound.y)) + }, + GetExtents: function () { + return new b2Vec2(0.5 * (this.upperBound.x - this.lowerBound.x), 0.5 * (this.upperBound.y - this.lowerBound.y)) + }, + GetPerimeter: function () { + return 2 * ((this.upperBound.x - this.lowerBound.x) + (this.upperBound.y - this.lowerBound.y)) + }, + Combine: function (aabb1, aabb2) { + if (aabb2) { + this.lowerBound.x = b2Min(aabb1.lowerBound.x, aabb2.lowerBound.x); + this.lowerBound.y = b2Min(aabb1.lowerBound.y, aabb2.lowerBound.y); + this.upperBound.x = b2Max(aabb1.upperBound.x, aabb2.upperBound.x); + this.upperBound.y = b2Max(aabb1.upperBound.y, aabb2.upperBound.y) + } else { + this.lowerBound.x = b2Min(this.lowerBound.x, aabb1.lowerBound.x); + this.lowerBound.y = b2Min(this.lowerBound.y, aabb1.lowerBound.y); + this.upperBound.x = b2Max(this.upperBound.x, aabb1.upperBound.x); + this.upperBound.y = b2Max(this.upperBound.y, aabb1.upperBound.y) + } + }, + Contains: function (aabb) { + return this.lowerBound.x <= aabb.lowerBound.x && this.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= this.upperBound.x && aabb.upperBound.y <= this.upperBound.y + }, + RayCast: function (output, input) { + var tmin = -b2_maxFloat; + var tmax = b2_maxFloat; + var p = input.p1; + var d = b2Vec2.Subtract(input.p2, input.p1); + var absD = b2Abs_v2(d); + var normal = new b2Vec2(); + for (var i = 0; i < 2; ++i) { + if (absD.get_i(i) < b2_epsilon) { + if (p.get_i(i) < this.lowerBound.get_i(i) || this.upperBound.get_i(i) < p.get_i(i)) { + return false + } + } else { + var inv_d = 1 / d.get_i(i); + var t1 = (this.lowerBound.get_i(i) - p.get_i(i)) * inv_d; + var t2 = (this.upperBound.get_i(i) - p.get_i(i)) * inv_d; + var s = -1; + if (t1 > t2) { + var temp = t2; + t2 = t1; + t1 = temp; + s = 1 + } + if (t1 > tmin) { + normal.x = normal.y = 0; + normal.set_i(i, s); + tmin = t1 + } + tmax = b2Min(tmax, t2); + if (tmin > tmax) { + return false + } + } + } + if (tmin < 0 || input.maxFraction < tmin) { + return false + } + output.fraction = tmin; + output.normal.x = normal.x; + output.normal.y = normal.y; + return true + } +}; + +function b2CollideCircles(manifold, circleA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var pA = b2Mul_t_v2(xfA, circleA.m_p); + var pB = b2Mul_t_v2(xfB, circleB.m_p); + var dx = pB.x - pA.x; + var dy = pB.y - pA.y; + var distSqr = dx * dx + dy * dy; + var rA = circleA.m_radius, + rB = circleB.m_radius; + var radius = rA + rB; + if (distSqr > radius * radius) { + return + } + manifold.type = b2Manifold.e_circles; + manifold.localPoint.x = circleA.m_p.x; + manifold.localPoint.y = circleA.m_p.y; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.pointCount = 1; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() +} + +function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var c = b2Mul_t_v2(xfB, circleB.m_p); + var cLocal = b2MulT_t_v2(xfA, c); + var normalIndex = 0; + var separation = -b2_maxFloat; + var radius = polygonA.m_radius + circleB.m_radius; + var vertexCount = polygonA.m_count; + var vertices = polygonA.m_vertices; + var normals = polygonA.m_normals; + for (var i = 0; i < vertexCount; ++i) { + var s = normals[i].x * (cLocal.x - vertices[i].x) + normals[i].y * (cLocal.y - vertices[i].y); + if (s > radius) { + return + } + if (s > separation) { + separation = s; + normalIndex = i + } + } + var vertIndex1 = normalIndex; + var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; + var v1 = vertices[vertIndex1]; + var v2 = vertices[vertIndex2]; + if (separation < b2_epsilon) { + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = normals[normalIndex].x; + manifold.localNormal.y = normals[normalIndex].y; + manifold.localPoint.x = 0.5 * (v1.x + v2.x); + manifold.localPoint.y = 0.5 * (v1.y + v2.y); + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset(); + return + } + var u1 = (cLocal.x - v1.x) * (v2.x - v1.x) + (cLocal.y - v1.y) * (v2.y - v1.y); + var u2 = (cLocal.x - v2.x) * (v1.x - v2.x) + (cLocal.y - v2.y) * (v1.y - v2.y); + if (u1 <= 0) { + if (b2DistanceSquared(cLocal, v1) > radius * radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = cLocal.x - v1.x; + manifold.localNormal.y = cLocal.y - v1.y; + manifold.localNormal.Normalize(); + manifold.localPoint.x = v1.x; + manifold.localPoint.y = v1.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } else { + if (u2 <= 0) { + if (b2DistanceSquared(cLocal, v2) > radius * radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = cLocal.x - v2.x; + manifold.localNormal.y = cLocal.y - v2.y; + manifold.localNormal.Normalize(); + manifold.localPoint.x = v2.x; + manifold.localPoint.y = v2.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } else { + var faceCenterx = 0.5 * (v1.x + v2.x); + var faceCentery = 0.5 * (v1.y + v2.y); + var separation = (cLocal.x - faceCenterx) * normals[vertIndex1].x + (cLocal.y - faceCentery) * normals[vertIndex1].y; + if (separation > radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = normals[vertIndex1].x; + manifold.localNormal.y = normals[vertIndex1].y; + manifold.localPoint.x = faceCenterx; + manifold.localPoint.y = faceCentery; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } + } +} + +function b2FindMaxSeparation(edgeIndex, poly1, xf1, poly2, xf2) { + var count1 = poly1.m_count; + var count2 = poly2.m_count; + var n1s = poly1.m_normals; + var v1s = poly1.m_vertices; + var v2s = poly2.m_vertices; + var xf = b2MulT_t_t(xf2, xf1); + var bestIndex = 0; + var maxSeparation = -b2_maxFloat; + for (var i = 0; i < count1; ++i) { + var nx = xf.q.c * n1s[i].x - xf.q.s * n1s[i].y; + var ny = xf.q.s * n1s[i].x + xf.q.c * n1s[i].y; + var v1x = (xf.q.c * v1s[i].x - xf.q.s * v1s[i].y) + xf.p.x; + var v1y = (xf.q.s * v1s[i].x + xf.q.c * v1s[i].y) + xf.p.y; + var si = b2_maxFloat; + for (var j = 0; j < count2; ++j) { + var sij = nx * (v2s[j].x - v1x) + ny * (v2s[j].y - v1y); + if (sij < si) { + si = sij + } + } + if (si > maxSeparation) { + maxSeparation = si; + bestIndex = i + } + } + edgeIndex[0] = bestIndex; + return maxSeparation +} + +function b2FindIncidentEdge(c, poly1, xf1, edge1, poly2, xf2) { + var normals1 = poly1.m_normals; + var count2 = poly2.m_count; + var vertices2 = poly2.m_vertices; + var normals2 = poly2.m_normals; + var t1x = xf1.q.c * normals1[edge1].x - xf1.q.s * normals1[edge1].y; + var t1y = xf1.q.s * normals1[edge1].x + xf1.q.c * normals1[edge1].y; + var normal1x = xf2.q.c * t1x + xf2.q.s * t1y; + var normal1y = -xf2.q.s * t1x + xf2.q.c * t1y; + var index = 0; + var minDot = b2_maxFloat; + for (var i = 0; i < count2; ++i) { + var dot = normal1x * normals2[i].x + normal1y * normals2[i].y; + if (dot < minDot) { + minDot = dot; + index = i + } + } + var i1 = index; + var i2 = i1 + 1 < count2 ? i1 + 1 : 0; + c[0].v.x = (xf2.q.c * vertices2[i1].x - xf2.q.s * vertices2[i1].y) + xf2.p.x; + c[0].v.y = (xf2.q.s * vertices2[i1].x + xf2.q.c * vertices2[i1].y) + xf2.p.y; + c[0].id.indexA = edge1; + c[0].id.indexB = i1; + c[0].id.typeA = b2ContactID.e_face; + c[0].id.typeB = b2ContactID.e_vertex; + c[1].v.x = (xf2.q.c * vertices2[i2].x - xf2.q.s * vertices2[i2].y) + xf2.p.x; + c[1].v.y = (xf2.q.s * vertices2[i2].x + xf2.q.c * vertices2[i2].y) + xf2.p.y; + c[1].id.indexA = edge1; + c[1].id.indexB = i2; + c[1].id.typeA = b2ContactID.e_face; + c[1].id.typeB = b2ContactID.e_vertex +} + +function b2CollidePolygons(manifold, polyA, xfA, polyB, xfB) { + manifold.pointCount = 0; + var totalRadius = polyA.m_radius + polyB.m_radius; + var edgeA = [0]; + var separationA = b2FindMaxSeparation(edgeA, polyA, xfA, polyB, xfB); + if (separationA > totalRadius) { + return + } + var edgeB = [0]; + var separationB = b2FindMaxSeparation(edgeB, polyB, xfB, polyA, xfA); + if (separationB > totalRadius) { + return + } + var poly1; + var poly2; + var xf1, xf2; + var edge1 = 0; + var flip = 0; + var k_tol = 0.1 * b2_linearSlop; + if (separationB > separationA + k_tol) { + poly1 = polyB; + poly2 = polyA; + xf1 = xfB; + xf2 = xfA; + edge1 = edgeB[0]; + manifold.type = b2Manifold.e_faceB; + flip = 1 + } else { + poly1 = polyA; + poly2 = polyB; + xf1 = xfA; + xf2 = xfB; + edge1 = edgeA[0]; + manifold.type = b2Manifold.e_faceA; + flip = 0 + } + b2FindIncidentEdge(b2CollidePolygons._local_incidentEdges, poly1, xf1, edge1, poly2, xf2); + var count1 = poly1.m_count; + var vertices1 = poly1.m_vertices; + var iv1 = edge1; + var iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0; + var v11 = vertices1[iv1]; + var v12 = vertices1[iv2]; + b2CollidePolygons._localTangent.x = v12.x - v11.x; + b2CollidePolygons._localTangent.y = v12.y - v11.y; + b2CollidePolygons._localTangent.Normalize(); + var localNormalx = 1 * b2CollidePolygons._localTangent.y; + var localNormaly = -1 * b2CollidePolygons._localTangent.x; + var planePointx = 0.5 * (v11.x + v12.x); + var planePointy = 0.5 * (v11.y + v12.y); + var tangentx = xf1.q.c * b2CollidePolygons._localTangent.x - xf1.q.s * b2CollidePolygons._localTangent.y; + var tangenty = xf1.q.s * b2CollidePolygons._localTangent.x + xf1.q.c * b2CollidePolygons._localTangent.y; + var normalx = 1 * tangenty; + var normaly = -1 * tangentx; + v11 = b2Mul_t_v2(xf1, v11); + v12 = b2Mul_t_v2(xf1, v12); + var frontOffset = normalx * v11.x + normaly * v11.y; + var sideOffset1 = -(tangentx * v11.x + tangenty * v11.y) + totalRadius; + var sideOffset2 = (tangentx * v12.x + tangenty * v12.y) + totalRadius; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, b2CollidePolygons._local_incidentEdges, -tangentx, -tangenty, sideOffset1, iv1); + if (np < 2) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangentx, tangenty, sideOffset2, iv2); + if (np < 2) { + return + } + manifold.localNormal.x = localNormalx; + manifold.localNormal.y = localNormaly; + manifold.localPoint.x = planePointx; + manifold.localPoint.y = planePointy; + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = (normalx * clipPoints2[i].v.x + normaly * clipPoints2[i].v.y) - frontOffset; + if (separation <= totalRadius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + cp.localPoint.Assign(b2MulT_t_v2(xf2, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id); + if (flip) { + var cf = new b2ContactID(); + cf.Assign(cp.id); + cp.id.indexA = cf.indexB; + cp.id.indexB = cf.indexA; + cp.id.typeA = cf.typeB; + cp.id.typeB = cf.typeA + }++pointCount + } + } + manifold.pointCount = pointCount +} +b2CollidePolygons._localTangent = new b2Vec2(); +b2CollidePolygons._local_incidentEdges = [new b2ClipVertex(), new b2ClipVertex()]; + +function b2CollideEdgeAndCircle(manifold, edgeA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var Q = b2MulT_t_v2(xfA, b2Mul_t_v2(xfB, circleB.m_p)); + var A = edgeA.m_vertex1, + B = edgeA.m_vertex2; + var ex = B.x - A.x; + var ey = B.y - A.y; + var u = ex * (B.x - Q.x) + ey * (B.y - Q.y); + var v = ex * (Q.x - A.x) + ey * (Q.y - A.y); + var radius = edgeA.m_radius + circleB.m_radius; + var cf = new b2ContactID(); + cf.indexB = 0; + cf.typeB = b2ContactID.e_vertex; + if (v <= 0) { + var P = A; + var dx = Q.x - P.x; + var dy = Q.y - P.y; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + if (edgeA.m_hasVertex0) { + var A1 = edgeA.m_vertex0; + var B1 = A; + var e1x = B1.x - A1.x; + var e1y = B1.y - A1.y; + var u1 = e1x * (B1.x - Q.x) + e1y * (B1.y - Q.y); + if (u1 > 0) { + return + } + } + cf.indexA = 0; + cf.typeA = b2ContactID.e_vertex; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + return + } + if (u <= 0) { + var P = B; + var dx = Q.x - P.x; + var dy = Q.y - P.y; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + if (edgeA.m_hasVertex3) { + var B2 = edgeA.m_vertex3; + var A2 = B; + var e2x = B2.x - A2.x; + var e2y = B2.y - A2.y; + var v2 = e2x * (Q.x - A2.x) + e2y * (Q.y - A2.y); + if (v2 > 0) { + return + } + } + cf.indexA = 1; + cf.typeA = b2ContactID.e_vertex; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + return + } + var den = ex * ex + ey * ey; + var Px = (1 / den) * ((u * A.x) + (v * B.x)); + var Py = (1 / den) * ((u * A.y) + (v * B.y)); + var dx = Q.x - Px; + var dy = Q.y - Py; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + var nx = -ey; + var ny = ex; + if (nx * (Q.x - A.x) + ny * (Q.y - A.y) < 0) { + nx = -nx; + ny = -ny + } + cf.indexA = 0; + cf.typeA = b2ContactID.e_face; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = nx; + manifold.localNormal.y = ny; + manifold.localNormal.Normalize(); + manifold.localPoint.x = A.x; + manifold.localPoint.y = A.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y +} + +function b2EPAxis() { + this.type = 0; + this.index = 0; + this.separation = 0 +} +b2EPAxis.e_unknown = 0; +b2EPAxis.e_edgeA = 1; +b2EPAxis.e_edgeB = 2; + +function b2TempPolygon() { + this.vertices = new Array(b2_maxPolygonVertices); + this.normals = new Array(b2_maxPolygonVertices); + this.count = 0 +} + +function b2ReferenceFace() { + this.i1 = 0, this.i2 = 0; + this.v1 = new b2Vec2(), this.v2 = new b2Vec2(); + this.normal = new b2Vec2(); + this.sideNormal1 = new b2Vec2(); + this.sideOffset1 = 0; + this.sideNormal2 = new b2Vec2(); + this.sideOffset2 = 0 +} + +function b2EPCollider() { + this.m_polygonB = new b2TempPolygon(); + this.m_xf = new b2Transform(); + this.m_centroidB = new b2Vec2(); + this.m_v0 = new b2Vec2(), this.m_v1 = new b2Vec2(), this.m_v2 = new b2Vec2(), this.m_v3 = new b2Vec2(); + this.m_normal0 = new b2Vec2(), this.m_normal1 = new b2Vec2(), this.m_normal2 = new b2Vec2(); + this.m_normal = new b2Vec2(); + this.m_type1 = 0, this.m_type2 = 0; + this.m_lowerLimit = new b2Vec2(), this.m_upperLimit = new b2Vec2(); + this.m_radius = 0; + this.m_front = false +} +b2EPCollider._temp_edge = new b2Vec2(); +b2EPCollider._temp_edge0 = new b2Vec2(); +b2EPCollider._temp_edge2 = new b2Vec2(); +b2EPCollider.prototype = { + Collide: function (manifold, edgeA, xfA, polygonB, xfB) { + this.m_xf.Assign(b2MulT_t_t(xfA, xfB)); + this.m_centroidB.x = (this.m_xf.q.c * polygonB.m_centroid.x - this.m_xf.q.s * polygonB.m_centroid.y) + this.m_xf.p.x; + this.m_centroidB.y = (this.m_xf.q.s * polygonB.m_centroid.x + this.m_xf.q.c * polygonB.m_centroid.y) + this.m_xf.p.y; + this.m_v0.x = edgeA.m_vertex0.x; + this.m_v0.y = edgeA.m_vertex0.y; + this.m_v1.x = edgeA.m_vertex1.x; + this.m_v1.y = edgeA.m_vertex1.y; + this.m_v2.x = edgeA.m_vertex2.x; + this.m_v2.y = edgeA.m_vertex2.y; + this.m_v3.x = edgeA.m_vertex3.x; + this.m_v3.y = edgeA.m_vertex3.y; + var hasVertex0 = edgeA.m_hasVertex0; + var hasVertex3 = edgeA.m_hasVertex3; + b2EPCollider._temp_edge.x = this.m_v2.x - this.m_v1.x; + b2EPCollider._temp_edge.y = this.m_v2.y - this.m_v1.y; + b2EPCollider._temp_edge.Normalize(); + this.m_normal1.x = b2EPCollider._temp_edge.y; + this.m_normal1.y = -b2EPCollider._temp_edge.x; + var offset1 = this.m_normal1.x * (this.m_centroidB.x - this.m_v1.x) + this.m_normal1.y * (this.m_centroidB.y - this.m_v1.y); + var offset0 = 0, + offset2 = 0; + var convex1 = false, + convex2 = false; + if (hasVertex0) { + b2EPCollider._temp_edge0.x = this.m_v1.x - this.m_v0.x; + b2EPCollider._temp_edge0.y = this.m_v1.y - this.m_v0.y; + b2EPCollider._temp_edge0.Normalize(); + this.m_normal0.x = b2EPCollider._temp_edge0.y; + this.m_normal0.y = -b2EPCollider._temp_edge0.x; + convex1 = (b2EPCollider._temp_edge0.x * b2EPCollider._temp_edge.y - b2EPCollider._temp_edge0.y * b2EPCollider._temp_edge.x) >= 0; + offset0 = this.m_normal0.x * (this.m_centroidB.x - this.m_v0.x) + this.m_normal0.y * (this.m_centroidB.y - this.m_v0.y) + } + if (hasVertex3) { + b2EPCollider._temp_edge2.x = this.m_v3.x - this.m_v2.x; + b2EPCollider._temp_edge2.y = this.m_v3.y - this.m_v2.y; + b2EPCollider._temp_edge2.Normalize(); + this.m_normal2.x = b2EPCollider._temp_edge2.y; + this.m_normal2.y = -b2EPCollider._temp_edge2.x; + convex2 = (b2EPCollider._temp_edge.x * b2EPCollider._temp_edge2.y - b2EPCollider._temp_edge.y * b2EPCollider._temp_edge2.x) > 0; + offset2 = this.m_normal2.x * (this.m_centroidB.x - this.m_v2.x) + this.m_normal2.y * (this.m_centroidB.y - this.m_v2.y) + } + if (hasVertex0 && hasVertex3) { + if (convex1 && convex2) { + this.m_front = offset0 >= 0 || offset1 >= 0 || offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + if (convex1) { + this.m_front = offset0 >= 0 || (offset1 >= 0 && offset2 >= 0); + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + if (convex2) { + this.m_front = offset2 >= 0 || (offset0 >= 0 && offset1 >= 0); + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } + } + } + } else { + if (hasVertex0) { + if (convex1) { + this.m_front = offset0 >= 0 || offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } + } else { + if (hasVertex3) { + if (convex2) { + this.m_front = offset1 >= 0 || offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } else { + this.m_front = offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } + } else { + this.m_front = offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } + } + } + this.m_polygonB.count = polygonB.m_count; + for (var i = 0; i < polygonB.m_count; ++i) { + this.m_polygonB.vertices[i] = b2Mul_t_v2(this.m_xf, polygonB.m_vertices[i]); + this.m_polygonB.normals[i] = b2Mul_r_v2(this.m_xf.q, polygonB.m_normals[i]) + } + this.m_radius = 2 * b2_polygonRadius; + manifold.pointCount = 0; + var edgeAxis = this.ComputeEdgeSeparation(); + if (edgeAxis.type == b2EPAxis.e_unknown) { + return + } + if (edgeAxis.separation > this.m_radius) { + return + } + var polygonAxis = this.ComputePolygonSeparation(); + if (polygonAxis.type != b2EPAxis.e_unknown && polygonAxis.separation > this.m_radius) { + return + } + var k_relativeTol = 0.98; + var k_absoluteTol = 0.001; + var primaryAxis = new b2EPAxis(); + if (polygonAxis.type == b2EPAxis.e_unknown) { + primaryAxis = edgeAxis + } else { + if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { + primaryAxis = polygonAxis + } else { + primaryAxis = edgeAxis + } + } + var ie = new Array(2); + var rf = new b2ReferenceFace(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.type = b2Manifold.e_faceA; + var bestIndex = 0; + var bestValue = this.m_normal.x * this.m_polygonB.normals[0].x + this.m_normal.y * this.m_polygonB.normals[0].y; + for (var i = 1; i < this.m_polygonB.count; ++i) { + var value = this.m_normal.x * this.m_polygonB.normals[i].x + this.m_normal.y * this.m_polygonB.normals[i].y; + if (value < bestValue) { + bestValue = value; + bestIndex = i + } + } + var i1 = bestIndex; + var i2 = i1 + 1 < this.m_polygonB.count ? i1 + 1 : 0; + ie[0] = new b2ClipVertex(); + ie[0].v.x = this.m_polygonB.vertices[i1].x; + ie[0].v.y = this.m_polygonB.vertices[i1].y; + ie[0].id.indexA = 0; + ie[0].id.indexB = i1; + ie[0].id.typeA = b2ContactID.e_face; + ie[0].id.typeB = b2ContactID.e_vertex; + ie[1] = new b2ClipVertex(); + ie[1].v.x = this.m_polygonB.vertices[i2].x; + ie[1].v.y = this.m_polygonB.vertices[i2].y; + ie[1].id.indexA = 0; + ie[1].id.indexB = i2; + ie[1].id.typeA = b2ContactID.e_face; + ie[1].id.typeB = b2ContactID.e_vertex; + if (this.m_front) { + rf.i1 = 0; + rf.i2 = 1; + rf.v1.x = this.m_v1.x; + rf.v1.y = this.m_v1.y; + rf.v2.x = this.m_v2.x; + rf.v2.y = this.m_v2.y; + rf.normal.x = this.m_normal1.x; + rf.normal.y = this.m_normal1.y + } else { + rf.i1 = 1; + rf.i2 = 0; + rf.v1.x = this.m_v2.x; + rf.v1.y = this.m_v2.y; + rf.v2.x = this.m_v1.x; + rf.v2.y = this.m_v1.y; + rf.normal.x = -this.m_normal1.x; + rf.normal.y = -this.m_normal1.y + } + } else { + manifold.type = b2Manifold.e_faceB; + ie[0] = new b2ClipVertex(); + ie[0].v = this.m_v1; + ie[0].id.indexA = 0; + ie[0].id.indexB = primaryAxis.index; + ie[0].id.typeA = b2ContactID.e_vertex; + ie[0].id.typeB = b2ContactID.e_face; + ie[1] = new b2ClipVertex(); + ie[1].v = this.m_v2; + ie[1].id.indexA = 0; + ie[1].id.indexB = primaryAxis.index; + ie[1].id.typeA = b2ContactID.e_vertex; + ie[1].id.typeB = b2ContactID.e_face; + rf.i1 = primaryAxis.index; + rf.i2 = rf.i1 + 1 < this.m_polygonB.count ? rf.i1 + 1 : 0; + rf.v1.x = this.m_polygonB.vertices[rf.i1].x; + rf.v1.y = this.m_polygonB.vertices[rf.i1].y; + rf.v2.x = this.m_polygonB.vertices[rf.i2].x; + rf.v2.y = this.m_polygonB.vertices[rf.i2].y; + rf.normal.x = this.m_polygonB.normals[rf.i1].x; + rf.normal.y = this.m_polygonB.normals[rf.i1].y + } + rf.sideNormal1.x = rf.normal.y; + rf.sideNormal1.y = -rf.normal.x; + rf.sideNormal2.x = -rf.sideNormal1.x; + rf.sideNormal2.y = -rf.sideNormal1.y; + rf.sideOffset1 = rf.sideNormal1.x * rf.v1.x + rf.sideNormal1.y * rf.v1.y; + rf.sideOffset2 = rf.sideNormal2.x * rf.v2.x + rf.sideNormal2.y * rf.v2.y; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1.x, rf.sideNormal1.y, rf.sideOffset1, rf.i1); + if (np < b2_maxManifoldPoints) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2.x, rf.sideNormal2.y, rf.sideOffset2, rf.i2); + if (np < b2_maxManifoldPoints) { + return + } + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.localNormal.x = rf.normal.x; + manifold.localNormal.y = rf.normal.y; + manifold.localPoint.x = rf.v1.x; + manifold.localPoint.y = rf.v1.y + } else { + manifold.localNormal.x = polygonB.m_normals[rf.i1].x; + manifold.localNormal.y = polygonB.m_normals[rf.i1].y; + manifold.localPoint.x = polygonB.m_vertices[rf.i1].x; + manifold.localPoint.y = polygonB.m_vertices[rf.i1].y + } + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = rf.normal.x * (clipPoints2[i].v.x - rf.v1.x) + rf.normal.y * (clipPoints2[i].v.y - rf.v1.y); + if (separation <= this.m_radius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + cp.localPoint.Assign(b2MulT_t_v2(this.m_xf, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id) + } else { + cp.localPoint.x = clipPoints2[i].v.x; + cp.localPoint.y = clipPoints2[i].v.y; + cp.id.typeA = clipPoints2[i].id.typeB; + cp.id.typeB = clipPoints2[i].id.typeA; + cp.id.indexA = clipPoints2[i].id.indexB; + cp.id.indexB = clipPoints2[i].id.indexA + }++pointCount + } + } + manifold.pointCount = pointCount + }, + ComputeEdgeSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_edgeA; + axis.index = this.m_front ? 0 : 1; + axis.separation = Number.MAX_VALUE; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var s = this.m_normal.x * (this.m_polygonB.vertices[i].x - this.m_v1.x) + this.m_normal.y * (this.m_polygonB.vertices[i].y - this.m_v1.y); + if (s < axis.separation) { + axis.separation = s + } + } + return axis + }, + ComputePolygonSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_unknown; + axis.index = -1; + axis.separation = -Number.MAX_VALUE; + var perpx = -this.m_normal.y; + var perpy = this.m_normal.x; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var nx = -this.m_polygonB.normals[i].x; + var ny = -this.m_polygonB.normals[i].y; + var s1 = nx * (this.m_polygonB.vertices[i].x - this.m_v1.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v1.y); + var s2 = nx * (this.m_polygonB.vertices[i].x - this.m_v2.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v2.y); + var s = b2Min(s1, s2); + if (s > this.m_radius) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s; + return axis + } + if (nx * perpx + ny * perpy >= 0) { + if ((nx - this.m_upperLimit.x) * this.m_normal.x + (ny - this.m_upperLimit.y) * this.m_normal.y < -b2_angularSlop) { + continue + } + } else { + if ((nx - this.m_lowerLimit.x) * this.m_normal.x + (ny - this.m_lowerLimit.y) * this.m_normal.y < -b2_angularSlop) { + continue + } + } + if (s > axis.separation) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s + } + } + return axis + } +}; +b2EPCollider.e_isolated = 0; +b2EPCollider.e_concave = 1; +b2EPCollider.e_convex = 2; + +function b2CollideEdgeAndPolygon(manifold, edgeA, xfA, polygonB, xfB) { + b2CollideEdgeAndPolygon.collider.Collide(manifold, edgeA, xfA, polygonB, xfB) +} +b2CollideEdgeAndPolygon.collider = new b2EPCollider(); + +function b2ClipSegmentToLine(vOut, vIn, normalx, normaly, offset, vertexIndexA) { + var numOut = 0; + var distance0 = (normalx * vIn[0].v.x + normaly * vIn[0].v.y) - offset; + var distance1 = (normalx * vIn[1].v.x + normaly * vIn[1].v.y) - offset; + if (distance0 <= 0) { + vOut[numOut++] = vIn[0] + } + if (distance1 <= 0) { + vOut[numOut++] = vIn[1] + } + if (distance0 * distance1 < 0) { + var interp = distance0 / (distance0 - distance1); + vOut[numOut] = new b2ClipVertex(); + vOut[numOut].v.x = vIn[0].v.x + (interp * (vIn[1].v.x - vIn[0].v.x)); + vOut[numOut].v.y = vIn[0].v.y + (interp * (vIn[1].v.y - vIn[0].v.y)); + vOut[numOut].id.indexA = vertexIndexA; + vOut[numOut].id.indexB = vIn[0].id.indexB; + vOut[numOut].id.typeA = b2ContactID.e_vertex; + vOut[numOut].id.typeB = b2ContactID.e_face; + ++numOut + } + return numOut +} + +function b2TestShapeOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB) { + b2TestShapeOverlap.input.proxyA.Set(shapeA, indexA); + b2TestShapeOverlap.input.proxyB.Set(shapeB, indexB); + b2TestShapeOverlap.input.transformA = xfA; + b2TestShapeOverlap.input.transformB = xfB; + b2TestShapeOverlap.input.useRadii = true; + b2TestShapeOverlap.cache.count = 0; + b2DistanceFunc(b2TestShapeOverlap.output, b2TestShapeOverlap.cache, b2TestShapeOverlap.input); + return b2TestShapeOverlap.output.distance < 10 * b2_epsilon +} +b2TestShapeOverlap.input = new b2DistanceInput(); +b2TestShapeOverlap.cache = new b2SimplexCache(); +b2TestShapeOverlap.output = new b2DistanceOutput(); + +function b2TestOverlap(a, b) { + return !((b.lowerBound.x - a.upperBound.x) > 0 || (b.lowerBound.y - a.upperBound.y) > 0 || (a.lowerBound.x - b.upperBound.x) > 0 || (a.lowerBound.y - b.upperBound.y) > 0) +} +"use strict"; +var b2_nullNode = -1; + +function b2TreeNode() { + this.aabb = new b2AABB(); + this.userData = null; + this.parent = 0; + this.child1 = this.child2 = this.height = 0 +} +b2TreeNode.prototype = { + IsLeaf: function () { + return this.child1 == b2_nullNode + } +}; + +function b2DynamicTree() { + this.m_root = b2_nullNode; + this.m_nodeCapacity = 16; + this.m_nodeCount = 0; + this.m_nodes = new Array(this.m_nodeCapacity); + for (var i = 0; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 + } + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = 0; + this.m_path = 0; + this.m_insertionCount = 0 +} +b2DynamicTree.aabbExtensionFattener = new b2Vec2(b2_aabbExtension, b2_aabbExtension); +b2DynamicTree.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.AllocateNode(); + this.m_nodes[proxyId].aabb.lowerBound.Assign(b2Vec2.Subtract(aabb.lowerBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].aabb.upperBound.Assign(b2Vec2.Add(aabb.upperBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].userData = userData; + this.m_nodes[proxyId].height = 0; + this.InsertLeaf(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.RemoveLeaf(proxyId); + this.FreeNode(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + if (this.m_nodes[proxyId].aabb.Contains(aabb)) { + return false + } + this.RemoveLeaf(proxyId); + this.m_nodes[proxyId].aabb.Assign(aabb); + this.m_nodes[proxyId].aabb.lowerBound.Subtract(b2DynamicTree.aabbExtensionFattener); + this.m_nodes[proxyId].aabb.upperBound.Add(b2DynamicTree.aabbExtensionFattener); + var d = b2Vec2.Multiply(b2_aabbMultiplier, displacement); + if (d.x < 0) { + this.m_nodes[proxyId].aabb.lowerBound.x += d.x + } else { + this.m_nodes[proxyId].aabb.upperBound.x += d.x + } + if (d.y < 0) { + this.m_nodes[proxyId].aabb.lowerBound.y += d.y + } else { + this.m_nodes[proxyId].aabb.upperBound.y += d.y + } + this.InsertLeaf(proxyId); + return true + }, + GetUserData: function (proxyId) { + return this.m_nodes[proxyId].userData + }, + GetFatAABB: function (proxyId) { + return this.m_nodes[proxyId].aabb + }, + Query: function (callback, aabb) { + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue + } + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, aabb)) { + if (node.IsLeaf()) { + var proceed = callback.QueryCallback(nodeId); + if (proceed == false) { + return + } + } else { + stack.push(node.child1); + stack.push(node.child2) + } + } + } + }, + RayCast: function (callback, input) { + var p1 = input.p1; + var p2 = input.p2; + var r = b2Vec2.Subtract(p2, p1); + r.Normalize(); + var v = b2Cross_f_v2(1, r); + var abs_v = b2Abs_v2(v); + var maxFraction = input.maxFraction; + var segmentAABB = new b2AABB(); + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)); + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue + } + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, segmentAABB) == false) { + continue + } + var c = node.aabb.GetCenter(); + var h = node.aabb.GetExtents(); + var separation = b2Abs(b2Dot_v2_v2(v, b2Vec2.Subtract(p1, c))) - b2Dot_v2_v2(abs_v, h); + if (separation > 0) { + continue + } + if (node.IsLeaf()) { + var subInput = new b2RayCastInput(); + subInput.p1.Assign(input.p1); + subInput.p2.Assign(input.p2); + subInput.maxFraction = maxFraction; + var value = callback.RayCastCallback(subInput, nodeId); + if (value == 0) { + return + } + if (value > 0) { + maxFraction = value; + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)) + } + } else { + stack.push(node.child1); + stack.push(node.child2) + } + } + }, + Validate: function () { + this.ValidateStructure(this.m_root); + this.ValidateMetrics(this.m_root); + var freeCount = 0; + var freeIndex = this.m_freeList; + while (freeIndex != b2_nullNode) { + freeIndex = this.m_nodes[freeIndex].parent; + ++freeCount + } + }, + GetHeight: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + return this.m_nodes[this.m_root].height + }, + GetMaxBalance: function () { + var maxBalance = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height <= 1) { + continue + } + var child1 = node.child1; + var child2 = node.child2; + var balance = b2Abs(this.m_nodes[child2].height - this.m_nodes[child1].height); + maxBalance = b2Max(maxBalance, balance) + } + return maxBalance + }, + GetAreaRatio: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + var root = this.m_nodes[this.m_root]; + var rootArea = root.aabb.GetPerimeter(); + var totalArea = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height < 0) { + continue + } + totalArea += node.aabb.GetPerimeter() + } + return totalArea / rootArea + }, + RebuildBottomUp: function () { + var nodes = new Array(this.m_nodeCount); + var count = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + if (this.m_nodes[i].height < 0) { + continue + } + if (this.m_nodes[i].IsLeaf()) { + this.m_nodes[i].parent = b2_nullNode; + nodes[count] = i; + ++count + } else { + this.FreeNode(i) + } + } + while (count > 1) { + var minCost = b2_maxFloat; + var iMin = -1, + jMin = -1; + for (i = 0; i < count; ++i) { + var aabbi = this.m_nodes[nodes[i]].aabb; + for (var j = i + 1; j < count; ++j) { + var aabbj = this.m_nodes[nodes[j]].aabb; + var b = new b2AABB(); + b.Combine(aabbi, aabbj); + var cost = b.GetPerimeter(); + if (cost < minCost) { + iMin = i; + jMin = j; + minCost = cost + } + } + } + var index1 = nodes[iMin]; + var index2 = nodes[jMin]; + var child1 = this.m_nodes[index1]; + var child2 = this.m_nodes[index2]; + var parentIndex = this.AllocateNode(); + var parent = this.m_nodes[parentIndex]; + parent.child1 = index1; + parent.child2 = index2; + parent.height = 1 + b2Max(child1.height, child2.height); + parent.aabb.Combine(child1.aabb, child2.aabb); + parent.parent = b2_nullNode; + child1.parent = parentIndex; + child2.parent = parentIndex; + nodes[jMin] = nodes[count - 1]; + nodes[iMin] = parentIndex; + --count + } + this.m_root = nodes[0]; + this.Validate() + }, + ShiftOrigin: function (newOrigin) { + for (var i = 0; i < this.m_nodeCapacity; ++i) { + this.m_nodes[i].aabb.lowerBound.Subtract(newOrigin); + this.m_nodes[i].aabb.upperBound.Subtract(newOrigin) + } + }, + AllocateNode: function () { + if (this.m_freeList == b2_nullNode) { + var oldNodes = this.m_nodes; + this.m_nodeCapacity *= 2; + this.m_nodes = oldNodes.concat(new Array(this.m_nodeCapacity - this.m_nodeCount)); + for (var i = this.m_nodeCount; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 + } + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = this.m_nodeCount + } + var nodeId = this.m_freeList; + this.m_freeList = this.m_nodes[nodeId].parent; + this.m_nodes[nodeId].parent = b2_nullNode; + this.m_nodes[nodeId].child1 = b2_nullNode; + this.m_nodes[nodeId].child2 = b2_nullNode; + this.m_nodes[nodeId].height = 0; + this.m_nodes[nodeId].userData = null; + ++this.m_nodeCount; + return nodeId + }, + FreeNode: function (nodeId) { + this.m_nodes[nodeId].parent = this.m_freeList; + this.m_nodes[nodeId].height = -1; + this.m_freeList = nodeId; + --this.m_nodeCount + }, + InsertLeaf: function (leaf) { + ++this.m_insertionCount; + if (this.m_root == b2_nullNode) { + this.m_root = leaf; + this.m_nodes[this.m_root].parent = b2_nullNode; + return + } + var leafAABB = this.m_nodes[leaf].aabb; + var index = this.m_root; + while (this.m_nodes[index].IsLeaf() == false) { + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + var area = this.m_nodes[index].aabb.GetPerimeter(); + var combinedAABB = new b2AABB(); + combinedAABB.Combine(this.m_nodes[index].aabb, leafAABB); + var combinedArea = combinedAABB.GetPerimeter(); + var cost = 2 * combinedArea; + var inheritanceCost = 2 * (combinedArea - area); + var cost1; + var aabb; + if (this.m_nodes[child1].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + cost1 = aabb.GetPerimeter() + inheritanceCost + } else { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + var oldArea = this.m_nodes[child1].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost1 = (newArea - oldArea) + inheritanceCost + } + var cost2; + if (this.m_nodes[child2].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + cost2 = aabb.GetPerimeter() + inheritanceCost + } else { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + var oldArea = this.m_nodes[child2].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost2 = newArea - oldArea + inheritanceCost + } + if (cost < cost1 && cost < cost2) { + break + } + if (cost1 < cost2) { + index = child1 + } else { + index = child2 + } + } + var sibling = index; + var oldParent = this.m_nodes[sibling].parent; + var newParent = this.AllocateNode(); + this.m_nodes[newParent].parent = oldParent; + this.m_nodes[newParent].userData = null; + this.m_nodes[newParent].aabb.Combine(leafAABB, this.m_nodes[sibling].aabb); + this.m_nodes[newParent].height = this.m_nodes[sibling].height + 1; + if (oldParent != b2_nullNode) { + if (this.m_nodes[oldParent].child1 == sibling) { + this.m_nodes[oldParent].child1 = newParent + } else { + this.m_nodes[oldParent].child2 = newParent + } + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent + } else { + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent; + this.m_root = newParent + } + index = this.m_nodes[leaf].parent; + while (index != b2_nullNode) { + index = this.Balance(index); + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); + this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + index = this.m_nodes[index].parent + } + }, + RemoveLeaf: function (leaf) { + if (leaf == this.m_root) { + this.m_root = b2_nullNode; + return + } + var parent = this.m_nodes[leaf].parent; + var grandParent = this.m_nodes[parent].parent; + var sibling; + if (this.m_nodes[parent].child1 == leaf) { + sibling = this.m_nodes[parent].child2 + } else { + sibling = this.m_nodes[parent].child1 + } + if (grandParent != b2_nullNode) { + if (this.m_nodes[grandParent].child1 == parent) { + this.m_nodes[grandParent].child1 = sibling + } else { + this.m_nodes[grandParent].child2 = sibling + } + this.m_nodes[sibling].parent = grandParent; + this.FreeNode(parent); + var index = grandParent; + while (index != b2_nullNode) { + index = this.Balance(index); + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); + index = this.m_nodes[index].parent + } + } else { + this.m_root = sibling; + this.m_nodes[sibling].parent = b2_nullNode; + this.FreeNode(parent) + } + }, + Balance: function (iA) { + var A = this.m_nodes[iA]; + if (A.IsLeaf() || A.height < 2) { + return iA + } + var iB = A.child1; + var iC = A.child2; + var B = this.m_nodes[iB]; + var C = this.m_nodes[iC]; + var balance = C.height - B.height; + if (balance > 1) { + var iF = C.child1; + var iG = C.child2; + var F = this.m_nodes[iF]; + var G = this.m_nodes[iG]; + C.child1 = iA; + C.parent = A.parent; + A.parent = iC; + if (C.parent != b2_nullNode) { + if (this.m_nodes[C.parent].child1 == iA) { + this.m_nodes[C.parent].child1 = iC + } else { + this.m_nodes[C.parent].child2 = iC + } + } else { + this.m_root = iC + } + if (F.height > G.height) { + C.child2 = iF; + A.child2 = iG; + G.parent = iA; + A.aabb.Combine(B.aabb, G.aabb); + C.aabb.Combine(A.aabb, F.aabb); + A.height = 1 + b2Max(B.height, G.height); + C.height = 1 + b2Max(A.height, F.height) + } else { + C.child2 = iG; + A.child2 = iF; + F.parent = iA; + A.aabb.Combine(B.aabb, F.aabb); + C.aabb.Combine(A.aabb, G.aabb); + A.height = 1 + b2Max(B.height, F.height); + C.height = 1 + b2Max(A.height, G.height) + } + return iC + } + if (balance < -1) { + var iD = B.child1; + var iE = B.child2; + var D = this.m_nodes[iD]; + var E = this.m_nodes[iE]; + B.child1 = iA; + B.parent = A.parent; + A.parent = iB; + if (B.parent != b2_nullNode) { + if (this.m_nodes[B.parent].child1 == iA) { + this.m_nodes[B.parent].child1 = iB + } else { + this.m_nodes[B.parent].child2 = iB + } + } else { + this.m_root = iB + } + if (D.height > E.height) { + B.child2 = iD; + A.child1 = iE; + E.parent = iA; + A.aabb.Combine(C.aabb, E.aabb); + B.aabb.Combine(A.aabb, D.aabb); + A.height = 1 + b2Max(C.height, E.height); + B.height = 1 + b2Max(A.height, D.height) + } else { + B.child2 = iE; + A.child1 = iD; + D.parent = iA; + A.aabb.Combine(C.aabb, D.aabb); + B.aabb.Combine(A.aabb, E.aabb); + A.height = 1 + b2Max(C.height, D.height); + B.height = 1 + b2Max(A.height, E.height) + } + return iB + } + return iA + }, + ComputeHeight: function (nodeId) { + if (typeof (nodeId) === "undefined") { + nodeId = this.m_root + } + var node = this.m_nodes[nodeId]; + if (node.IsLeaf()) { + return 0 + } + var height1 = this.ComputeHeight(node.child1); + var height2 = this.ComputeHeight(node.child2); + return 1 + b2Max(height1, height2) + }, + ValidateStructure: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + this.ValidateStructure(child1); + this.ValidateStructure(child2) + }, + ValidateMetrics: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + var height1 = this.m_nodes[child1].height; + var height2 = this.m_nodes[child2].height; + var height; + height = 1 + b2Max(height1, height2); + var aabb = new b2AABB(); + aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.ValidateMetrics(child1); + this.ValidateMetrics(child2) + } +}; +"use strict"; + +function b2TOIInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.sweepA = new b2Sweep(); + this.sweepB = new b2Sweep(); + this.tMax = 0 +} + +function b2TOIOutput() { + this.state = 0; + this.t = 0 +} +b2TOIOutput.e_unknown = 0; +b2TOIOutput.e_failed = 1; +b2TOIOutput.e_overlapped = 2; +b2TOIOutput.e_touching = 3; +b2TOIOutput.e_separated = 4; + +function b2SeparationFunction() { + this.m_proxyA = null; + this.m_proxyB = null; + this.m_sweepA = null; + this.m_sweepB = null; + this.m_type = 0; + this.m_localPoint = new b2Vec2(); + this.m_axis = new b2Vec2() +} +var _local_xfA = new b2Transform(); +var _local_xfB = new b2Transform(); +b2SeparationFunction.prototype = { + Initialize: function (cache, proxyA, sweepA, proxyB, sweepB, t1) { + this.m_proxyA = proxyA; + this.m_proxyB = proxyB; + var count = cache.count; + this.m_sweepA = sweepA; + this.m_sweepB = sweepB; + this.m_sweepA.GetTransform(_local_xfA, t1); + this.m_sweepB.GetTransform(_local_xfB, t1); + if (count == 1) { + this.m_type = b2SeparationFunction.e_points; + var localPointA = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + this.m_axis.x = pointBx - pointAx; + this.m_axis.y = pointBy - pointAy; + var s = this.m_axis.Normalize(); + return s + } else { + if (cache.indexA[0] == cache.indexA[1]) { + this.m_type = b2SeparationFunction.e_faceB; + var localPointB1 = proxyB.GetVertex(cache.indexB[0]); + var localPointB2 = proxyB.GetVertex(cache.indexB[1]); + this.m_axis.x = 1 * (localPointB2.y - localPointB1.y); + this.m_axis.y = -1 * (localPointB2.x - localPointB1.x); + this.m_axis.Normalize(); + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x); + this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y); + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = proxyA.GetVertex(cache.indexA[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var s = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } else { + this.m_type = b2SeparationFunction.e_faceA; + var localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]); + this.m_axis.x = 1 * (localPointA2.y - localPointA1.y); + this.m_axis.y = -1 * (localPointA2.x - localPointA1.x); + this.m_axis.Normalize(); + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x); + this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y); + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var s = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } + } + }, + FindMinSeparation: function (indices, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var axisAx = _local_xfA.q.c * this.m_axis.x + _local_xfA.q.s * this.m_axis.y; + var axisAy = -_local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var axisBx = _local_xfB.q.c * -this.m_axis.x + _local_xfB.q.s * -this.m_axis.y; + var axisBy = -_local_xfB.q.s * -this.m_axis.x + _local_xfB.q.c * -this.m_axis.y; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisAy); + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var localPointB = this.m_proxyB.GetVertex(indices[1]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + return (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var axisBx = _local_xfB.q.c * -normalx + _local_xfB.q.s * -normaly; + var axisBy = -_local_xfB.q.s * -normalx + _local_xfB.q.c * -normaly; + indices[0] = -1; + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointB = this.m_proxyB.GetVertex(indices[1]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + return (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var axisAx = _local_xfA.q.c * -normalx + _local_xfA.q.s * -normaly; + var axisBy = -_local_xfA.q.s * -normalx + _local_xfA.q.c * -normaly; + indices[1] = -1; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + return (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly + } + }, + Evaluate: function (indexA, indexB, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var localPointA = this.m_proxyA.GetVertex(indexA); + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + return separation; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + return separation; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = this.m_proxyA.GetVertex(indexA); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var separation = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + return separation + } + } +}; +b2SeparationFunction.e_points = 0; +b2SeparationFunction.e_faceA = 1; +b2SeparationFunction.e_faceB = 2; +var profile_toi = b2Profiler.create("toi", "solveTOI"); + +function b2TimeOfImpact(output, input) { + profile_toi.start(); + ++b2TimeOfImpact.b2_toiCalls; + output.state = b2TOIOutput.e_unknown; + output.t = input.tMax; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + b2TimeOfImpact._temp_sweepA.Assign(input.sweepA); + b2TimeOfImpact._temp_sweepB.Assign(input.sweepB); + b2TimeOfImpact._temp_sweepA.Normalize(); + b2TimeOfImpact._temp_sweepB.Normalize(); + var tMax = input.tMax; + var totalRadius = proxyA.m_radius + proxyB.m_radius; + var target = b2Max(b2_linearSlop, totalRadius - 3 * b2_linearSlop); + var tolerance = 0.25 * b2_linearSlop; + var t1 = 0; + var k_maxIterations = 20; + var iter = 0; + var cache = new b2SimplexCache(); + cache.count = 0; + var distanceInput = new b2DistanceInput(); + distanceInput.proxyA.Assign(input.proxyA); + distanceInput.proxyB.Assign(input.proxyB); + distanceInput.useRadii = false; + for (;;) { + b2TimeOfImpact._temp_sweepA.GetTransform(distanceInput.transformA, t1); + b2TimeOfImpact._temp_sweepB.GetTransform(distanceInput.transformB, t1); + var distanceOutput = new b2DistanceOutput(); + b2DistanceFunc(distanceOutput, cache, distanceInput); + if (distanceOutput.distance <= 0) { + output.state = b2TOIOutput.e_overlapped; + output.t = 0; + break + } + if (distanceOutput.distance < target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + break + } + var fcn = new b2SeparationFunction(); + fcn.Initialize(cache, proxyA, b2TimeOfImpact._temp_sweepA, proxyB, b2TimeOfImpact._temp_sweepB, t1); + var done = false; + var t2 = tMax; + var pushBackIter = 0; + for (;;) { + var indices = []; + var s2 = fcn.FindMinSeparation(indices, t2); + if (s2 > target + tolerance) { + output.state = b2TOIOutput.e_separated; + output.t = tMax; + done = true; + break + } + if (s2 > target - tolerance) { + t1 = t2; + break + } + var s1 = fcn.Evaluate(indices[0], indices[1], t1); + if (s1 < target - tolerance) { + output.state = b2TOIOutput.e_failed; + output.t = t1; + done = true; + break + } + if (s1 <= target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + done = true; + break + } + var rootIterCount = 0; + var a1 = t1, + a2 = t2; + for (;;) { + var t; + if (rootIterCount & 1) { + t = a1 + (target - s1) * (a2 - a1) / (s2 - s1) + } else { + t = 0.5 * (a1 + a2) + }++rootIterCount; + ++b2TimeOfImpact.b2_toiRootIters; + var s = fcn.Evaluate(indices[0], indices[1], t); + if (b2Abs(s - target) < tolerance) { + t2 = t; + break + } + if (s > target) { + a1 = t; + s1 = s + } else { + a2 = t; + s2 = s + } + if (rootIterCount == 50) { + break + } + } + b2TimeOfImpact.b2_toiMaxRootIters = b2Max(b2TimeOfImpact.b2_toiMaxRootIters, rootIterCount); + ++pushBackIter; + if (pushBackIter == b2_maxPolygonVertices) { + break + } + }++iter; + ++b2TimeOfImpact.b2_toiIters; + if (done) { + break + } + if (iter == k_maxIterations) { + output.state = b2TOIOutput.e_failed; + output.t = t1; + break + } + } + b2TimeOfImpact.b2_toiMaxIters = b2Max(b2TimeOfImpact.b2_toiMaxIters, iter); + profile_toi.stop(); + b2TimeOfImpact.b2_toiMaxTime = b2Max(b2TimeOfImpact.b2_toiMaxTime, profile_toi.elapsedTime); + b2TimeOfImpact.b2_toiTime += profile_toi.elapsedTime +} +b2TimeOfImpact._temp_sweepA = new b2Sweep(); +b2TimeOfImpact._temp_sweepB = new b2Sweep(); +b2TimeOfImpact.b2_toiTime = 0; +b2TimeOfImpact.b2_toiMaxTime = 0; +b2TimeOfImpact.b2_toiCalls = 0; +b2TimeOfImpact.b2_toiIters = 0; +b2TimeOfImpact.b2_toiMaxIters = 0; +b2TimeOfImpact.b2_toiRootIters = 0; +b2TimeOfImpact.b2_toiMaxRootIters = 0; +"use strict"; + +function b2BodyDef() { + this.type = b2Body.b2_staticBody; + this.position = new b2Vec2(0, 0); + this.angle = 0; + this.linearVelocity = new b2Vec2(0, 0); + this.angularVelocity = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.allowSleep = true; + this.awake = true; + this.fixedRotation = false; + this.bullet = false; + this.active = true; + this.userData = null; + this.gravityScale = 1; + Object.seal(this) +} +b2BodyDef.prototype = { + _deserialize: function (data) { + this.type = data.type; + this.position._deserialize(data.position); + this.angle = data.angle; + this.linearVelocity._deserialize(data.linearVelocity); + this.angularVelocity = data.angularVelocity; + this.linearDamping = data.linearDamping; + this.angularDamping = data.angularDamping; + this.allowSleep = data.allowSleep; + this.awake = data.awake; + this.fixedRotation = data.fixedRotation; + this.bullet = data.bullet; + this.active = data.active; + this.gravityScale = data.gravityScale + } +}; + +function b2Body(bd, world) { + this.m_islandIndex = 0; + this.m_flags = 0; + if (bd.bullet) { + this.m_flags |= b2Body.e_bulletFlag + } + if (bd.fixedRotation) { + this.m_flags |= b2Body.e_fixedRotationFlag + } + if (bd.allowSleep) { + this.m_flags |= b2Body.e_autoSleepFlag + } + if (bd.awake) { + this.m_flags |= b2Body.e_awakeFlag + } + if (bd.active) { + this.m_flags |= b2Body.e_activeFlag + } + this.m_world = world; + this.m_xf = new b2Transform(); + this.m_xf.p.Assign(bd.position); + this.m_xf.q.Set(bd.angle); + this.m_sweep = new b2Sweep(); + this.m_sweep.localCenter.SetZero(); + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = bd.angle; + this.m_sweep.a = bd.angle; + this.m_sweep.alpha0 = 0; + this.m_jointList = null; + this.m_contactList = null; + this.m_prev = null; + this.m_next = null; + this.m_linearVelocity = bd.linearVelocity.Clone(); + this.m_angularVelocity = bd.angularVelocity; + this.m_linearDamping = bd.linearDamping; + this.m_angularDamping = bd.angularDamping; + this.m_gravityScale = bd.gravityScale; + this.m_force = new b2Vec2(); + this.m_torque = 0; + this.m_sleepTime = 0; + this.m_type = bd.type; + if (this.m_type == b2Body.b2_dynamicBody) { + this.m_mass = 1; + this.m_invMass = 1 + } else { + this.m_mass = 0; + this.m_invMass = 0 + } + this.m_I = 0; + this.m_invI = 0; + this.m_userData = bd.userData; + this.m_fixtureList = null; + this.m_fixtureCount = 0 +} +b2Body.b2_staticBody = 0; +b2Body.b2_kinematicBody = 1; +b2Body.b2_dynamicBody = 2; +b2Body.e_islandFlag = 1; +b2Body.e_awakeFlag = 2; +b2Body.e_autoSleepFlag = 4; +b2Body.e_bulletFlag = 8; +b2Body.e_fixedRotationFlag = 16; +b2Body.e_activeFlag = 32; +b2Body.e_toiFlag = 64; +b2Body.m_local_oldCenter = new b2Vec2(); +b2Body.m_local_xf1 = new b2Transform(); +b2Body.prototype = { + CreateFixture: function (def, density) { + if (typeof (density) !== "undefined") { + var ndef = new b2FixtureDef(); + ndef.shape = def; + ndef.density = density; + return this.CreateFixture(ndef) + } + if (this.m_world.IsLocked() == true) { + return null + } + var fixture = new b2Fixture(); + fixture.Create(this, def); + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.CreateProxies(broadPhase, this.m_xf) + } + fixture.m_next = this.m_fixtureList; + this.m_fixtureList = fixture; + ++this.m_fixtureCount; + fixture.m_body = this; + if (fixture.m_density > 0) { + this.ResetMassData() + } + this.m_world.m_flags |= b2World.e_newFixture; + return fixture + }, + DestroyFixture: function (fixture) { + if (this.m_world.IsLocked() == true) { + return + } + var node = this.m_fixtureList; + var found = false; + while (node != null) { + if (node == fixture) { + this.m_fixtureList = node = fixture.m_next; + found = true; + break + } + node = node.m_next + } + var edge = this.m_contactList; + while (edge) { + var c = edge.contact; + edge = edge.next; + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + if (fixture == fixtureA || fixture == fixtureB) { + this.m_world.m_contactManager.Destroy(c) + } + } + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.DestroyProxies(broadPhase) + } + fixture.Destroy(); + fixture.m_body = null; + fixture.m_next = null; + --this.m_fixtureCount; + this.ResetMassData() + }, + SetTransform: function (position, angle) { + if (this.m_world.IsLocked() == true) { + return + } + this.m_xf.q.Set(angle); + this.m_xf.p.Assign(position); + this.m_sweep.c.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.a = angle; + this.m_sweep.c0.Assign(this.m_sweep.c); + this.m_sweep.a0 = angle; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, this.m_xf, this.m_xf) + } + }, + GetTransform: function () { + return this.m_xf + }, + GetPosition: function () { + return this.m_xf.p + }, + GetAngle: function () { + return this.m_sweep.a + }, + GetWorldCenter: function () { + return this.m_sweep.c + }, + GetLocalCenter: function () { + return this.m_sweep.localCenter + }, + SetLinearVelocity: function (v) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (b2Dot_v2_v2(v, v) > 0) { + this.SetAwake(true) + } + this.m_linearVelocity = v + }, + GetLinearVelocity: function () { + return this.m_linearVelocity + }, + SetAngularVelocity: function (w) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (w * w > 0) { + this.SetAwake(true) + } + this.m_angularVelocity = w + }, + GetAngularVelocity: function () { + return this.m_angularVelocity + }, + ApplyForce: function (force, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force); + this.m_torque += b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), force) + } + }, + ApplyForceToCenter: function (force, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force) + } + }, + ApplyTorque: function (torque, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_torque += torque + } + }, + ApplyLinearImpulse: function (impulse, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_linearVelocity.Add(b2Vec2.Multiply(this.m_invMass, impulse)); + this.m_angularVelocity += this.m_invI * b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), impulse) + } + }, + ApplyAngularImpulse: function (impulse, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_angularVelocity += this.m_invI * impulse + } + }, + GetMass: function () { + return this.m_mass + }, + GetInertia: function () { + return this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter) + }, + GetMassData: function (data) { + data.mass = this.m_mass; + data.I = this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter); + data.center = this.m_sweep.localCenter + }, + SetMassData: function (massData) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_mass = massData.mass; + if (this.m_mass <= 0) { + this.m_mass = 1 + } + this.m_invMass = 1 / this.m_mass; + if (massData.I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I = massData.I - this.m_mass * b2Dot_v2_v2(massData.center, massData.center); + this.m_invI = 1 / this.m_I + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(massData.center); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + ResetMassData: function () { + this.m_mass = 0; + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_sweep.localCenter.SetZero(); + if (this.m_type == b2Body.b2_staticBody || this.m_type == b2Body.b2_kinematicBody) { + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = this.m_sweep.a; + return + } + var localCenter = new b2Vec2(0, 0); + for (var f = this.m_fixtureList; f; f = f.m_next) { + if (f.m_density == 0) { + continue + } + var massData = new b2MassData(); + f.GetMassData(massData); + this.m_mass += massData.mass; + localCenter.Add(b2Vec2.Multiply(massData.mass, massData.center)); + this.m_I += massData.I + } + if (this.m_mass > 0) { + this.m_invMass = 1 / this.m_mass; + localCenter.Multiply(this.m_invMass) + } else { + this.m_mass = 1; + this.m_invMass = 1 + } + if (this.m_I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I -= this.m_mass * b2Dot_v2_v2(localCenter, localCenter); + this.m_invI = 1 / this.m_I + } else { + this.m_I = 0; + this.m_invI = 0 + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(localCenter); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + GetWorldPoint: function (localPoint) { + return b2Mul_t_v2(this.m_xf, localPoint) + }, + GetWorldVector: function (localVector) { + return b2Mul_r_v2(this.m_xf.q, localVector) + }, + GetLocalPoint: function (worldPoint) { + return b2MulT_t_v2(this.m_xf, worldPoint) + }, + GetLocalVector: function (worldVector) { + return b2MulT_r_v2(this.m_xf.q, worldVector) + }, + GetLinearVelocityFromWorldPoint: function (worldPoint) { + return b2Vec2.Add(this.m_linearVelocity, b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(worldPoint, this.m_sweep.c))) + }, + GetLinearVelocityFromLocalPoint: function (localPoint) { + return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint)) + }, + GetLinearDamping: function () { + return this.m_linearDamping + }, + SetLinearDamping: function (linearDamping) { + this.m_linearDamping = linearDamping + }, + GetAngularDamping: function () { + return this.m_angularDamping + }, + SetAngularDamping: function (angularDamping) { + this.m_angularDamping = angularDamping + }, + GetGravityScale: function () { + return this.m_gravityScale + }, + SetGravityScale: function (scale) { + this.m_gravityScale = scale + }, + SetType: function (type) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type == type) { + return + } + this.m_type = type; + this.ResetMassData(); + if (this.m_type == b2Body.b2_staticBody) { + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_sweep.a0 = this.m_sweep.a; + this.m_sweep.c0.Assign(this.m_sweep.c); + this.SynchronizeFixtures() + } + this.SetAwake(true); + this.m_force.SetZero(); + this.m_torque = 0; + var ce = this.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_world.m_contactManager.Destroy(ce0.contact) + } + this.m_contactList = null; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + var proxyCount = f.m_proxyCount; + for (var i = 0; i < proxyCount; ++i) { + broadPhase.TouchProxy(f.m_proxies[i].proxyId) + } + } + }, + GetType: function () { + return this.m_type + }, + SetBullet: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_bulletFlag + } else { + this.m_flags &= ~b2Body.e_bulletFlag + } + }, + IsBullet: function () { + return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag + }, + SetSleepingAllowed: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_autoSleepFlag + } else { + this.m_flags &= ~b2Body.e_autoSleepFlag; + this.SetAwake(true) + } + }, + IsSleepingAllowed: function () { + return (this.m_flags & b2Body.e_autoSleepFlag) == b2Body.e_autoSleepFlag + }, + SetAwake: function (flag) { + if (flag) { + if ((this.m_flags & b2Body.e_awakeFlag) == 0) { + this.m_flags |= b2Body.e_awakeFlag; + this.m_sleepTime = 0 + } + } else { + this.m_flags &= ~b2Body.e_awakeFlag; + this.m_sleepTime = 0; + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_force.SetZero(); + this.m_torque = 0 + } + }, + IsAwake: function () { + return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag + }, + SetActive: function (flag) { + if (flag == this.IsActive()) { + return + } + if (flag) { + this.m_flags |= b2Body.e_activeFlag; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.CreateProxies(broadPhase, this.m_xf) + } + } else { + this.m_flags &= ~b2Body.e_activeFlag; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.DestroyProxies(broadPhase) + } + var ce = this.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_world.m_contactManager.Destroy(ce0.contact) + } + this.m_contactList = null + } + }, + IsActive: function () { + return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag + }, + SetFixedRotation: function (flag) { + var status = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag; + if (status == flag) { + return + } + if (flag) { + this.m_flags |= b2Body.e_fixedRotationFlag + } else { + this.m_flags &= ~b2Body.e_fixedRotationFlag + } + this.m_angularVelocity = 0; + this.ResetMassData() + }, + IsFixedRotation: function () { + return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag + }, + GetFixtureList: function () { + return this.m_fixtureList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactList + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + GetWorld: function () { + return this.m_world + }, + SynchronizeFixtures: function () { + b2Body.m_local_xf1.q.Set(this.m_sweep.a0); + b2Body.m_local_xf1.p.Assign(b2Vec2.Subtract(this.m_sweep.c0, b2Mul_r_v2(b2Body.m_local_xf1.q, this.m_sweep.localCenter))); + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, b2Body.m_local_xf1, this.m_xf) + } + }, + SynchronizeTransform: function () { + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + ShouldCollide: function (other) { + if (this.m_type != b2Body.b2_dynamicBody && other.m_type != b2Body.b2_dynamicBody) { + return false + } + for (var jn = this.m_jointList; jn; jn = jn.next) { + if (jn.other == other) { + if (jn.joint.m_collideConnected == false) { + return false + } + } + } + return true + }, + Advance: function (alpha) { + this.m_sweep.Advance(alpha); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_sweep.a = this.m_sweep.a0; + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + _serialize: function (out) { + var obj = out || {}; + obj.fixtures = null; + obj.type = this.m_type; + obj.position = this.GetPosition()._serialize(); + obj.angle = this.GetAngle(); + obj.linearVelocity = this.GetLinearVelocity()._serialize(); + obj.angularVelocity = this.GetAngularVelocity(); + obj.linearDamping = this.GetLinearDamping(); + obj.angularDamping = this.GetAngularDamping(); + obj.allowSleep = this.IsSleepingAllowed(); + obj.awake = this.IsAwake(); + obj.fixedRotation = this.IsFixedRotation(); + obj.bullet = this.IsBullet(); + obj.active = this.IsActive(); + obj.gravityScale = this.GetGravityScale(); + return obj + } +}; +"use strict"; + +function b2Filter() { + this.categoryBits = 1; + this.maskBits = 65535; + this.groupIndex = 0 +} +b2Filter.prototype = { + Clone: function () { + var filter = new b2Filter(); + filter.categoryBits = this.categoryBits; + filter.maskBits = this.maskBits; + filter.groupIndex = this.groupIndex; + return filter + }, + Assign: function (filter) { + this.categoryBits = filter.categoryBits; + this.maskBits = filter.maskBits; + this.groupIndex = filter.groupIndex + }, + _serialize: function (out) { + var obj = out || {}; + obj.categoryBits = this.categoryBits; + obj.maskBits = this.maskBits; + obj.groupIndex = this.groupIndex; + return obj + }, + _deserialize: function (data) { + this.categoryBits = data.categoryBits; + this.maskBits = data.maskBits; + this.groupIndex = data.groupIndex + } +}; + +function b2FixtureDef() { + this.shape = null; + this.userData = null; + this.friction = 0.2; + this.restitution = 0; + this.density = 0; + this.isSensor = false; + this.filter = new b2Filter(); + Object.seal(this) +} +b2FixtureDef.prototype = { + _deserialize: function (data) { + this.friction = data.friction; + this.restitution = data.restitution; + this.density = data.density; + this.isSensor = data.isSensor; + this.filter._deserialize(data.filter) + } +}; + +function b2FixtureProxy() { + this.aabb = new b2AABB(); + this.fixture = null; + this.childIndex = 0; + this.proxyId = 0 +} + +function b2Fixture() { + this.m_userData = null; + this.m_body = null; + this.m_next = null; + this.m_proxies = null; + this.m_proxyCount = 0; + this.m_shape = null; + this.m_density = 0; + this.m_filter = new b2Filter(); + this.m_isSensor = false; + this.m_friction = 0; + this.m_restitution = 0 +} +b2Fixture.prototype = { + GetType: function () { + return this.m_shape.GetType() + }, + GetShape: function () { + return this.m_shape + }, + SetSensor: function (sensor) { + if (sensor != this.m_isSensor) { + this.m_body.SetAwake(true); + this.m_isSensor = sensor + } + }, + IsSensor: function () { + return this.m_isSensor + }, + SetFilterData: function (filter) { + this.m_filter = filter; + this.Refilter() + }, + GetFilterData: function () { + return this.m_filter + }, + Refilter: function () { + if (this.m_body == null) { + return + } + var edge = this.m_body.GetContactList(); + while (edge) { + var contact = edge.contact; + var fixtureA = contact.GetFixtureA(); + var fixtureB = contact.GetFixtureB(); + if (fixtureA == this || fixtureB == this) { + contact.FlagForFiltering() + } + edge = edge.next + } + var world = this.m_body.GetWorld(); + if (world == null) { + return + } + var broadPhase = world.m_contactManager.m_broadPhase; + for (var i = 0; i < this.m_proxyCount; ++i) { + broadPhase.TouchProxy(this.m_proxies[i].proxyId) + } + }, + GetBody: function () { + return this.m_body + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + TestPoint: function (p) { + return this.m_shape.TestPoint(this.m_body.GetTransform(), p) + }, + RayCast: function (output, input, childIndex) { + return this.m_shape.RayCast(output, input, this.m_body.GetTransform(), childIndex) + }, + GetMassData: function (massData) { + this.m_shape.ComputeMass(massData, this.m_density) + }, + SetDensity: function (density) { + this.m_density = density + }, + GetDensity: function () { + return this.m_density + }, + GetFriction: function () { + return this.m_friction + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetRestitution: function () { + return this.m_restitution + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetAABB: function (childIndex) { + return this.m_proxies[childIndex].aabb + }, + Create: function (body, def) { + this.m_userData = def.userData; + this.m_friction = def.friction; + this.m_restitution = def.restitution; + this.m_body = body; + this.m_next = null; + this.m_filter.Assign(def.filter); + this.m_isSensor = def.isSensor; + this.m_shape = def.shape.Clone(); + var childCount = this.m_shape.GetChildCount(); + this.m_proxies = new Array(childCount); + for (var i = 0; i < childCount; ++i) { + this.m_proxies[i] = new b2FixtureProxy(); + this.m_proxies[i].fixture = null; + this.m_proxies[i].proxyId = b2BroadPhase.e_nullProxy + } + this.m_proxyCount = 0; + this.m_density = def.density + }, + Destroy: function () { + this.m_proxies = null; + this.m_shape = null + }, + CreateProxies: function (broadPhase, xf) { + this.m_proxyCount = this.m_shape.GetChildCount(); + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + this.m_shape.ComputeAABB(proxy.aabb, xf, i); + proxy.proxyId = broadPhase.CreateProxy(proxy.aabb, proxy); + proxy.fixture = this; + proxy.childIndex = i + } + }, + DestroyProxies: function (broadPhase) { + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + broadPhase.DestroyProxy(proxy.proxyId); + proxy.proxyId = b2BroadPhase.e_nullProxy + } + this.m_proxyCount = 0 + }, + Synchronize: function (broadPhase, transform1, transform2) { + if (this.m_proxyCount == 0) { + return + } + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + var aabb1 = new b2AABB(), + aabb2 = new b2AABB(); + this.m_shape.ComputeAABB(aabb1, transform1, proxy.childIndex); + this.m_shape.ComputeAABB(aabb2, transform2, proxy.childIndex); + proxy.aabb.Combine(aabb1, aabb2); + var displacement = b2Vec2.Subtract(transform2.p, transform1.p); + broadPhase.MoveProxy(proxy.proxyId, proxy.aabb, displacement) + } + }, + _serialize: function (out) { + var obj = out || {}; + obj.shape = null; + obj.friction = this.m_friction; + obj.restitution = this.m_restitution; + obj.density = this.m_density; + obj.isSensor = this.m_isSensor; + obj.filter = this.m_filter._serialize(); + return obj + } +}; +"use strict"; + +function b2DestructionListener() {} +b2DestructionListener.prototype = { + SayGoodbyeJoint: function (joint) {}, + SayGoodbyeFixture: function (fixture) {} +}; + +function b2ContactFilter() {} +b2ContactFilter.prototype = { + ShouldCollide: function (fixtureA, fixtureB) { + var filterA = fixtureA.GetFilterData(); + var filterB = fixtureB.GetFilterData(); + if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { + return filterA.groupIndex > 0 + } + var collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; + return collide + } +}; + +function b2ContactImpulse() { + this.normalImpulses = new Array(b2_maxManifoldPoints); + this.tangentImpulses = new Array(b2_maxManifoldPoints); + this.count = 0 +} + +function b2ContactListener() {} +b2ContactListener.prototype = { + BeginContact: function (contact) {}, + EndContact: function (contact) {}, + PreSolve: function (contact, oldManifold) {}, + PostSolve: function (contact, impulse) {} +}; + +function b2QueryCallback() {} +b2QueryCallback.prototype = { + ReportFixture: function (fixture) {} +}; + +function b2RayCastCallback() {} +b2RayCastCallback.prototype = { + ReportFixture: function (fixture, point, normal, fraction) {} +}; +"use strict"; + +function b2TimeStep() { + this.dt = 0; + this.inv_dt = 0; + this.dtRatio = 0; + this.velocityIterations = 0; + this.positionIterations = 0; + this.warmStarting = false +} + +function b2Position() { + this.c = new b2Vec2(); + this.a = 0 +} + +function b2Velocity() { + this.v = new b2Vec2(); + this.w = 0 +} + +function b2SolverData() { + this.step = new b2TimeStep(); + this.positions = null; + this.velocities = null +} +"use strict"; +var profile_world_step = b2Profiler.create("step"); +var profile_world_collide = b2Profiler.create("collide", "step"); +var profile_world_solve = b2Profiler.create("solve", "step"); +var profile_world_solveTOI = b2Profiler.create("solveTOI", "step"); +var profile_world_broadphase = b2Profiler.create("broadphase", "step"); + +function b2World(gravity) { + this.m_contactManager = new b2ContactManager(); + this.m_destructionListener = null; + this.g_debugDraw = null; + this.m_bodyList = null; + this.m_jointList = null; + this.m_bodyCount = 0; + this.m_jointCount = 0; + this.m_warmStarting = true; + this.m_continuousPhysics = true; + this.m_subStepping = false; + this.m_stepComplete = true; + this.m_allowSleep = true; + this.m_gravity = gravity; + this.m_flags = b2World.e_clearForces; + this.m_inv_dt0 = 0; + this.p_step = new b2TimeStep(); + this.p_island = new b2Island() +} + +function b2WorldQueryWrapper() { + this.broadPhase = null; + this.callback = null +} +b2WorldQueryWrapper.prototype = { + QueryCallback: function (proxyId) { + var proxy = this.broadPhase.GetUserData(proxyId); + return this.callback.ReportFixture(proxy.fixture) + } +}; + +function b2WorldRayCastWrapper() { + this.broadPhase = null; + this.callback = null +} +b2WorldRayCastWrapper.prototype = { + RayCastCallback: function (input, proxyId) { + var userData = this.broadPhase.GetUserData(proxyId); + var proxy = userData; + var fixture = proxy.fixture; + var index = proxy.childIndex; + var output = new b2RayCastOutput(); + var hit = fixture.RayCast(output, input, index); + if (hit) { + var fraction = output.fraction; + var point = b2Vec2.Add(b2Vec2.Multiply((1 - fraction), input.p1), b2Vec2.Multiply(fraction, input.p2)); + return this.callback.ReportFixture(fixture, point, output.normal, fraction) + } + return input.maxFraction + } +}; +b2World.m_local_sweep_backupA = new b2Sweep(); +b2World.m_local_sweep_backupB = new b2Sweep(); +b2World.m_local_sweep_backupC = new b2Sweep(); +b2World.prototype = { + Destroy: function () { + var b = this.m_bodyList; + while (b) { + var bNext = b.m_next; + var f = b.m_fixtureList; + while (f) { + var fNext = f.m_next; + f.m_proxyCount = 0; + f.Destroy(); + f = fNext + } + b = bNext + } + }, + SetDestructionListener: function (listener) { + this.m_destructionListener = listener + }, + SetContactFilter: function (filter) { + this.m_contactManager.m_contactFilter = filter + }, + SetContactListener: function (listener) { + this.m_contactManager.m_contactListener = listener + }, + SetDebugDraw: function (debugDraw) { + this.g_debugDraw = debugDraw + }, + CreateBody: function (def) { + if (this.IsLocked()) { + return null + } + var b = new b2Body(def, this); + b.m_prev = null; + b.m_next = this.m_bodyList; + if (this.m_bodyList) { + this.m_bodyList.m_prev = b + } + this.m_bodyList = b; + ++this.m_bodyCount; + return b + }, + DestroyBody: function (b) { + if (this.IsLocked()) { + return + } + var je = b.m_jointList; + while (je) { + var je0 = je; + je = je.next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeJoint(je0.joint) + } + this.DestroyJoint(je0.joint); + b.m_jointList = je + } + b.m_jointList = null; + var ce = b.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_contactManager.Destroy(ce0.contact) + } + b.m_contactList = null; + var f = b.m_fixtureList; + while (f) { + var f0 = f; + f = f.m_next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeFixture(f0) + } + f0.DestroyProxies(this.m_contactManager.m_broadPhase); + f0.Destroy(); + b.m_fixtureList = f; + b.m_fixtureCount -= 1 + } + b.m_fixtureList = null; + b.m_fixtureCount = 0; + if (b.m_prev) { + b.m_prev.m_next = b.m_next + } + if (b.m_next) { + b.m_next.m_prev = b.m_prev + } + if (b == this.m_bodyList) { + this.m_bodyList = b.m_next + } + b.m_destroyed = true; + --this.m_bodyCount + }, + CreateJoint: function (def) { + if (this.IsLocked()) { + return null + } + var j = b2Joint.Create(def); + j.m_prev = null; + j.m_next = this.m_jointList; + if (this.m_jointList) { + this.m_jointList.m_prev = j + } + this.m_jointList = j; + ++this.m_jointCount; + j.m_edgeA.joint = j; + j.m_edgeA.other = j.m_bodyB; + j.m_edgeA.prev = null; + j.m_edgeA.next = j.m_bodyA.m_jointList; + if (j.m_bodyA.m_jointList) { + j.m_bodyA.m_jointList.prev = j.m_edgeA + } + j.m_bodyA.m_jointList = j.m_edgeA; + j.m_edgeB.joint = j; + j.m_edgeB.other = j.m_bodyA; + j.m_edgeB.prev = null; + j.m_edgeB.next = j.m_bodyB.m_jointList; + if (j.m_bodyB.m_jointList) { + j.m_bodyB.m_jointList.prev = j.m_edgeB + } + j.m_bodyB.m_jointList = j.m_edgeB; + var bodyA = def.bodyA; + var bodyB = def.bodyB; + if (def.collideConnected == false) { + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() + } + edge = edge.next + } + } + return j + }, + DestroyJoint: function (j) { + if (this.IsLocked()) { + return + } + var collideConnected = j.m_collideConnected; + if (j.m_prev) { + j.m_prev.m_next = j.m_next + } + if (j.m_next) { + j.m_next.m_prev = j.m_prev + } + if (j == this.m_jointList) { + this.m_jointList = j.m_next + } + var bodyA = j.m_bodyA; + var bodyB = j.m_bodyB; + bodyA.SetAwake(true); + bodyB.SetAwake(true); + if (j.m_edgeA.prev) { + j.m_edgeA.prev.next = j.m_edgeA.next + } + if (j.m_edgeA.next) { + j.m_edgeA.next.prev = j.m_edgeA.prev + } + if (j.m_edgeA == bodyA.m_jointList) { + bodyA.m_jointList = j.m_edgeA.next + } + j.m_edgeA.prev = null; + j.m_edgeA.next = null; + if (j.m_edgeB.prev) { + j.m_edgeB.prev.next = j.m_edgeB.next + } + if (j.m_edgeB.next) { + j.m_edgeB.next.prev = j.m_edgeB.prev + } + if (j.m_edgeB == bodyB.m_jointList) { + bodyB.m_jointList = j.m_edgeB.next + } + j.m_edgeB.prev = null; + j.m_edgeB.next = null; + b2Joint.Destroy(j); + --this.m_jointCount; + if (collideConnected == false) { + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() + } + edge = edge.next + } + } + }, + Step: function (dt, velocityIterations, positionIterations) { + profile_world_step.start(); + if (this.m_flags & b2World.e_newFixture) { + this.m_contactManager.FindNewContacts(); + this.m_flags &= ~b2World.e_newFixture + } + this.m_flags |= b2World.e_locked; + this.p_step.dt = dt; + this.p_step.velocityIterations = velocityIterations; + this.p_step.positionIterations = positionIterations; + if (dt > 0) { + this.p_step.inv_dt = 1 / dt + } else { + this.p_step.inv_dt = 0 + } + this.p_step.dtRatio = this.m_inv_dt0 * dt; + this.p_step.warmStarting = this.m_warmStarting; + profile_world_collide.start(); + this.m_contactManager.Collide(); + profile_world_collide.stop(); + if (this.m_stepComplete && this.p_step.dt > 0) { + profile_world_solve.start(); + this.Solve(this.p_step); + profile_world_solve.stop() + } + if (this.m_continuousPhysics && this.p_step.dt > 0) { + profile_world_solveTOI.start(); + this.SolveTOI(this.p_step); + profile_world_solveTOI.stop() + } + if (this.p_step.dt > 0) { + this.m_inv_dt0 = this.p_step.inv_dt + } + if (this.m_flags & b2World.e_clearForces) { + this.ClearForces() + } + this.m_flags &= ~b2World.e_locked; + profile_world_step.stop() + }, + ClearForces: function () { + for (var body = this.m_bodyList; body; body = body.GetNext()) { + body.m_force.x = body.m_force.y = 0; + body.m_torque = 0 + } + }, + DrawDebugData: function () { + if (this.g_debugDraw == null) { + return + } + var flags = this.g_debugDraw.GetFlags(); + if (flags & b2Draw.e_shapeBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform(); + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + if (b.IsActive() == false) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.3)) + } else { + if (b.GetType() == b2Body.b2_staticBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.9, 0.5)) + } else { + if (b.GetType() == b2Body.b2_kinematicBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.9)) + } else { + if (b.IsAwake() == false) { + this.DrawShape(f, xf, new b2Color(0.6, 0.6, 0.6)) + } else { + this.DrawShape(f, xf, new b2Color(0.9, 0.7, 0.7)) + } + } + } + } + } + } + } + if (flags & b2Draw.e_jointBit) { + for (var j = this.m_jointList; j; j = j.GetNext()) { + this.DrawJoint(j) + } + } + if (flags & b2Draw.e_pairBit) { + var color = new b2Color(0.3, 0.9, 0.9); + for (var c = this.m_contactManager.m_contactList; c; c = c.GetNext()) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var cA = fixtureA.GetAABB(c.GetChildIndexA()).GetCenter(); + var cB = fixtureB.GetAABB(c.GetChildIndexB()).GetCenter(); + this.g_debugDraw.DrawSegment(cA, cB, color) + } + } + if (flags & b2Draw.e_aabbBit) { + var color = new b2Color(0.9, 0.3, 0.9); + var bp = this.m_contactManager.m_broadPhase; + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if (b.IsActive() == false) { + continue + } + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + for (var i = 0; i < f.m_proxyCount; ++i) { + var proxy = f.m_proxies[i]; + var aabb = bp.GetFatAABB(proxy.proxyId); + var vs = []; + vs[0] = new b2Vec2(aabb.lowerBound.x, aabb.lowerBound.y); + vs[1] = new b2Vec2(aabb.upperBound.x, aabb.lowerBound.y); + vs[2] = new b2Vec2(aabb.upperBound.x, aabb.upperBound.y); + vs[3] = new b2Vec2(aabb.lowerBound.x, aabb.upperBound.y); + this.g_debugDraw.DrawPolygon(vs, 4, color) + } + } + } + } + if (flags & b2Draw.e_centerOfMassBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform().Clone(); + xf.p = b.GetWorldCenter(); + this.g_debugDraw.DrawTransform(xf) + } + } + }, + QueryAABB: function (callback, aabb) { + var wrapper = new b2WorldQueryWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + this.m_contactManager.m_broadPhase.Query(wrapper, aabb) + }, + RayCast: function (callback, point1, point2) { + var wrapper = new b2WorldRayCastWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + var input = new b2RayCastInput(); + input.maxFraction = 1; + input.p1 = point1; + input.p2 = point2; + this.m_contactManager.m_broadPhase.RayCast(wrapper, input) + }, + GetBodyList: function () { + return this.m_bodyList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactManager.m_contactList + }, + SetAllowSleeping: function (flag) { + if (flag == this.m_allowSleep) { + return + } + this.m_allowSleep = flag; + if (this.m_allowSleep == false) { + for (var b = this.m_bodyList; b; b = b.m_next) { + b.SetAwake(true) + } + } + }, + GetAllowSleeping: function () { + return this.m_allowSleep + }, + SetWarmStarting: function (flag) { + this.m_warmStarting = flag + }, + GetWarmStarting: function () { + return this.m_warmStarting + }, + SetContinuousPhysics: function (flag) { + this.m_continuousPhysics = flag + }, + GetContinuousPhysics: function () { + return this.m_continuousPhysics + }, + SetSubStepping: function (flag) { + this.m_subStepping = flag + }, + GetSubStepping: function () { + return this.m_subStepping + }, + GetProxyCount: function () { + return this.m_contactManager.m_broadPhase.GetProxyCount() + }, + GetBodyCount: function () { + return this.m_bodyCount + }, + GetJointCount: function () { + return this.m_jointCount + }, + GetContactCount: function () { + return this.m_contactManager.m_contactCount + }, + GetTreeHeight: function () { + return this.m_contactManager.m_broadPhase.GetTreeHeight() + }, + GetTreeBalance: function () { + return this.m_contactManager.m_broadPhase.GetTreeBalance() + }, + GetTreeQuality: function () { + return this.m_contactManager.m_broadPhase.GetTreeQuality() + }, + SetGravity: function (gravity) { + this.m_gravity = gravity + }, + GetGravity: function () { + return this.m_gravity + }, + IsLocked: function () { + return (this.m_flags & b2World.e_locked) == b2World.e_locked + }, + SetAutoClearForces: function (flag) { + if (flag) { + this.m_flags |= b2World.e_clearForces + } else { + this.m_flags &= ~b2World.e_clearForces + } + }, + GetAutoClearForces: function () { + return (this.m_flags & b2World.e_clearForces) == b2World.e_clearForces + }, + ShiftOrigin: function (newOrigin) { + if ((this.m_flags & b2World.e_locked) == b2World.e_locked) { + return + } + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_xf.p.Subtract(newOrigin); + b.m_sweep.c0.Subtract(newOrigin); + b.m_sweep.c.Subtract(newOrigin) + } + for (var j = this.m_jointList; j; j = j.m_next) { + j.ShiftOrigin(newOrigin) + } + this.m_contactManager.m_broadPhase.ShiftOrigin(newOrigin) + }, + GetContactManager: function () { + return this.m_contactManager + }, + Solve: function (step) { + this.p_island.Initialize(this.m_bodyCount, this.m_contactManager.m_contactCount, this.m_jointCount, this.m_contactManager.m_contactListener); + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_flags &= ~b2Body.e_islandFlag + } + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + c.m_flags &= ~b2Contact.e_islandFlag + } + for (var j = this.m_jointList; j; j = j.m_next) { + j.m_islandFlag = false + } + var stackSize = this.m_bodyCount; + var stack = new Array(stackSize); + for (var seed = this.m_bodyList; seed; seed = seed.m_next) { + if (seed.m_flags & b2Body.e_islandFlag) { + continue + } + if (seed.IsAwake() == false || seed.IsActive() == false) { + continue + } + if (seed.GetType() == b2Body.b2_staticBody) { + continue + } + this.p_island.Clear(); + var stackCount = 0; + stack[stackCount++] = seed; + seed.m_flags |= b2Body.e_islandFlag; + while (stackCount > 0) { + var b = stack[--stackCount]; + this.p_island.AddBody(b); + b.SetAwake(true); + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + for (var ce = b.m_contactList; ce; ce = ce.next) { + var contact = ce.contact; + if (contact.m_flags & b2Contact.e_islandFlag) { + continue + } + if (contact.IsEnabled() == false || contact.IsTouching() == false) { + continue + } + var sensorA = contact.m_fixtureA.m_isSensor; + var sensorB = contact.m_fixtureB.m_isSensor; + if (sensorA || sensorB) { + continue + } + this.p_island.AddContact(contact); + contact.m_flags |= b2Contact.e_islandFlag; + var other = ce.other; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag + } + for (var je = b.m_jointList; je; je = je.next) { + if (je.joint.m_islandFlag == true) { + continue + } + var other = je.other; + if (other.IsActive() == false) { + continue + } + this.p_island.AddJoint(je.joint); + je.joint.m_islandFlag = true; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag + } + } + this.p_island.Solve(step, this.m_gravity, this.m_allowSleep); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var b = this.p_island.m_bodies[i]; + if (b.GetType() == b2Body.b2_staticBody) { + b.m_flags &= ~b2Body.e_islandFlag + } + } + } + profile_world_broadphase.start(); + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if ((b.m_flags & b2Body.e_islandFlag) == 0) { + continue + } + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + b.SynchronizeFixtures() + } + this.m_contactManager.FindNewContacts(); + profile_world_broadphase.stop() + }, + SolveTOI: function (step) { + this.p_island.Initialize(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, this.m_contactManager.m_contactListener); + if (this.m_stepComplete) { + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_flags &= ~b2Body.e_islandFlag; + b.m_sweep.alpha0 = 0 + } + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag); + c.m_toiCount = 0; + c.m_toi = 1 + } + } + for (;;) { + var minContact = null; + var minAlpha = 1; + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + if (c.IsEnabled() == false) { + continue + } + if (c.m_toiCount > b2_maxSubSteps) { + continue + } + var alpha = 1; + if (c.m_flags & b2Contact.e_toiFlag) { + alpha = c.m_toi + } else { + var fA = c.GetFixtureA(); + var fB = c.GetFixtureB(); + if (fA.IsSensor() || fB.IsSensor()) { + continue + } + var bA = fA.GetBody(); + var bB = fB.GetBody(); + var typeA = bA.m_type; + var typeB = bB.m_type; + var activeA = bA.IsAwake() && typeA != b2Body.b2_staticBody; + var activeB = bB.IsAwake() && typeB != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + continue + } + var collideA = bA.IsBullet() || typeA != b2Body.b2_dynamicBody; + var collideB = bB.IsBullet() || typeB != b2Body.b2_dynamicBody; + if (collideA == false && collideB == false) { + continue + } + var alpha0 = bA.m_sweep.alpha0; + if (bA.m_sweep.alpha0 < bB.m_sweep.alpha0) { + alpha0 = bB.m_sweep.alpha0; + bA.m_sweep.Advance(alpha0) + } else { + if (bB.m_sweep.alpha0 < bA.m_sweep.alpha0) { + alpha0 = bA.m_sweep.alpha0; + bB.m_sweep.Advance(alpha0) + } + } + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); + var input = new b2TOIInput(); + input.proxyA.Set(fA.GetShape(), indexA); + input.proxyB.Set(fB.GetShape(), indexB); + input.sweepA.Assign(bA.m_sweep); + input.sweepB.Assign(bB.m_sweep); + input.tMax = 1; + var output = new b2TOIOutput(); + b2TimeOfImpact(output, input); + var beta = output.t; + if (output.state == b2TOIOutput.e_touching) { + alpha = b2Min(alpha0 + (1 - alpha0) * beta, 1) + } else { + alpha = 1 + } + c.m_toi = alpha; + c.m_flags |= b2Contact.e_toiFlag + } + if (alpha < minAlpha) { + minContact = c; + minAlpha = alpha + } + } + if (minContact == null || 1 - 10 * b2_epsilon < minAlpha) { + this.m_stepComplete = true; + break + } + var fA = minContact.GetFixtureA(); + var fB = minContact.GetFixtureB(); + var bA = fA.GetBody(); + var bB = fB.GetBody(); + b2World.m_local_sweep_backupA.Assign(bA.m_sweep); + b2World.m_local_sweep_backupB.Assign(bB.m_sweep); + bA.Advance(minAlpha); + bB.Advance(minAlpha); + minContact.Update(this.m_contactManager.m_contactListener); + minContact.m_flags &= ~b2Contact.e_toiFlag; + ++minContact.m_toiCount; + if (minContact.IsEnabled() == false || minContact.IsTouching() == false) { + minContact.SetEnabled(false); + bA.m_sweep.Assign(b2World.m_local_sweep_backupA); + bB.m_sweep.Assign(b2World.m_local_sweep_backupB); + bA.SynchronizeTransform(); + bB.SynchronizeTransform(); + continue + } + bA.SetAwake(true); + bB.SetAwake(true); + this.p_island.Clear(); + this.p_island.AddBody(bA); + this.p_island.AddBody(bB); + this.p_island.AddContact(minContact); + bA.m_flags |= b2Body.e_islandFlag; + bB.m_flags |= b2Body.e_islandFlag; + minContact.m_flags |= b2Contact.e_islandFlag; + var bodies = [bA, bB]; + for (var i = 0; i < 2; ++i) { + var body = bodies[i]; + if (body.m_type == b2Body.b2_dynamicBody) { + for (var ce = body.m_contactList; ce; ce = ce.next) { + if (this.p_island.m_bodyCount == this.p_island.m_bodyCapacity) { + break + } + if (this.p_island.m_contactCount == this.p_island.m_contactCapacity) { + break + } + var contact = ce.contact; + if (contact.m_flags & b2Contact.e_islandFlag) { + continue + } + var other = ce.other; + if (other.m_type == b2Body.b2_dynamicBody && body.IsBullet() == false && other.IsBullet() == false) { + continue + } + var sensorA = contact.m_fixtureA.m_isSensor; + var sensorB = contact.m_fixtureB.m_isSensor; + if (sensorA || sensorB) { + continue + } + b2World.m_local_sweep_backupC.Assign(other.m_sweep); + if ((other.m_flags & b2Body.e_islandFlag) == 0) { + other.Advance(minAlpha) + } + contact.Update(this.m_contactManager.m_contactListener); + if (contact.IsEnabled() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } + if (contact.IsTouching() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } + contact.m_flags |= b2Contact.e_islandFlag; + this.p_island.AddContact(contact); + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + other.m_flags |= b2Body.e_islandFlag; + if (other.m_type != b2Body.b2_staticBody) { + other.SetAwake(true) + } + this.p_island.AddBody(other) + } + } + } + var subStep = new b2TimeStep(); + subStep.dt = (1 - minAlpha) * step.dt; + subStep.inv_dt = 1 / subStep.dt; + subStep.dtRatio = 1; + subStep.positionIterations = 20; + subStep.velocityIterations = step.velocityIterations; + subStep.warmStarting = false; + this.p_island.SolveTOI(subStep, bA.m_islandIndex, bB.m_islandIndex); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var body = this.p_island.m_bodies[i]; + body.m_flags &= ~b2Body.e_islandFlag; + if (body.m_type != b2Body.b2_dynamicBody) { + continue + } + body.SynchronizeFixtures(); + for (var ce = body.m_contactList; ce; ce = ce.next) { + ce.contact.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag) + } + } + this.m_contactManager.FindNewContacts(); + if (this.m_subStepping) { + this.m_stepComplete = false; + break + } + } + }, + DrawJoint: function (joint) { + var bodyA = joint.GetBodyA(); + var bodyB = joint.GetBodyB(); + var xf1 = bodyA.GetTransform(); + var xf2 = bodyB.GetTransform(); + var x1 = xf1.p; + var x2 = xf2.p; + var p1 = joint.GetAnchorA(); + var p2 = joint.GetAnchorB(); + var color = new b2Color(0.5, 0.8, 0.8); + switch (joint.GetType()) { + case b2Joint.e_distanceJoint: + this.g_debugDraw.DrawSegment(p1, p2, color); + break; + case b2Joint.e_pulleyJoint: + var pulley = joint; + var s1 = pulley.GetGroundAnchorA(); + var s2 = pulley.GetGroundAnchorB(); + this.g_debugDraw.DrawSegment(s1, p1, color); + this.g_debugDraw.DrawSegment(s2, p2, color); + this.g_debugDraw.DrawSegment(s1, s2, color); + break; + case b2Joint.e_mouseJoint: + break; + case b2Joint.e_motorJoint: + this.g_debugDraw.DrawPoint(joint.GetLinearOffset(), 5, color); + default: + this.g_debugDraw.DrawSegment(x1, p1, color); + this.g_debugDraw.DrawSegment(p1, p2, color); + this.g_debugDraw.DrawSegment(x2, p2, color) + } + }, + DrawShape: function (fixture, xf, color) { + switch (fixture.GetType()) { + case b2Shape.e_circle: + var circle = fixture.GetShape(); + var center = b2Mul_t_v2(xf, circle.m_p); + var radius = circle.m_radius; + var axis = b2Mul_r_v2(xf.q, new b2Vec2(1, 0)); + this.g_debugDraw.DrawSolidCircle(center, radius, axis, color); + break; + case b2Shape.e_edge: + var edge = fixture.GetShape(); + var v1 = b2Mul_t_v2(xf, edge.m_vertex1); + var v2 = b2Mul_t_v2(xf, edge.m_vertex2); + this.g_debugDraw.DrawSegment(v1, v2, color); + break; + case b2Shape.e_chain: + var chain = fixture.GetShape(); + var count = chain.m_count; + var vertices = chain.m_vertices; + var v1 = b2Mul_t_v2(xf, vertices[0]); + for (var i = 1; i < count; ++i) { + var v2 = b2Mul_t_v2(xf, vertices[i]); + this.g_debugDraw.DrawSegment(v1, v2, color); + v1 = v2 + } + break; + case b2Shape.e_polygon: + var poly = fixture.GetShape(); + var vertexCount = poly.m_count; + var vertices = new Array(b2_maxPolygonVertices); + for (var i = 0; i < vertexCount; ++i) { + vertices[i] = b2Mul_t_v2(xf, poly.m_vertices[i]) + } + this.g_debugDraw.DrawSolidPolygon(vertices, vertexCount, color); + break; + default: + break + } + } +}; +b2World.e_newFixture = 1; +b2World.e_locked = 2; +b2World.e_clearForces = 4; +"use strict"; + +function b2MixFriction(friction1, friction2) { + return b2Sqrt(friction1 * friction2) +} + +function b2MixRestitution(restitution1, restitution2) { + return restitution1 > restitution2 ? restitution1 : restitution2 +} + +function b2ContactRegister() { + this.fcn = null; + this.primary = false +} + +function b2ContactEdge() { + this.other = null; + this.contact = null; + this.prev = null; + this.next = null +} + +function b2Contact() { + this.m_nodeA = new b2ContactEdge(); + this.m_nodeB = new b2ContactEdge(); + this.m_manifold = new b2Manifold() +} +b2Contact.m_local_tempManifold = new b2Manifold(); +b2Contact.prototype = { + Create: function (fA, indexA, fB, indexB) { + this.m_toi = 0; + this.m_flags = b2Contact.e_enabledFlag; + this.m_fixtureA = fA || null; + this.m_fixtureB = fB || null; + this.m_indexA = indexA || 0; + this.m_indexB = indexB || 0; + this.m_manifold.pointCount = 0; + this.m_prev = null; + this.m_next = null; + this.m_nodeA.contact = null; + this.m_nodeA.prev = null; + this.m_nodeA.next = null; + this.m_nodeA.other = null; + this.m_nodeB.contact = null; + this.m_nodeB.prev = null; + this.m_nodeB.next = null; + this.m_nodeB.other = null; + this.m_toiCount = 0; + if (fA) { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction); + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + } else { + this.m_friction = 0; + this.m_restitution = 0 + } + this.m_tangentSpeed = 0 + }, + GetManifold: function () { + return this.m_manifold + }, + GetWorldManifold: function (worldManifold) { + var bodyA = this.m_fixtureA.GetBody(); + var bodyB = this.m_fixtureB.GetBody(); + var shapeA = this.m_fixtureA.GetShape(); + var shapeB = this.m_fixtureB.GetShape(); + worldManifold.Initialize(this.m_manifold, bodyA.GetTransform(), shapeA.m_radius, bodyB.GetTransform(), shapeB.m_radius) + }, + IsTouching: function () { + return (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag + }, + SetEnabled: function (flag) { + if (flag) { + this.m_flags |= b2Contact.e_enabledFlag + } else { + this.m_flags &= ~b2Contact.e_enabledFlag + } + }, + IsEnabled: function () { + return (this.m_flags & b2Contact.e_enabledFlag) == b2Contact.e_enabledFlag + }, + GetNext: function () { + return this.m_next + }, + GetFixtureA: function () { + return this.m_fixtureA + }, + GetChildIndexA: function () { + return this.m_indexA + }, + GetFixtureB: function () { + return this.m_fixtureB + }, + GetChildIndexB: function () { + return this.m_indexB + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetFriction: function () { + return this.m_friction + }, + ResetFriction: function () { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction) + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetRestitution: function () { + return this.m_restitution + }, + ResetRestitution: function () { + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + }, + SetTangentSpeed: function (speed) { + this.m_tangentSpeed = speed + }, + GetTangentSpeed: function () { + return this.m_tangentSpeed + }, + Evaluate: function (manifold, xfA, xfB) {}, + FlagForFiltering: function () { + this.m_flags |= b2Contact.e_filterFlag + }, + m_oldManifold: null, + Update: function (listener) { + b2Contact.m_local_tempManifold.Assign(this.m_manifold); + this.m_flags |= b2Contact.e_enabledFlag; + var touching = false; + var wasTouching = (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag; + var sensorA = this.m_fixtureA.IsSensor(); + var sensorB = this.m_fixtureB.IsSensor(); + var sensor = sensorA || sensorB; + var bodyA = this.m_fixtureA.GetBody(); + var bodyB = this.m_fixtureB.GetBody(); + var xfA = bodyA.GetTransform(); + var xfB = bodyB.GetTransform(); + if (sensor) { + var shapeA = this.m_fixtureA.GetShape(); + var shapeB = this.m_fixtureB.GetShape(); + touching = b2TestShapeOverlap(shapeA, this.m_indexA, shapeB, this.m_indexB, xfA, xfB); + this.m_manifold.pointCount = 0 + } else { + this.Evaluate(this.m_manifold, xfA, xfB); + touching = this.m_manifold.pointCount > 0; + for (var i = 0; i < this.m_manifold.pointCount; ++i) { + var mp2 = this.m_manifold.points[i]; + mp2.normalImpulse = 0; + mp2.tangentImpulse = 0; + var id2 = mp2.id; + for (var j = 0; j < b2Contact.m_local_tempManifold.pointCount; ++j) { + var mp1 = b2Contact.m_local_tempManifold.points[j]; + if (mp1.id.Get() == id2.Get()) { + mp2.normalImpulse = mp1.normalImpulse; + mp2.tangentImpulse = mp1.tangentImpulse; + break + } + } + } + if (touching != wasTouching) { + bodyA.SetAwake(true); + bodyB.SetAwake(true) + } + } + if (touching) { + this.m_flags |= b2Contact.e_touchingFlag + } else { + this.m_flags &= ~b2Contact.e_touchingFlag + } + if (wasTouching == false && touching == true && listener) { + listener.BeginContact(this) + } + if (wasTouching == true && touching == false && listener) { + listener.EndContact(this) + } + if (sensor == false && touching && listener) { + listener.PreSolve(this, b2Contact.m_local_tempManifold) + } + } +}; +b2Contact.e_islandFlag = 1; +b2Contact.e_touchingFlag = 2; +b2Contact.e_enabledFlag = 4; +b2Contact.e_filterFlag = 8; +b2Contact.e_bulletHitFlag = 16; +b2Contact.e_toiFlag = 32; + +function b2CircleContact() { + this.parent.call(this) +} +b2CircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideCircles(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, unused1, fixtureB, unused2) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2CircleContact._extend(b2Contact); +var _local_temp_edgeShape = new b2EdgeShape(); + +function b2ChainAndCircleContact() { + this.parent.call(this) +} +b2ChainAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndCircle(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } +}; +b2ChainAndCircleContact._extend(b2Contact); + +function b2ChainAndPolygonContact() { + this.parent.call(this) +} +b2ChainAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndPolygon(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } +}; +b2ChainAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB) +}; +b2ChainAndPolygonContact._extend(b2Contact); + +function b2EdgeAndCircleContact() { + this.parent.call(this) +} +b2EdgeAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2EdgeAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndCircleContact(fixtureA, fixtureB) +}; +b2EdgeAndCircleContact._extend(b2Contact); + +function b2EdgeAndPolygonContact() { + this.parent.call(this) +} +b2EdgeAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndPolygon(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2EdgeAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndPolygonContact(fixtureA, fixtureB) +}; +b2EdgeAndPolygonContact._extend(b2Contact); + +function b2PolygonAndCircleContact() { + this.parent.call(this) +} +b2PolygonAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygonAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2PolygonAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonAndCircleContact(fixtureA, fixtureB) +}; +b2PolygonAndCircleContact._extend(b2Contact); + +function b2PolygonContact() { + this.parent.call(this) +} +b2PolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygons(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2PolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonContact(fixtureA, fixtureB) +}; +b2PolygonContact._extend(b2Contact); +b2Contact.AddType = function (fcn, type1, type2) { + if (!b2Contact.s_registers[type1]) { + b2Contact.s_registers[type1] = [] + } + b2Contact.s_registers[type1][type2] = new b2ContactRegister(); + b2Contact.s_registers[type1][type2].fcn = fcn; + b2Contact.s_registers[type1][type2].primary = true; + if (type1 != type2) { + if (!b2Contact.s_registers[type2]) { + b2Contact.s_registers[type2] = [] + } + b2Contact.s_registers[type2][type1] = new b2ContactRegister(); + b2Contact.s_registers[type2][type1].fcn = fcn; + b2Contact.s_registers[type2][type1].primary = false + } + fcn.garbage = []; + fcn.alloc = 2 +}; +b2Contact.InitializeRegisters = function () { + b2Contact.AddType(b2CircleContact, b2Shape.e_circle, b2Shape.e_circle); + b2Contact.AddType(b2PolygonAndCircleContact, b2Shape.e_polygon, b2Shape.e_circle); + b2Contact.AddType(b2PolygonContact, b2Shape.e_polygon, b2Shape.e_polygon); + b2Contact.AddType(b2EdgeAndCircleContact, b2Shape.e_edge, b2Shape.e_circle); + b2Contact.AddType(b2EdgeAndPolygonContact, b2Shape.e_edge, b2Shape.e_polygon); + b2Contact.AddType(b2ChainAndCircleContact, b2Shape.e_chain, b2Shape.e_circle); + b2Contact.AddType(b2ChainAndPolygonContact, b2Shape.e_chain, b2Shape.e_polygon) +}; +b2Contact.RetrieveGarbage = function (fcn) { + var contact; + if (contact = fcn.garbage.pop()) { + return contact + } + for (var i = 0; i < fcn.alloc - 1; ++i) { + fcn.garbage.push(new fcn()) + } + fcn.alloc += 32; + return new fcn() +}; +b2Contact.Create = function (fixtureA, indexA, fixtureB, indexB) { + if (b2Contact.s_initialized == false) { + b2Contact.InitializeRegisters(); + b2Contact.s_initialized = true + } + var type1 = fixtureA.GetType(); + var type2 = fixtureB.GetType(); + var fcn = b2Contact.s_registers[type1][type2].fcn; + if (fcn) { + var contact = b2Contact.RetrieveGarbage(fcn); + if (b2Contact.s_registers[type1][type2].primary) { + contact.Create(fixtureA, indexA, fixtureB, indexB) + } else { + contact.Create(fixtureB, indexB, fixtureA, indexA) + } + return contact + } + return null +}; +b2Contact.Destroy = function (contact) { + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + if (contact.m_manifold.pointCount > 0 && fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + fixtureA.GetBody().SetAwake(true); + fixtureB.GetBody().SetAwake(true) + } + var typeA = fixtureA.GetType(); + var typeB = fixtureB.GetType(); + b2Contact.s_registers[typeA][typeB].fcn.garbage.push(contact) +}; +b2Contact.s_registers = []; +b2Contact.s_initialized = false; +"use strict"; +var b2_defaultFilter = new b2ContactFilter(); +var b2_defaultListener = new b2ContactListener(); + +function b2ContactManager() { + this.m_broadPhase = new b2BroadPhase(); + this.m_contactList = null; + this.m_contactCount = 0; + this.m_contactFilter = b2_defaultFilter; + this.m_contactListener = b2_defaultListener +} +b2ContactManager.prototype = { + AddPair: function (proxyUserDataA, proxyUserDataB) { + var proxyA = proxyUserDataA; + var proxyB = proxyUserDataB; + var fixtureA = proxyA.fixture; + var fixtureB = proxyB.fixture; + var indexA = proxyA.childIndex; + var indexB = proxyB.childIndex; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (bodyA == bodyB) { + return + } + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + var fA = edge.contact.GetFixtureA(); + var fB = edge.contact.GetFixtureB(); + var iA = edge.contact.GetChildIndexA(); + var iB = edge.contact.GetChildIndexB(); + if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) { + return + } + if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { + return + } + } + edge = edge.next + } + if (bodyB.ShouldCollide(bodyA) == false) { + return + } + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + return + } + var c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); + if (c == null) { + return + } + fixtureA = c.GetFixtureA(); + fixtureB = c.GetFixtureB(); + indexA = c.GetChildIndexA(); + indexB = c.GetChildIndexB(); + bodyA = fixtureA.GetBody(); + bodyB = fixtureB.GetBody(); + c.m_prev = null; + c.m_next = this.m_contactList; + if (this.m_contactList != null) { + this.m_contactList.m_prev = c + } + this.m_contactList = c; + c.m_nodeA.contact = c; + c.m_nodeA.other = bodyB; + c.m_nodeA.prev = null; + c.m_nodeA.next = bodyA.m_contactList; + if (bodyA.m_contactList != null) { + bodyA.m_contactList.prev = c.m_nodeA + } + bodyA.m_contactList = c.m_nodeA; + c.m_nodeB.contact = c; + c.m_nodeB.other = bodyA; + c.m_nodeB.prev = null; + c.m_nodeB.next = bodyB.m_contactList; + if (bodyB.m_contactList != null) { + bodyB.m_contactList.prev = c.m_nodeB + } + bodyB.m_contactList = c.m_nodeB; + if (fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + bodyA.SetAwake(true); + bodyB.SetAwake(true) + }++this.m_contactCount + }, + FindNewContacts: function () { + this.m_broadPhase.UpdatePairs(this) + }, + Destroy: function (c) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (this.m_contactListener && c.IsTouching()) { + this.m_contactListener.EndContact(c) + } + if (c.m_prev) { + c.m_prev.m_next = c.m_next + } + if (c.m_next) { + c.m_next.m_prev = c.m_prev + } + if (c == this.m_contactList) { + this.m_contactList = c.m_next + } + if (c.m_nodeA.prev) { + c.m_nodeA.prev.next = c.m_nodeA.next + } + if (c.m_nodeA.next) { + c.m_nodeA.next.prev = c.m_nodeA.prev + } + if (c.m_nodeA == bodyA.m_contactList) { + bodyA.m_contactList = c.m_nodeA.next + } + if (c.m_nodeB.prev) { + c.m_nodeB.prev.next = c.m_nodeB.next + } + if (c.m_nodeB.next) { + c.m_nodeB.next.prev = c.m_nodeB.prev + } + if (c.m_nodeB == bodyB.m_contactList) { + bodyB.m_contactList = c.m_nodeB.next + } + b2Contact.Destroy(c); + --this.m_contactCount + }, + Collide: function () { + var c = this.m_contactList; + while (c) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (c.m_flags & b2Contact.e_filterFlag) { + if (bodyB.ShouldCollide(bodyA) == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.m_flags &= ~b2Contact.e_filterFlag + } + var activeA = bodyA.IsAwake() && bodyA.m_type != b2Body.b2_staticBody; + var activeB = bodyB.IsAwake() && bodyB.m_type != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + c = c.GetNext(); + continue + } + var proxyIdA = fixtureA.m_proxies[indexA].proxyId; + var proxyIdB = fixtureB.m_proxies[indexB].proxyId; + var overlap = this.m_broadPhase.TestOverlap(proxyIdA, proxyIdB); + if (overlap == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.Update(this.m_contactListener); + c = c.GetNext() + } + } +}; + +function b2VelocityConstraintPoint() { + this.rA = new b2Vec2(); + this.rB = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.normalMass = 0; + this.tangentMass = 0; + this.velocityBias = 0 +} + +function b2ContactPositionConstraint() { + this.localPoints = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.localCenterA = new b2Vec2(), this.localCenterB = new b2Vec2(); + this.invIA = 0, this.invIB = 0; + this.type = 0; + this.radiusA = 0, this.radiusB = 0; + this.pointCount = 0 +} + +function b2ContactVelocityConstraint() { + this.points = new Array(b2_maxManifoldPoints); + for (var i = 0; i < this.points.length; ++i) { + this.points[i] = new b2VelocityConstraintPoint() + } + this.normal = new b2Vec2(); + this.normalMass = new b2Mat22(); + this.K = new b2Mat22(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.invIA = 0, this.invIB = 0; + this.friction = 0; + this.restitution = 0; + this.tangentSpeed = 0; + this.pointCount = 0; + this.contactIndex = 0 +} + +function b2PositionSolverManifold() { + this.normal = new b2Vec2(); + this.point = new b2Vec2(); + this.separation = 0 +} +b2PositionSolverManifold.prototype = { + Initialize: function (pc, xfA, xfB, index) { + switch (pc.type) { + case b2Manifold.e_circles: + var pointAx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * pc.localPoints[0].x - xfB.q.s * pc.localPoints[0].y) + xfB.p.x; + var pointBy = (xfB.q.s * pc.localPoints[0].x + xfB.q.c * pc.localPoints[0].y) + xfB.p.y; + this.point.x = 0.5 * (pointAx + pointBx); + this.point.y = 0.5 * (pointAy + pointBy); + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + var tempnx = this.normal.x; + var tempny = this.normal.y; + this.normal.Normalize(); + this.separation = (tempnx * this.normal.x + tempny * this.normal.y) - pc.radiusA - pc.radiusB; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * pc.localNormal.x - xfA.q.s * pc.localNormal.y; + this.normal.y = xfA.q.s * pc.localNormal.x + xfA.q.c * pc.localNormal.y; + var planePointx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var clipPointx = (xfB.q.c * pc.localPoints[index].x - xfB.q.s * pc.localPoints[index].y) + xfB.p.x; + var clipPointy = (xfB.q.s * pc.localPoints[index].x + xfB.q.c * pc.localPoints[index].y) + xfB.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * pc.localNormal.x - xfB.q.s * pc.localNormal.y; + this.normal.y = xfB.q.s * pc.localNormal.x + xfB.q.c * pc.localNormal.y; + var planePointx = (xfB.q.c * pc.localPoint.x - xfB.q.s * pc.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * pc.localPoint.x + xfB.q.c * pc.localPoint.y) + xfB.p.y; + var clipPointx = (xfA.q.c * pc.localPoints[index].x - xfA.q.s * pc.localPoints[index].y) + xfA.p.x; + var clipPointy = (xfA.q.s * pc.localPoints[index].x + xfA.q.c * pc.localPoints[index].y) + xfA.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } +}; + +function b2ContactSolverDef() { + this.step = new b2TimeStep(); + this.contacts = null; + this.count = 0; + this.positions = null; + this.velocities = null +} + +function b2ContactSolver() { + this.m_positionConstraints = []; + this.m_velocityConstraints = [] +} +b2ContactSolver.cs_xfA = new b2Transform(); +b2ContactSolver.cs_xfB = new b2Transform(); +b2ContactSolver.temp_solver_manifold = new b2PositionSolverManifold(); +b2ContactSolver.prototype = { + Init: function (def) { + this.m_step = def.step; + this.m_count = def.count; + this.m_positionConstraints.length = this.m_count; + this.m_velocityConstraints.length = this.m_count; + this.m_positions = def.positions; + this.m_velocities = def.velocities; + this.m_contacts = def.contacts; + for (var i = 0; i < this.m_count; ++i) { + var contact = this.m_contacts[i]; + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + var shapeA = fixtureA.GetShape(); + var shapeB = fixtureB.GetShape(); + var radiusA = shapeA.m_radius; + var radiusB = shapeB.m_radius; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + var manifold = contact.GetManifold(); + var pointCount = manifold.pointCount; + var vc = this.m_velocityConstraints[i] || new b2ContactVelocityConstraint(); + vc.friction = contact.m_friction; + vc.restitution = contact.m_restitution; + vc.tangentSpeed = contact.m_tangentSpeed; + vc.indexA = bodyA.m_islandIndex; + vc.indexB = bodyB.m_islandIndex; + vc.invMassA = bodyA.m_invMass; + vc.invMassB = bodyB.m_invMass; + vc.invIA = bodyA.m_invI; + vc.invIB = bodyB.m_invI; + vc.contactIndex = i; + vc.pointCount = pointCount; + vc.K.SetZero(); + vc.normalMass.SetZero(); + this.m_velocityConstraints[i] = vc; + var pc = this.m_positionConstraints[i] || new b2ContactPositionConstraint(); + pc.indexA = bodyA.m_islandIndex; + pc.indexB = bodyB.m_islandIndex; + pc.invMassA = bodyA.m_invMass; + pc.invMassB = bodyB.m_invMass; + pc.localCenterA.x = bodyA.m_sweep.localCenter.x; + pc.localCenterA.y = bodyA.m_sweep.localCenter.y; + pc.localCenterB.x = bodyB.m_sweep.localCenter.x; + pc.localCenterB.y = bodyB.m_sweep.localCenter.y; + pc.invIA = bodyA.m_invI; + pc.invIB = bodyB.m_invI; + pc.localNormal.x = manifold.localNormal.x; + pc.localNormal.y = manifold.localNormal.y; + pc.localPoint.x = manifold.localPoint.x; + pc.localPoint.y = manifold.localPoint.y; + pc.pointCount = pointCount; + pc.radiusA = radiusA; + pc.radiusB = radiusB; + pc.type = manifold.type; + this.m_positionConstraints[i] = pc; + for (var j = 0; j < pointCount; ++j) { + var cp = manifold.points[j]; + var vcp = vc.points[j]; + if (this.m_step.warmStarting) { + vcp.normalImpulse = this.m_step.dtRatio * cp.normalImpulse; + vcp.tangentImpulse = this.m_step.dtRatio * cp.tangentImpulse + } else { + vcp.normalImpulse = 0; + vcp.tangentImpulse = 0 + } + vcp.rA.SetZero(); + vcp.rB.SetZero(); + vcp.normalMass = 0; + vcp.tangentMass = 0; + vcp.velocityBias = 0; + pc.localPoints[j] = cp.localPoint + } + } + }, + InitializeVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var pc = this.m_positionConstraints[i]; + var radiusA = pc.radiusA; + var radiusB = pc.radiusB; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var mB = vc.invMassB; + var iA = vc.invIA; + var iB = vc.invIB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); + b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); + b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); + b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); + var worldManifold = new b2WorldManifold(); + worldManifold.Initialize(manifold, b2ContactSolver.cs_xfA, radiusA, b2ContactSolver.cs_xfB, radiusB); + vc.normal.x = worldManifold.normal.x; + vc.normal.y = worldManifold.normal.y; + var pointCount = vc.pointCount; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + vcp.rA.x = worldManifold.points[j].x - cA.x; + vcp.rA.y = worldManifold.points[j].y - cA.y; + vcp.rB.x = worldManifold.points[j].x - cB.x; + vcp.rB.y = worldManifold.points[j].y - cB.y; + var rnA = vcp.rA.x * vc.normal.y - vcp.rA.y * vc.normal.x; + var rnB = vcp.rB.x * vc.normal.y - vcp.rB.y * vc.normal.x; + var kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + vcp.normalMass = kNormal > 0 ? 1 / kNormal : 0; + var tangentx = 1 * vc.normal.y; + var tangenty = -1 * vc.normal.x; + var rtA = vcp.rA.x * tangenty - vcp.rA.y * tangentx; + var rtB = vcp.rB.x * tangenty - vcp.rB.y * tangentx; + var kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + vcp.tangentMass = kTangent > 0 ? 1 / kTangent : 0; + vcp.velocityBias = 0; + var vRel = vc.normal.x * (((vB.x + (-wB * vcp.rB.y)) - vA.x) - (-wA * vcp.rA.y)) + vc.normal.y * (((vB.y + (wB * vcp.rB.x)) - vA.y) - (wA * vcp.rA.x)); + if (vRel < -b2_velocityThreshold) { + vcp.velocityBias = -vc.restitution * vRel + } + } + if (vc.pointCount == 2) { + var vcp1 = vc.points[0]; + var vcp2 = vc.points[1]; + var rn1A = vcp1.rA.x * vc.normal.y - vcp1.rA.y * vc.normal.x; + var rn1B = vcp1.rB.x * vc.normal.y - vcp1.rB.y * vc.normal.x; + var rn2A = vcp2.rA.x * vc.normal.y - vcp2.rA.y * vc.normal.x; + var rn2B = vcp2.rB.x * vc.normal.y - vcp2.rB.y * vc.normal.x; + var k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B; + var k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B; + var k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B; + var k_maxConditionNumber = 1000; + if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { + vc.K.ex.x = k11; + vc.K.ex.y = k12; + vc.K.ey.x = k12; + vc.K.ey.y = k22; + vc.normalMass.Assign(vc.K.GetInverse()) + } else { + vc.pointCount = 1 + } + } + } + }, + WarmStart: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var Px = (vcp.normalImpulse * normal.x) + (vcp.tangentImpulse * tangentx); + var Py = (vcp.normalImpulse * normal.y) + (vcp.tangentImpulse * tangenty); + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vA.x -= mA * Px; + vA.y -= mA * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px); + vB.x += mB * Px; + vB.y += mB * Py + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + SolveVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + var friction = vc.friction; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + var dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vt = (dvx * tangentx + dvy * tangenty) - vc.tangentSpeed; + var lambda = vcp.tangentMass * (-vt); + var maxFriction = friction * vcp.normalImpulse; + var newImpulse = b2Clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction); + lambda = newImpulse - vcp.tangentImpulse; + vcp.tangentImpulse = newImpulse; + var Px = lambda * tangentx; + var Py = lambda * tangenty; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } + if (vc.pointCount == 1) { + vcp = vc.points[0]; + dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vn = dvx * normal.x + dvy * normal.y; + var lambda = -vcp.normalMass * (vn - vcp.velocityBias); + var newImpulse = b2Max(vcp.normalImpulse + lambda, 0); + lambda = newImpulse - vcp.normalImpulse; + vcp.normalImpulse = newImpulse; + Px = lambda * normal.x; + Py = lambda * normal.y; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } else { + var cp1 = vc.points[0]; + var cp2 = vc.points[1]; + var ax = cp1.normalImpulse; + var ay = cp2.normalImpulse; + var dv1x = vB.x + (-wB * cp1.rB.y) - vA.x - (-wA * cp1.rA.y); + var dv1y = vB.y + (wB * cp1.rB.x) - vA.y - (wA * cp1.rA.x); + var dv2x = vB.x + (-wB * cp2.rB.y) - vA.x - (-wA * cp2.rA.y); + var dv2y = vB.y + (wB * cp2.rB.x) - vA.y - (wA * cp2.rA.x); + var vn1 = dv1x * normal.x + dv1y * normal.y; + var vn2 = dv2x * normal.x + dv2y * normal.y; + var bx = vn1 - cp1.velocityBias; + var by = vn2 - cp2.velocityBias; + bx -= vc.K.ex.x * ax + vc.K.ey.x * ay; + by -= vc.K.ex.y * ax + vc.K.ey.y * ay; + for (;;) { + var xx = -(vc.normalMass.ex.x * bx + vc.normalMass.ey.x * by); + var xy = -(vc.normalMass.ex.y * bx + vc.normalMass.ey.y * by); + if (xx >= 0 && xy >= 0) { + var dx = xx - ax; + var dy = xy - ay; + var P1x = dx * normal.x; + var P1y = dx * normal.y; + var P2x = dy * normal.x; + var P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = -cp1.normalMass * bx; + xy = 0; + vn1 = 0; + vn2 = vc.K.ex.y * xx + by; + if (xx >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = -cp2.normalMass * by; + vn1 = vc.K.ey.x * xy + bx; + vn2 = 0; + if (xy >= 0 && vn1 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = 0; + vn1 = bx; + vn2 = by; + if (vn1 >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + break + } + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + StoreImpulses: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + for (var j = 0; j < vc.pointCount; ++j) { + manifold.points[j].normalImpulse = vc.points[j].normalImpulse; + manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse + } + } + }, + SolvePositionConstraints: function () { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var mA = pc.invMassA; + var iA = pc.invIA; + var localCenterB = pc.localCenterB; + var mB = pc.invMassB; + var iB = pc.invIB; + var pointCount = pc.pointCount; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); + b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); + b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); + b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rAx = point.x - cA.x; + var rAy = point.y - cA.y; + var rBx = point.x - cB.x; + var rBy = point.y - cB.y; + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = rAx * normal.y - rAy * normal.x; + var rnB = rBx * normal.y - rBy * normal.x; + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var Px = impulse * normal.x; + var Py = impulse * normal.y; + cA.x -= mA * Px; + cA.y -= mA * Py; + aA -= iA * (rAx * Py - rAy * Px); + cB.x += mB * Px; + cB.y += mB * Py; + aB += iB * (rBx * Py - rBy * Px) + } + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB + } + return minSeparation >= -3 * b2_linearSlop + }, + SolveTOIPositionConstraints: function (toiIndexA, toiIndexB) { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var pointCount = pc.pointCount; + var mA = 0; + var iA = 0; + if (indexA == toiIndexA || indexA == toiIndexB) { + mA = pc.invMassA; + iA = pc.invIA + } + var mB = 0; + var iB = 0; + if (indexB == toiIndexA || indexB == toiIndexB) { + mB = pc.invMassB; + iB = pc.invIB + } + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.Assign(b2Vec2.Subtract(cA, b2Mul_r_v2(b2ContactSolver.cs_xfA.q, localCenterA))); + b2ContactSolver.cs_xfB.p.Assign(b2Vec2.Subtract(cB, b2Mul_r_v2(b2ContactSolver.cs_xfB.q, localCenterB))); + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rA = b2Vec2.Subtract(point, cA); + var rB = b2Vec2.Subtract(point, cB); + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_toiBaugarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = b2Cross_v2_v2(rA, normal); + var rnB = b2Cross_v2_v2(rB, normal); + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var P = b2Vec2.Multiply(impulse, normal); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB + } + return minSeparation >= -1.5 * b2_linearSlop + } +}; +"use strict"; + +function b2Island() { + this.m_bodies = []; + this.m_contacts = []; + this.m_joints = []; + this.m_velocities = []; + this.m_positions = [] +} +var profile_solve_init = b2Profiler.create("solve initialization", "solve"); +var profile_solve_init_warmStarting = b2Profiler.create("warm starting", "solve initialization"); +var profile_solve_velocity = b2Profiler.create("solve velocities", "solve"); +var profile_solve_position = b2Profiler.create("solve positions", "solve"); +b2Island._solverData = new b2SolverData(); +b2Island._solverDef = new b2ContactSolverDef(); +b2Island._solver = new b2ContactSolver(); +b2Island.prototype = { + Clear: function () { + this.m_bodyCount = 0; + this.m_contactCount = 0; + this.m_jointCount = 0 + }, + Initialize: function (bodyCapacity, contactCapacity, jointCapacity, listener) { + this.m_listener = listener; + this.m_bodyCapacity = bodyCapacity; + this.m_contactCapacity = contactCapacity; + this.m_jointCapacity = jointCapacity; + this.m_bodyCount = 0; + this.m_contactCount = 0; + this.m_jointCount = 0; + this.m_bodies.length = bodyCapacity; + this.m_contacts.length = contactCapacity; + this.m_joints.length = jointCapacity; + this.m_velocities.length = bodyCapacity; + this.m_positions.length = bodyCapacity + }, + Solve: function (step, gravity, allowSleep) { + profile_solve_init.start(); + var h = step.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + var a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + var w = b.m_angularVelocity; + b.m_sweep.c0.Assign(b.m_sweep.c); + b.m_sweep.a0 = b.m_sweep.a; + if (b.m_type == b2Body.b2_dynamicBody) { + this.m_velocities[i].v.x += h * ((b.m_gravityScale * gravity.x) + (b.m_invMass * b.m_force.x)); + this.m_velocities[i].v.y += h * ((b.m_gravityScale * gravity.y) + (b.m_invMass * b.m_force.y)); + w += h * b.m_invI * b.m_torque; + this.m_velocities[i].v.x *= 1 / (1 + h * b.m_linearDamping); + this.m_velocities[i].v.y *= 1 / (1 + h * b.m_linearDamping); + w *= 1 / (1 + h * b.m_angularDamping) + } + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + b2Island._solverData.step = step; + b2Island._solverData.positions = this.m_positions; + b2Island._solverData.velocities = this.m_velocities; + b2Island._solverDef.step = step; + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solverDef.allocator = this.m_allocator; + b2Island._solver.Init(b2Island._solverDef); + b2Island._solver.InitializeVelocityConstraints(); + if (step.warmStarting) { + profile_solve_init_warmStarting.start(); + b2Island._solver.WarmStart(); + profile_solve_init_warmStarting.stop() + } + for (var i = 0; i < this.m_jointCount; ++i) { + this.m_joints[i].InitVelocityConstraints(b2Island._solverData) + } + profile_solve_init.stop(); + profile_solve_velocity.start(); + for (var i = 0; i < step.velocityIterations; ++i) { + for (var j = 0; j < this.m_jointCount; ++j) { + this.m_joints[j].SolveVelocityConstraints(b2Island._solverData) + } + b2Island._solver.SolveVelocityConstraints() + } + b2Island._solver.StoreImpulses(); + profile_solve_velocity.stop(); + profile_solve_position.start(); + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translationx = h * v.x; + var translationy = h * v.y; + var translationl = translationx * translationx + translationy * translationy; + if (translationl > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / b2Sqrt(translationl); + v.x *= ratio; + v.y *= ratio + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.x += h * v.x; + c.y += h * v.y; + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + var positionSolved = false; + for (var i = 0; i < step.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolvePositionConstraints(); + var jointsOkay = true; + for (var j = 0; j < this.m_jointCount; ++j) { + var jointOkay = this.m_joints[j].SolvePositionConstraints(b2Island._solverData); + jointsOkay = jointsOkay && jointOkay + } + if (contactsOkay && jointsOkay) { + positionSolved = true; + break + } + } + for (var i = 0; i < this.m_bodyCount; ++i) { + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(this.m_positions[i].c); + body.m_sweep.a = this.m_positions[i].a; + body.m_linearVelocity.Assign(this.m_velocities[i].v); + body.m_angularVelocity = this.m_velocities[i].w; + body.SynchronizeTransform() + } + profile_solve_position.stop(); + this.Report(b2Island._solver.m_velocityConstraints); + if (allowSleep) { + var minSleepTime = b2_maxFloat; + var linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; + var angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + if ((b.m_flags & b2Body.e_autoSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || b2Dot_v2_v2(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) { + b.m_sleepTime = 0; + minSleepTime = 0 + } else { + b.m_sleepTime += h; + minSleepTime = b2Min(minSleepTime, b.m_sleepTime) + } + } + if (minSleepTime >= b2_timeToSleep && positionSolved) { + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + b.SetAwake(false) + } + } + } + }, + SolveTOI: function (subStep, toiIndexA, toiIndexB) { + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + this.m_positions[i].a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + this.m_velocities[i].w = b.m_angularVelocity + } + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.step = subStep; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solver.Init(b2Island._solverDef); + for (var i = 0; i < subStep.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); + if (contactsOkay) { + break + } + } + this.m_bodies[toiIndexA].m_sweep.c0.Assign(this.m_positions[toiIndexA].c); + this.m_bodies[toiIndexA].m_sweep.a0 = this.m_positions[toiIndexA].a; + this.m_bodies[toiIndexB].m_sweep.c0.Assign(this.m_positions[toiIndexB].c); + this.m_bodies[toiIndexB].m_sweep.a0 = this.m_positions[toiIndexB].a; + b2Island._solver.InitializeVelocityConstraints(); + for (var i = 0; i < subStep.velocityIterations; ++i) { + b2Island._solver.SolveVelocityConstraints() + } + var h = subStep.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translation = b2Vec2.Multiply(h, v); + if (b2Dot_v2_v2(translation, translation) > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / translation.Length(); + v.Multiply(ratio) + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.Add(b2Vec2.Multiply(h, v)); + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w; + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(c); + body.m_sweep.a = a; + body.m_linearVelocity.Assign(v); + body.m_angularVelocity = w; + body.SynchronizeTransform() + } + this.Report(b2Island._solver.m_velocityConstraints) + }, + AddBody: function (body) { + body.m_islandIndex = this.m_bodyCount; + this.m_bodies[this.m_bodyCount] = body; + if (!this.m_positions[this.m_bodyCount]) { + this.m_positions[this.m_bodyCount] = new b2Position(); + this.m_velocities[this.m_bodyCount] = new b2Velocity() + }++this.m_bodyCount + }, + AddContact: function (contact) { + this.m_contacts[this.m_contactCount++] = contact + }, + AddJoint: function (joint) { + this.m_joints[this.m_jointCount++] = joint + }, + Report: function (constraints) { + if (this.m_listener == null) { + return + } + for (var i = 0; i < this.m_contactCount; ++i) { + var c = this.m_contacts[i]; + var vc = constraints[i]; + var impulse = new b2ContactImpulse(); + impulse.count = vc.pointCount; + for (var j = 0; j < vc.pointCount; ++j) { + impulse.normalImpulses[j] = vc.points[j].normalImpulse; + impulse.tangentImpulses[j] = vc.points[j].tangentImpulse + } + this.m_listener.PostSolve(c, impulse) + } + } +}; + +function b2Jacobian() { + this.linear = new b2Vec2(); + this.angularA = 0; + this.angularB = 0 +} + +function b2JointEdge() { + this.other = null; + this.joint = null; + this.prev = null; + this.next = null +} + +function b2JointDef() { + this.type = b2Joint.e_unknownJoint; + this.userData = null; + this.bodyA = null; + this.bodyB = null; + this.collideConnected = false +} +b2JointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.bodyA = bodies[data.bodyA]; + this.bodyB = bodies[data.bodyB]; + this.collideConnected = data.collideConnected + } +}; + +function b2Joint(def) { + this.m_type = def.type; + this.m_prev = null; + this.m_next = null; + this.m_bodyA = def.bodyA; + this.m_bodyB = def.bodyB; + this.m_index = 0; + this.m_collideConnected = def.collideConnected; + this.m_islandFlag = false; + this.m_userData = def.userData; + this.m_edgeA = new b2JointEdge(); + this.m_edgeA.joint = null; + this.m_edgeA.other = null; + this.m_edgeA.prev = null; + this.m_edgeA.next = null; + this.m_edgeB = new b2JointEdge(); + this.m_edgeB.joint = null; + this.m_edgeB.other = null; + this.m_edgeB.prev = null; + this.m_edgeB.next = null +} +b2Joint.prototype = { + GetType: function () { + return this.m_type + }, + GetBodyA: function () { + return this.m_bodyA + }, + GetBodyB: function () { + return this.m_bodyB + }, + GetAnchorA: function () {}, + GetAnchorB: function () {}, + GetReactionForce: function (inv_dt) {}, + GetReactionTorque: function (inv_dt) {}, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + IsActive: function () { + return this.m_bodyA.IsActive() && this.m_bodyB.IsActive() + }, + GetCollideConnected: function () { + return this.m_collideConnected + }, + ShiftOrigin: function (newOrigin) {}, + InitVelocityConstraints: function (data) {}, + SolveVelocityConstraints: function (data) {}, + SolvePositionConstraints: function (data) {}, + _serialize: function (out) { + var obj = out || {}; + obj.bodyA = null; + obj.bodyB = null; + obj.type = this.m_type; + obj.collideConnected = this.m_collideConnected; + return obj + } +}; +b2Joint.e_inactiveLimit = 0; +b2Joint.e_atLowerLimit = 1; +b2Joint.e_atUpperLimit = 2; +b2Joint.e_equalLimits = 3; +b2Joint.e_unknownJoint = 0; +b2Joint.e_revoluteJoint = 1; +b2Joint.e_prismaticJoint = 2; +b2Joint.e_distanceJoint = 3; +b2Joint.e_pulleyJoint = 4; +b2Joint.e_mouseJoint = 5; +b2Joint.e_gearJoint = 6; +b2Joint.e_wheelJoint = 7; +b2Joint.e_weldJoint = 8; +b2Joint.e_frictionJoint = 9; +b2Joint.e_ropeJoint = 10; +b2Joint.e_motorJoint = 11; +b2Joint.Create = function (def) { + var joint = null; + switch (def.type) { + case b2Joint.e_distanceJoint: + joint = new b2DistanceJoint(def); + break; + case b2Joint.e_mouseJoint: + joint = new b2MouseJoint(def); + break; + case b2Joint.e_prismaticJoint: + joint = new b2PrismaticJoint(def); + break; + case b2Joint.e_revoluteJoint: + joint = new b2RevoluteJoint(def); + break; + case b2Joint.e_pulleyJoint: + joint = new b2PulleyJoint(def); + break; + case b2Joint.e_gearJoint: + joint = new b2GearJoint(def); + break; + case b2Joint.e_wheelJoint: + joint = new b2WheelJoint(def); + break; + case b2Joint.e_weldJoint: + joint = new b2WeldJoint(def); + break; + case b2Joint.e_frictionJoint: + joint = new b2FrictionJoint(def); + break; + case b2Joint.e_ropeJoint: + joint = new b2RopeJoint(def); + break; + case b2Joint.e_motorJoint: + joint = new b2MotorJoint(def); + break + } + return joint +}; +b2Joint.Destroy = function (joint) {}; + +function b2RevoluteJointDef() { + this.parent.call(this); + this.type = b2Joint.e_revoluteJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.referenceAngle = 0; + this.lowerAngle = 0; + this.upperAngle = 0; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.enableLimit = false; + this.enableMotor = false; + Object.seal(this) +} +b2RevoluteJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.lowerAngle = data.lowerAngle; + this.upperAngle = data.upperAngle; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.enableLimit = data.enableLimit; + this.enableMotor = data.enableMotor + } +}; +b2RevoluteJointDef._extend(b2JointDef); + +function b2RevoluteJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorImpulse = 0; + this.m_lowerAngle = def.lowerAngle; + this.m_upperAngle = def.upperAngle; + this.m_maxMotorTorque = def.maxMotorTorque; + this.m_motorSpeed = def.motorSpeed; + this.m_enableLimit = def.enableLimit; + this.m_enableMotor = def.enableMotor; + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_motorMass = 0 +} +b2RevoluteJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointAngle: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_angularVelocity - bA.m_angularVelocity + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerAngle + }, + GetUpperLimit: function () { + return this.m_upperAngle + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerAngle || upper != this.m_upperAngle) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_impulse.z = 0; + this.m_lowerAngle = lower; + this.m_upperAngle = upper + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA = this.m_bodyA.m_sweep.localCenter; + this.m_localCenterB = this.m_bodyB.m_sweep.localCenter; + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + this.m_mass.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB; + this.m_mass.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB; + this.m_mass.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB; + this.m_mass.ex.y = this.m_mass.ey.x; + this.m_mass.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB; + this.m_mass.ez.y = this.m_rA.x * iA + this.m_rB.x * iB; + this.m_mass.ex.z = this.m_mass.ez.x; + this.m_mass.ey.z = this.m_mass.ez.y; + this.m_mass.ez.z = iA + iB; + this.m_motorMass = iA + iB; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + if (this.m_enableMotor == false || fixedRotation) { + this.m_motorImpulse = 0 + } + if (this.m_enableLimit && fixedRotation == false) { + var jointAngle = aB - aA - this.m_referenceAngle; + if (b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2 * b2_angularSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointAngle <= this.m_lowerAngle) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_impulse.z = 0 + } + this.m_limitState = b2Joint.e_atLowerLimit + } else { + if (jointAngle >= this.m_upperAngle) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { + this.m_impulse.z = 0 + } + this.m_limitState = b2Joint.e_atUpperLimit + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + } + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_motorImpulse + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_motorImpulse + this.m_impulse.z) + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits && fixedRotation == false) { + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse + } + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = this.m_mass.Solve33(Cdot).Negate(); + if (this.m_limitState == b2Joint.e_equalLimits) { + this.m_impulse.Add(impulse) + } else { + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var newImpulse = this.m_impulse.z + impulse.z; + if (newImpulse < 0) { + var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); + var reduced = this.m_mass.Solve22(rhs); + impulse.x = reduced.x; + impulse.y = reduced.y; + impulse.z = -this.m_impulse.z; + this.m_impulse.x += reduced.x; + this.m_impulse.y += reduced.y; + this.m_impulse.z = 0 + } else { + this.m_impulse.Add(impulse) + } + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + var newImpulse = this.m_impulse.z + impulse.z; + if (newImpulse > 0) { + var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); + var reduced = this.m_mass.Solve22(rhs); + impulse.x = reduced.x; + impulse.y = reduced.y; + impulse.z = -this.m_impulse.z; + this.m_impulse.x += reduced.x; + this.m_impulse.y += reduced.y; + this.m_impulse.z = 0 + } else { + this.m_impulse.Add(impulse) + } + } + } + } + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } else { + var Cdot = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse = this.m_mass.Solve22(Cdot.Negate()); + this.m_impulse.x += impulse.x; + this.m_impulse.y += impulse.y; + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse) + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var angularError = 0; + var positionError = 0; + var fixedRotation = (this.m_invIA + this.m_invIB == 0); + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var angle = aB - aA - this.m_referenceAngle; + var limitImpulse = 0; + if (this.m_limitState == b2Joint.e_equalLimits) { + var C = b2Clamp(angle - this.m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C; + angularError = b2Abs(C) + } else { + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var C = angle - this.m_lowerAngle; + angularError = -C; + C = b2Clamp(C + b2_angularSlop, -b2_maxAngularCorrection, 0); + limitImpulse = -this.m_motorMass * C + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + var C = angle - this.m_upperAngle; + angularError = C; + C = b2Clamp(C - b2_angularSlop, 0, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C + } + } + } + aA -= this.m_invIA * limitImpulse; + aB += this.m_invIB * limitImpulse + } + qA.Set(aA); + qB.Set(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var C = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C.Length(); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y; + K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x; + var impulse = K.Solve(C).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, impulse)); + aA -= iA * b2Cross_v2_v2(rA, impulse); + cB.Add(b2Vec2.Multiply(mB, impulse)); + aB += iB * b2Cross_v2_v2(rB, impulse); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.lowerAngle = this.m_lowerAngle; + obj.upperAngle = this.m_upperAngle; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.enableLimit = this.m_enableLimit; + obj.enableMotor = this.m_enableMotor; + return obj + } +}; +b2RevoluteJoint._extend(b2Joint); + +function b2MouseJointDef() { + this.parent.call(this); + this.type = b2Joint.e_mouseJoint; + this.target = new b2Vec2(0, 0); + this.maxForce = 0; + this.frequencyHz = 5; + this.dampingRatio = 0.7; + Object.seal(this) +} +b2MouseJointDef._extend(b2JointDef); + +function b2MouseJoint(def) { + this.parent.call(this, def); + this.m_targetA = def.target.Clone(); + this.m_localAnchorB = b2MulT_t_v2(this.m_bodyB.GetTransform(), this.m_targetA); + this.m_maxForce = def.maxForce; + this.m_impulse = new b2Vec2(); + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_beta = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rB = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassB = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat22(); + this.m_C = new b2Vec2() +} +b2MouseJoint.prototype = { + GetAnchorA: function () { + return this.m_targetA + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_impulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * 0 + }, + SetTarget: function (target) { + if (this.m_bodyB.IsAwake() == false) { + this.m_bodyB.SetAwake(true) + } + this.m_targetA.Assign(target) + }, + GetTarget: function () { + return this.m_targetA + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + ShiftOrigin: function (newOrigin) { + this.m_targetA.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIB = this.m_bodyB.m_invI; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qB = new b2Rot(aB); + var mass = this.m_bodyB.GetMass(); + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * mass * this.m_dampingRatio * omega; + var k = mass * (omega * omega); + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + if (this.m_gamma != 0) { + this.m_gamma = 1 / this.m_gamma + } + this.m_beta = h * k * this.m_gamma; + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var K = new b2Mat22(); + K.ex.x = this.m_invMassB + this.m_invIB * this.m_rB.y * this.m_rB.y + this.m_gamma; + K.ex.y = -this.m_invIB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = this.m_invMassB + this.m_invIB * this.m_rB.x * this.m_rB.x + this.m_gamma; + this.m_mass.Assign(K.GetInverse()); + this.m_C.Assign(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), this.m_targetA)); + this.m_C.Multiply(this.m_beta); + wB *= 0.98; + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + vB.Add(b2Vec2.Multiply(this.m_invMassB, this.m_impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, this.m_impulse) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var impulse = b2Mul_m22_v2(this.m_mass, (b2Vec2.Add(b2Vec2.Add(Cdot, this.m_C), b2Vec2.Multiply(this.m_gamma, this.m_impulse))).Negate()); + var oldImpulse = this.m_impulse.Clone(); + this.m_impulse.Add(impulse); + var maxImpulse = data.step.dt * this.m_maxForce; + if (this.m_impulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_impulse.Multiply(maxImpulse / this.m_impulse.Length()) + } + impulse.Assign(b2Vec2.Subtract(this.m_impulse, oldImpulse)); + vB.Add(b2Vec2.Multiply(this.m_invMassB, impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + } +}; +b2MouseJoint._extend(b2Joint); + +function b2DistanceJointDef() { + this.parent.call(this); + this.type = b2Joint.e_distanceJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.length = 1; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) +} +b2DistanceJointDef.prototype = { + Initialize: function (b1, b2, anchor1, anchor2) { + this.bodyA = b1; + this.bodyB = b2; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor1); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor2); + var d = b2Vec2.Subtract(anchor2, anchor1); + this.length = d.Length() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.length = data.length; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2DistanceJointDef._extend(b2JointDef); + +function b2DistanceJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_length = def.length; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = 0; + this.m_gamma = 0; + this.m_bias = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0 +} +b2DistanceJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetLength: function (length) { + this.m_length = length + }, + GetLength: function () { + return this.m_length + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + this.m_u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA); + var length = this.m_u.Length(); + if (length > b2_linearSlop) { + this.m_u.Multiply(1 / length) + } else { + this.m_u.Set(0, 0) + } + var crAu = b2Cross_v2_v2(this.m_rA, this.m_u); + var crBu = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crAu * crAu + this.m_invMassB + this.m_invIB * crBu * crBu; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (this.m_frequencyHz > 0) { + var C = length - this.m_length; + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * this.m_mass * this.m_dampingRatio * omega; + var k = this.m_mass * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invMass += this.m_gamma; + this.m_mass = invMass != 0 ? 1 / invMass : 0 + } else { + this.m_gamma = 0; + this.m_bias = 0 + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse); + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + if (this.m_frequencyHz > 0) { + return true + } + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_length; + C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.length = this.m_length; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } +}; +b2DistanceJoint._extend(b2Joint); + +function b2PrismaticJointDef() { + this.parent.call(this); + this.type = b2Joint.e_prismaticJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.referenceAngle = 0; + this.enableLimit = false; + this.lowerTranslation = 0; + this.upperTranslation = 0; + this.enableMotor = false; + this.maxMotorForce = 0; + this.motorSpeed = 0; + Object.seal(this) +} +b2PrismaticJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.localAxisA = this.bodyA.GetLocalVector(axis); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.referenceAngle = data.referenceAngle; + this.enableLimit = data.enableLimit; + this.lowerTranslation = data.lowerTranslation; + this.upperTranslation = data.upperTranslation; + this.enableMotor = data.enableMotor; + this.maxMotorForce = data.maxMotorForce; + this.motorSpeed = data.motorSpeed + } +}; +b2PrismaticJointDef._extend(b2JointDef); + +function b2PrismaticJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localXAxisA.Normalize(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorMass = 0; + this.m_motorImpulse = 0; + this.m_lowerTranslation = def.lowerTranslation; + this.m_upperTranslation = def.upperTranslation; + this.m_maxMotorForce = def.maxMotorForce; + this.m_motorSpeed = def.motorSpeed; + this.m_enableLimit = def.enableLimit; + this.m_enableMotor = def.enableMotor; + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_axis = new b2Vec2(); + this.m_perp = new b2Vec2(); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_s1 = 0, this.m_s2 = 0; + this.m_a1 = 0, this.m_a2 = 0; + this.m_K = new b2Mat33(); + this.m_motorMass = 0 +} +b2PrismaticJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.y + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointTranslation: function () { + var pA = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var pB = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = this.m_bodyA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var rA = b2Mul_r_v2(bA.m_xf.q, b2Vec2.Subtract(this.m_localAnchorA, bA.m_sweep.localCenter)); + var rB = b2Mul_r_v2(bB.m_xf.q, b2Vec2.Subtract(this.m_localAnchorB, bB.m_sweep.localCenter)); + var p1 = b2Vec2.Add(bA.m_sweep.c, rA); + var p2 = b2Vec2.Add(bB.m_sweep.c, rB); + var d = b2Vec2.Subtract(p2, p1); + var axis = b2Mul_r_v2(bA.m_xf.q, this.m_localXAxisA); + var vA = bA.m_linearVelocity; + var vB = bB.m_linearVelocity; + var wA = bA.m_angularVelocity; + var wB = bB.m_angularVelocity; + var speed = b2Dot_v2_v2(d, b2Cross_f_v2(wA, axis)) + b2Dot_v2_v2(axis, b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, rB)), vA), b2Cross_f_v2(wA, rA))); + return speed + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerTranslation + }, + GetUpperLimit: function () { + return this.m_upperTranslation + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerTranslation || upper != this.m_upperTranslation) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_lowerTranslation = lower; + this.m_upperTranslation = upper; + this.m_impulse.z = 0 + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorForce: function (force) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorForce = force + }, + GetMaxMotorForce: function () { + return this.m_maxMotorForce + }, + GetMotorForce: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA = this.m_bodyA.m_sweep.localCenter; + this.m_localCenterB = this.m_bodyB.m_sweep.localCenter; + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + this.m_axis = b2Mul_r_v2(qA, this.m_localXAxisA); + this.m_a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_axis); + this.m_a2 = b2Cross_v2_v2(rB, this.m_axis); + this.m_motorMass = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + this.m_perp = b2Mul_r_v2(qA, this.m_localYAxisA); + this.m_s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_perp); + this.m_s2 = b2Cross_v2_v2(rB, this.m_perp); + var k11 = mA + mB + iA * this.m_s1 * this.m_s1 + iB * this.m_s2 * this.m_s2; + var k12 = iA * this.m_s1 + iB * this.m_s2; + var k13 = iA * this.m_s1 * this.m_a1 + iB * this.m_s2 * this.m_a2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var k23 = iA * this.m_a1 + iB * this.m_a2; + var k33 = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2; + this.m_K.ex.Set(k11, k12, k13); + this.m_K.ey.Set(k12, k22, k23); + this.m_K.ez.Set(k13, k23, k33); + if (this.m_enableLimit) { + var jointTranslation = b2Dot_v2_v2(this.m_axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointTranslation <= this.m_lowerTranslation) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_limitState = b2Joint.e_atLowerLimit; + this.m_impulse.z = 0 + } + } else { + if (jointTranslation >= this.m_upperTranslation) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { + this.m_limitState = b2Joint.e_atUpperLimit; + this.m_impulse.z = 0 + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + } + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + if (this.m_enableMotor == false) { + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis)); + var LA = this.m_impulse.x * this.m_s1 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a1; + var LB = this.m_impulse.x * this.m_s2 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) { + var Cdot = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; + var impulse = this.m_motorMass * (this.m_motorSpeed - Cdot); + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorForce; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_axis); + var LA = impulse * this.m_a1; + var LB = impulse * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + var Cdot1 = new b2Vec2(); + Cdot1.x = b2Dot_v2_v2(this.m_perp, b2Vec2.Subtract(vB, vA)) + this.m_s2 * wB - this.m_s1 * wA; + Cdot1.y = wB - wA; + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) { + var Cdot2; + Cdot2 = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var f1 = this.m_impulse.Clone(); + var df = this.m_K.Solve33(Cdot.Negate()); + this.m_impulse.Add(df); + if (this.m_limitState == b2Joint.e_atLowerLimit) { + this.m_impulse.z = b2Max(this.m_impulse.z, 0) + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + this.m_impulse.z = b2Min(this.m_impulse.z, 0) + } + } + var b = b2Vec2.Subtract(Cdot1.Negate(), b2Vec2.Multiply((this.m_impulse.z - f1.z), new b2Vec2(this.m_K.ez.x, this.m_K.ez.y))); + var f2r = b2Vec2.Add(this.m_K.Solve22(b), new b2Vec2(f1.x, f1.y)); + this.m_impulse.x = f2r.x; + this.m_impulse.y = f2r.y; + df = b2Vec3.Subtract(this.m_impulse, f1); + var P = b2Vec2.Add(b2Vec2.Multiply(df.x, this.m_perp), b2Vec2.Multiply(df.z, this.m_axis)); + var LA = df.x * this.m_s1 + df.y + df.z * this.m_a1; + var LB = df.x * this.m_s2 + df.y + df.z * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + var df = this.m_K.Solve22(Cdot1.Negate()); + this.m_impulse.x += df.x; + this.m_impulse.y += df.y; + var P = b2Vec2.Multiply(df.x, this.m_perp); + var LA = df.x * this.m_s1 + df.y; + var LB = df.x * this.m_s2 + df.y; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var axis = b2Mul_r_v2(qA, this.m_localXAxisA); + var a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), axis); + var a2 = b2Cross_v2_v2(rB, axis); + var perp = b2Mul_r_v2(qA, this.m_localYAxisA); + var s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), perp); + var s2 = b2Cross_v2_v2(rB, perp); + var impulse = new b2Vec3(); + var C1 = new b2Vec2(); + C1.x = b2Dot_v2_v2(perp, d); + C1.y = aB - aA - this.m_referenceAngle; + var linearError = b2Abs(C1.x); + var angularError = b2Abs(C1.y); + var active = false; + var C2 = 0; + if (this.m_enableLimit) { + var translation = b2Dot_v2_v2(axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); + linearError = b2Max(linearError, b2Abs(translation)); + active = true + } else { + if (translation <= this.m_lowerTranslation) { + C2 = b2Clamp(translation - this.m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0); + linearError = b2Max(linearError, this.m_lowerTranslation - translation); + active = true + } else { + if (translation >= this.m_upperTranslation) { + C2 = b2Clamp(translation - this.m_upperTranslation - b2_linearSlop, 0, b2_maxLinearCorrection); + linearError = b2Max(linearError, translation - this.m_upperTranslation); + active = true + } + } + } + } + if (active) { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k13 = iA * s1 * a1 + iB * s2 * a2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var k23 = iA * a1 + iB * a2; + var k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; + var K = new b2Mat33(); + K.ex.Set(k11, k12, k13); + K.ey.Set(k12, k22, k23); + K.ez.Set(k13, k23, k33); + var C = new b2Vec3(); + C.x = C1.x; + C.y = C1.y; + C.z = C2; + impulse = K.Solve33(C.Negate()) + } else { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var K = new b2Mat22(); + K.ex.Set(k11, k12); + K.ey.Set(k12, k22); + var impulse1 = K.Solve(C1.Negate()); + impulse.x = impulse1.x; + impulse.y = impulse1.y; + impulse.z = 0 + } + var P = b2Vec2.Add(b2Vec2.Multiply(impulse.x, perp), b2Vec2.Multiply(impulse.z, axis)); + var LA = impulse.x * s1 + impulse.y + impulse.z * a1; + var LB = impulse.x * s2 + impulse.y + impulse.z * a2; + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * LA; + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localXAxisA._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.enableLimit = this.m_enableLimit; + obj.lowerTranslation = this.m_lowerTranslation; + obj.upperTranslation = this.m_upperTranslation; + obj.enableMotor = this.m_enableMotor; + obj.maxMotorForce = this.m_maxMotorForce; + obj.motorSpeed = this.m_motorSpeed; + return obj + } +}; +b2PrismaticJoint._extend(b2Joint); + +function b2FrictionJointDef() { + this.parent.call(this); + this.type = b2Joint.e_frictionJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.maxForce = 0; + this.maxTorque = 0; + Object.seal(this) +} +b2FrictionJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque + } +}; +b2FrictionJointDef._extend(b2JointDef); + +function b2FrictionJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 +} +b2FrictionJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y; + K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x; + this.m_linearMass = K.GetInverse(); + this.m_angularMass = iA + iB; + if (this.m_angularMass > 0) { + this.m_angularMass = 1 / this.m_angularMass + } + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var Cdot = wB - wA; + var impulse = -this.m_angularMass * Cdot; + var oldImpulse = this.m_angularImpulse; + var maxImpulse = h * this.m_maxTorque; + this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(vB, b2Vec2.Subtract(b2Cross_f_v2(wB, this.m_rB), b2Vec2.Subtract(vA, b2Cross_f_v2(wA, this.m_rA)))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse.Clone(); + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse = b2Vec2.Subtract(this.m_linearImpulse, oldImpulse); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + return obj + } +}; +b2FrictionJoint._extend(b2Joint); + +function b2WeldJointDef() { + this.parent.call(this); + this.type = b2Joint.e_weldJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.referenceAngle = 0; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) +} +b2WeldJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2WeldJointDef._extend(b2JointDef); + +function b2WeldJoint(def) { + this.parent.call(this, def); + this.m_bias = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = new b2Vec3() +} +b2WeldJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat33(); + K.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB; + K.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB; + K.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB; + K.ex.y = K.ey.x; + K.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB; + K.ez.y = this.m_rA.x * iA + this.m_rB.x * iB; + K.ex.z = K.ez.x; + K.ey.z = K.ez.y; + K.ez.z = iA + iB; + if (this.m_frequencyHz > 0) { + K.GetInverse22(this.m_mass); + var invM = iA + iB; + var m = invM > 0 ? 1 / invM : 0; + var C = aB - aA - this.m_referenceAngle; + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * m * this.m_dampingRatio * omega; + var k = m * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invM += this.m_gamma; + this.m_mass.ez.z = invM != 0 ? 1 / invM : 0 + } else { + K.GetSymInverse33(this.m_mass); + this.m_gamma = 0; + this.m_bias = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_impulse.z) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_frequencyHz > 0) { + var Cdot2 = wB - wA; + var impulse2 = -this.m_mass.ez.z * (Cdot2 + this.m_bias + this.m_gamma * this.m_impulse.z); + this.m_impulse.z += impulse2; + wA -= iA * impulse2; + wB += iB * impulse2; + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse1 = b2Mul22_m33_v2(this.m_mass, Cdot1).Negate(); + this.m_impulse.x += impulse1.x; + this.m_impulse.y += impulse1.y; + var P = impulse1.Clone(); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * b2Cross_v2_v2(this.m_rB, P) + } else { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = b2Mul_m33_v3(this.m_mass, Cdot).Negate(); + this.m_impulse.Add(impulse); + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var positionError, angularError; + var K = new b2Mat33(); + K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; + K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; + K.ez.x = -rA.y * iA - rB.y * iB; + K.ex.y = K.ey.x; + K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; + K.ez.y = rA.x * iA + rB.x * iB; + K.ex.z = K.ez.x; + K.ey.z = K.ez.y; + K.ez.z = iA + iB; + if (this.m_frequencyHz > 0) { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C1.Length(); + angularError = 0; + var P = K.Solve22(C1).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } else { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var C2 = aB - aA - this.m_referenceAngle; + positionError = C1.Length(); + angularError = b2Abs(C2); + var C = new b2Vec3(C1.x, C1.y, C2); + var impulse = K.Solve33(C).Negate(); + var P = new b2Vec2(impulse.x, impulse.y); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * (b2Cross_v2_v2(rA, P) + impulse.z); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * (b2Cross_v2_v2(rB, P) + impulse.z) + } + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } +}; +b2WeldJoint._extend(b2Joint); + +function b2WheelJointDef() { + this.parent.call(this); + this.type = b2Joint.e_wheelJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.enableMotor = false; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.frequencyHz = 2; + this.dampingRatio = 0.7; + Object.seal(this) +} +b2WheelJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.localAxisA.Assign(this.bodyA.GetLocalVector(axis)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.enableMotor = data.enableMotor; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2WheelJointDef._extend(b2JointDef); + +function b2WheelJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_mass = 0; + this.m_impulse = 0; + this.m_motorMass = 0; + this.m_motorImpulse = 0; + this.m_springMass = 0; + this.m_springImpulse = 0; + this.m_maxMotorTorque = def.maxMotorTorque; + this.m_motorSpeed = def.motorSpeed; + this.m_enableMotor = def.enableMotor; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_bias = 0; + this.m_gamma = 0; + this.m_ax = new b2Vec2(); + this.m_ay = new b2Vec2(); + this.m_sAx = this.m_sBx = 0; + this.m_sAy = this.m_sBy = 0 +} +b2WheelJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetJointTranslation: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var pA = bA.GetWorldPoint(this.m_localAnchorA); + var pB = bB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = bA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var wA = this.m_bodyA.m_angularVelocity; + var wB = this.m_bodyB.m_angularVelocity; + return wB - wA + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + SetSpringFrequencyHz: function (hz) { + this.m_frequencyHz = hz + }, + GetSpringFrequencyHz: function () { + return this.m_frequencyHz + }, + SetSpringDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetSpringDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + this.m_ay.Assign(b2Mul_r_v2(qA, this.m_localYAxisA)); + this.m_sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ay); + this.m_sBy = b2Cross_v2_v2(rB, this.m_ay); + this.m_mass = mA + mB + iA * this.m_sAy * this.m_sAy + iB * this.m_sBy * this.m_sBy; + if (this.m_mass > 0) { + this.m_mass = 1 / this.m_mass + } + this.m_springMass = 0; + this.m_bias = 0; + this.m_gamma = 0; + if (this.m_frequencyHz > 0) { + this.m_ax.Assign(b2Mul_r_v2(qA, this.m_localXAxisA)); + this.m_sAx = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ax); + this.m_sBx = b2Cross_v2_v2(rB, this.m_ax); + var invMass = mA + mB + iA * this.m_sAx * this.m_sAx + iB * this.m_sBx * this.m_sBx; + if (invMass > 0) { + this.m_springMass = 1 / invMass; + var C = b2Dot_v2_v2(d, this.m_ax); + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * this.m_springMass * this.m_dampingRatio * omega; + var k = this.m_springMass * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + if (this.m_gamma > 0) { + this.m_gamma = 1 / this.m_gamma + } + this.m_bias = C * h * k * this.m_gamma; + this.m_springMass = invMass + this.m_gamma; + if (this.m_springMass > 0) { + this.m_springMass = 1 / this.m_springMass + } + } + } else { + this.m_springImpulse = 0 + } + if (this.m_enableMotor) { + this.m_motorMass = iA + iB; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + } else { + this.m_motorMass = 0; + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + this.m_springImpulse *= data.step.dtRatio; + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax)); + var LA = this.m_impulse * this.m_sAy + this.m_springImpulse * this.m_sAx + this.m_motorImpulse; + var LB = this.m_impulse * this.m_sBy + this.m_springImpulse * this.m_sBx + this.m_motorImpulse; + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * LA; + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * LB + } else { + this.m_impulse = 0; + this.m_springImpulse = 0; + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Dot_v2_v2(this.m_ax, b2Vec2.Subtract(vB, vA)) + this.m_sBx * wB - this.m_sAx * wA; + var impulse = -this.m_springMass * (Cdot + this.m_bias + this.m_gamma * this.m_springImpulse); + this.m_springImpulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ax); + var LA = impulse * this.m_sAx; + var LB = impulse * this.m_sBx; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Dot_v2_v2(this.m_ay, b2Vec2.Subtract(vB, vA)) + this.m_sBy * wB - this.m_sAy * wA; + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ay); + var LA = impulse * this.m_sAy; + var LB = impulse * this.m_sBy; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var ay = b2Mul_r_v2(qA, this.m_localYAxisA); + var sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), ay); + var sBy = b2Cross_v2_v2(rB, ay); + var C = b2Dot_v2_v2(d, ay); + var k = this.m_invMassA + this.m_invMassB + this.m_invIA * this.m_sAy * this.m_sAy + this.m_invIB * this.m_sBy * this.m_sBy; + var impulse; + if (k != 0) { + impulse = -C / k + } else { + impulse = 0 + } + var P = b2Vec2.Multiply(impulse, ay); + var LA = impulse * sAy; + var LB = impulse * sBy; + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * LA; + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) <= b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localAxisA._serialize(); + obj.enableMotor = this.m_enableMotor; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } +}; +b2WheelJoint._extend(b2Joint); + +function b2GearJointDef() { + this.parent.call(this); + this.type = b2Joint.e_gearJoint; + this.joint1 = null; + this.joint2 = null; + this.ratio = 1; + Object.seal(this) +} +b2GearJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.joint1 = data.joint1; + this.joint2 = data.joint2; + this.ratio = data.ratio + } +}; +b2GearJointDef._extend(b2JointDef); + +function b2GearJoint(def) { + this.parent.call(this, def); + this.m_joint1 = def.joint1; + this.m_joint2 = def.joint2; + this.m_typeA = this.m_joint1.GetType(); + this.m_typeB = this.m_joint2.GetType(); + var coordinateA, coordinateB; + this.m_bodyC = this.m_joint1.GetBodyA(); + this.m_bodyA = this.m_joint1.GetBodyB(); + var xfA = this.m_bodyA.m_xf; + var aA = this.m_bodyA.m_sweep.a; + var xfC = this.m_bodyC.m_xf; + var aC = this.m_bodyC.m_sweep.a; + this.m_localAnchorA = new b2Vec2(); + this.m_localAnchorB = new b2Vec2(); + this.m_localAnchorC = new b2Vec2(); + this.m_localAnchorD = new b2Vec2(); + this.m_localAxisC = new b2Vec2(); + this.m_localAxisD = new b2Vec2(); + if (this.m_typeA == b2Joint.e_revoluteJoint) { + var revolute = def.joint1; + this.m_localAnchorC.Assign(revolute.m_localAnchorA); + this.m_localAnchorA.Assign(revolute.m_localAnchorB); + this.m_referenceAngleA = revolute.m_referenceAngle; + this.m_localAxisC.SetZero(); + coordinateA = aA - aC - this.m_referenceAngleA + } else { + var prismatic = def.joint1; + this.m_localAnchorC.Assign(prismatic.m_localAnchorA); + this.m_localAnchorA.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleA = prismatic.m_referenceAngle; + this.m_localAxisC.Assign(prismatic.m_localXAxisA); + var pC = this.m_localAnchorC; + var pA = b2MulT_r_v2(xfC.q, b2Vec2.Add(b2Mul_r_v2(xfA.q, this.m_localAnchorA), b2Vec2.Subtract(xfA.p, xfC.p))); + coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) + } + this.m_bodyD = this.m_joint2.GetBodyA(); + this.m_bodyB = this.m_joint2.GetBodyB(); + var xfB = this.m_bodyB.m_xf; + var aB = this.m_bodyB.m_sweep.a; + var xfD = this.m_bodyD.m_xf; + var aD = this.m_bodyD.m_sweep.a; + if (this.m_typeB == b2Joint.e_revoluteJoint) { + var revolute = def.joint2; + this.m_localAnchorD.Assign(revolute.m_localAnchorA); + this.m_localAnchorB.Assign(revolute.m_localAnchorB); + this.m_referenceAngleB = revolute.m_referenceAngle; + this.m_localAxisD.SetZero(); + coordinateB = aB - aD - this.m_referenceAngleB + } else { + var prismatic = def.joint2; + this.m_localAnchorD.Assign(prismatic.m_localAnchorA); + this.m_localAnchorB.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleB = prismatic.m_referenceAngle; + this.m_localAxisD.Assign(prismatic.m_localXAxisA); + var pD = this.m_localAnchorD; + var pB = b2MulT_r_v2(xfD.q, b2Vec2.Add(b2Mul_r_v2(xfB.q, this.m_localAnchorB), b2Vec2.Subtract(xfB.p, xfD.p))); + coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) + } + this.m_ratio = def.ratio; + this.m_constant = coordinateA + this.m_ratio * coordinateB; + this.m_impulse = 0; + this.m_indexA = this.m_indexB = this.m_indexC = this.m_indexD = 0; + this.m_lcA = new b2Vec2(); + this.m_lcB = new b2Vec2(); + this.m_lcC = new b2Vec2(); + this.m_lcD = new b2Vec2(); + this.m_mA = this.m_mB = this.m_mC = this.m_mD = 0; + this.m_iA = this.m_iB = this.m_iC = this.m_iD = 0; + this.m_JvAC = new b2Vec2(), this.m_JvBD = new b2Vec2(); + this.m_JwA = this.m_JwB = this.m_JwC = this.m_JwD = 0; + this.m_mass = 0 +} +b2GearJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_JvAC); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + var L = this.m_impulse * this.m_JwA; + return inv_dt * L + }, + GetJoint1: function () { + return this.m_joint1 + }, + GetJoint2: function () { + return this.m_joint2 + }, + SetRatio: function (ratio) { + this.m_ratio = ratio + }, + GetRatio: function () { + return this.m_ratio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_indexC = this.m_bodyC.m_islandIndex; + this.m_indexD = this.m_bodyD.m_islandIndex; + this.m_lcA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_lcB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_lcC.Assign(this.m_bodyC.m_sweep.localCenter); + this.m_lcD.Assign(this.m_bodyD.m_sweep.localCenter); + this.m_mA = this.m_bodyA.m_invMass; + this.m_mB = this.m_bodyB.m_invMass; + this.m_mC = this.m_bodyC.m_invMass; + this.m_mD = this.m_bodyD.m_invMass; + this.m_iA = this.m_bodyA.m_invI; + this.m_iB = this.m_bodyB.m_invI; + this.m_iC = this.m_bodyC.m_invI; + this.m_iD = this.m_bodyD.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var aC = data.positions[this.m_indexC].a; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var aD = data.positions[this.m_indexD].a; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); + this.m_mass = 0; + if (this.m_typeA == b2Joint.e_revoluteJoint) { + this.m_JvAC.SetZero(); + this.m_JwA = 1; + this.m_JwC = 1; + this.m_mass += this.m_iA + this.m_iC + } else { + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + this.m_JvAC.Assign(u); + this.m_JwC = b2Cross_v2_v2(rC, u); + this.m_JwA = b2Cross_v2_v2(rA, u); + this.m_mass += this.m_mC + this.m_mA + this.m_iC * this.m_JwC * this.m_JwC + this.m_iA * this.m_JwA * this.m_JwA + } + if (this.m_typeB == b2Joint.e_revoluteJoint) { + this.m_JvBD.SetZero(); + this.m_JwB = this.m_ratio; + this.m_JwD = this.m_ratio; + this.m_mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD) + } else { + var u = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + this.m_JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + this.m_JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + this.m_JwB = this.m_ratio * b2Cross_v2_v2(rB, u); + this.m_mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * this.m_JwD * this.m_JwD + this.m_iB * this.m_JwB * this.m_JwB + } + this.m_mass = this.m_mass > 0 ? 1 / this.m_mass : 0; + if (data.step.warmStarting) { + vA.Add(b2Vec2.Multiply((this.m_mA * this.m_impulse), this.m_JvAC)); + wA += this.m_iA * this.m_impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * this.m_impulse), this.m_JvBD)); + wB += this.m_iB * this.m_impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * this.m_impulse), this.m_JvAC)); + wC -= this.m_iC * this.m_impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * this.m_impulse), this.m_JvBD)); + wD -= this.m_iD * this.m_impulse * this.m_JwD + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var Cdot = b2Dot_v2_v2(this.m_JvAC, b2Vec2.Subtract(vA, vC)) + b2Dot_v2_v2(this.m_JvBD, b2Vec2.Subtract(vB, vD)); + Cdot += (this.m_JwA * wA - this.m_JwC * wC) + (this.m_JwB * wB - this.m_JwD * wD); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + vA.Add(b2Vec2.Multiply((this.m_mA * impulse), this.m_JvAC)); + wA += this.m_iA * impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * impulse), this.m_JvBD)); + wB += this.m_iB * impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * impulse), this.m_JvAC)); + wC -= this.m_iC * impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * impulse), this.m_JvBD)); + wD -= this.m_iD * impulse * this.m_JwD; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var cC = data.positions[this.m_indexC].c.Clone(); + var aC = data.positions[this.m_indexC].a; + var cD = data.positions[this.m_indexD].c.Clone(); + var aD = data.positions[this.m_indexD].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); + var linearError = 0; + var coordinateA, coordinateB; + var JvAC = new b2Vec2(), + JvBD = new b2Vec2(); + var JwA, JwB, JwC, JwD; + var mass = 0; + if (this.m_typeA == b2Joint.e_revoluteJoint) { + JvAC.SetZero(); + JwA = 1; + JwC = 1; + mass += this.m_iA + this.m_iC; + coordinateA = aA - aC - this.m_referenceAngleA + } else { + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + JvAC.Assign(u); + JwC = b2Cross_v2_v2(rC, u); + JwA = b2Cross_v2_v2(rA, u); + mass += this.m_mC + this.m_mA + this.m_iC * JwC * JwC + this.m_iA * JwA * JwA; + var pC = b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC); + var pA = b2MulT_r_v2(qC, b2Vec2.Add(rA, b2Vec2.Subtract(cA, cC))); + coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) + } + if (this.m_typeB == b2Joint.e_revoluteJoint) { + JvBD.SetZero(); + JwB = this.m_ratio; + JwD = this.m_ratio; + mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD); + coordinateB = aB - aD - this.m_referenceAngleB + } else { + var u = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + JwB = this.m_ratio * b2Cross_v2_v2(rB, u); + mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * JwD * JwD + this.m_iB * JwB * JwB; + var pD = b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD); + var pB = b2MulT_r_v2(qD, b2Vec2.Add(rB, b2Vec2.Subtract(cB, cD))); + coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) + } + var C = (coordinateA + this.m_ratio * coordinateB) - this.m_constant; + var impulse = 0; + if (mass > 0) { + impulse = -C / mass + } + cA.Add(b2Vec2.Multiply(this.m_mA, b2Vec2.Multiply(impulse, JvAC))); + aA += this.m_iA * impulse * JwA; + cB.Add(b2Vec2.Multiply(this.m_mB, b2Vec2.Multiply(impulse, JvBD))); + aB += this.m_iB * impulse * JwB; + cC.Subtract(b2Vec2.Multiply(this.m_mC, b2Vec2.Multiply(impulse, JvAC))); + aC -= this.m_iC * impulse * JwC; + cD.Subtract(b2Vec2.Multiply(this.m_mD, b2Vec2.Multiply(impulse, JvBD))); + aD -= this.m_iD * impulse * JwD; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + data.positions[this.m_indexC].c.Assign(cC); + data.positions[this.m_indexC].a = aC; + data.positions[this.m_indexD].c.Assign(cD); + data.positions[this.m_indexD].a = aD; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.joint1 = this.m_joint1.__temp_joint_id; + obj.joint2 = this.m_joint2.__temp_joint_id; + obj.ratio = this.m_ratio; + return obj + } +}; +b2GearJoint._extend(b2Joint); + +function b2MotorJointDef() { + this.parent.call(this); + this.type = b2Joint.e_motorJoint; + this.linearOffset = new b2Vec2(); + this.angularOffset = 0; + this.maxForce = 1; + this.maxTorque = 1; + this.correctionFactor = 0.3; + Object.seal(this) +} +b2MotorJointDef.prototype = { + Initialize: function (bA, bB) { + this.bodyA = bA; + this.bodyB = bB; + var xB = this.bodyB.GetPosition(); + this.linearOffset.Assign(this.bodyA.GetLocalPoint(xB)); + var angleA = this.bodyA.GetAngle(); + var angleB = this.bodyB.GetAngle(); + this.angularOffset = angleB - angleA + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.linearOffset._deserialize(data.linearOffset); + this.angularOffset = data.angularOffset; + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque; + this.correctionFactor = data.correctionFactor + } +}; +b2MotorJointDef._extend(b2JointDef); + +function b2MotorJoint(def) { + this.parent.call(this, def); + this.m_linearOffset = def.linearOffset.Clone(); + this.m_angularOffset = def.angularOffset; + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_correctionFactor = def.correctionFactor; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_linearError = new b2Vec2(); + this.m_angularError = 0; + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 +} +b2MotorJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetPosition() + }, + GetAnchorB: function () { + return this.m_bodyB.GetPosition() + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + SetLinearOffset: function (linearOffset) { + if (linearOffset.x != this.m_linearOffset.x || linearOffset.y != this.m_linearOffset.y) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_linearOffset.Assign(linearOffset) + } + }, + GetLinearOffset: function () { + return this.m_linearOffset + }, + SetAngularOffset: function (angularOffset) { + if (angularOffset != this.m_angularOffset) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_angularOffset = angularOffset + } + }, + GetAngularOffset: function () { + return this.m_angularOffset + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + SetCorrectionFactor: function (factor) { + this.m_correctionFactor = factor + }, + GetCorrectionFactor: function () { + return this.m_correctionFactor + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, this.m_localCenterA.Negate())); + this.m_rB.Assign(b2Mul_r_v2(qB, this.m_localCenterB.Negate())); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y; + K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x; + this.m_linearMass.Assign(K.GetInverse()); + this.m_angularMass = iA + iB; + if (this.m_angularMass > 0) { + this.m_angularMass = 1 / this.m_angularMass + } + this.m_linearError.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA), b2Mul_r_v2(qA, this.m_linearOffset))); + this.m_angularError = aB - aA - this.m_angularOffset; + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var inv_h = data.step.inv_dt; + var Cdot = wB - wA + inv_h * this.m_correctionFactor * this.m_angularError; + var impulse = -this.m_angularMass * Cdot; + var oldImpulse = this.m_angularImpulse; + var maxImpulse = h * this.m_maxTorque; + this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)), b2Vec2.Multiply(inv_h, b2Vec2.Multiply(this.m_correctionFactor, this.m_linearError))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse; + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse.Assign(b2Vec2.Subtract(this.m_linearImpulse, oldImpulse)); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.linearOffset = this.m_linearOffset._serialize(); + obj.angularOffset = this.m_angularOffset; + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + obj.correctionFactor = this.m_correctionFactor; + return obj + } +}; +b2MotorJoint._extend(b2Joint); +var b2_minPulleyLength = 2; + +function b2PulleyJointDef() { + this.parent.call(this); + this.type = b2Joint.e_pulleyJoint; + this.groundAnchorA = new b2Vec2(-1, 1); + this.groundAnchorB = new b2Vec2(1, 1); + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.lengthA = 0; + this.lengthB = 0; + this.ratio = 1; + this.collideConnected = true; + Object.seal(this) +} +b2PulleyJointDef.prototype = { + Initialize: function (bA, bB, groundA, groundB, anchorA, anchorB, r) { + this.bodyA = bA; + this.bodyB = bB; + this.groundAnchorA.Assign(groundA); + this.groundAnchorB.Assign(groundB); + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchorA)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchorB)); + var dA = b2Vec2.Subtract(anchorA, groundA); + this.lengthA = dA.Length(); + var dB = b2Vec2.Subtract(anchorB, groundB); + this.lengthB = dB.Length(); + this.ratio = r + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.groundAnchorA._deserialize(data.groundAnchorA); + this.groundAnchorB._deserialize(data.groundAnchorB); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.lengthA = data.lengthA; + this.lengthB = data.lengthB; + this.ratio = data.ratio + } +}; +b2PulleyJointDef._extend(b2JointDef); + +function b2PulleyJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_uA = new b2Vec2(); + this.m_uB = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0; + this.m_groundAnchorA = def.groundAnchorA.Clone(); + this.m_groundAnchorB = def.groundAnchorB.Clone(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_lengthA = def.lengthA; + this.m_lengthB = def.lengthB; + this.m_ratio = def.ratio; + this.m_constant = def.lengthA + this.m_ratio * def.lengthB; + this.m_impulse = 0 +} +b2PulleyJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_uB); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetGroundAnchorA: function () { + return this.m_groundAnchorA + }, + GetGroundAnchorB: function () { + return this.m_groundAnchorB + }, + GetLengthA: function () { + return this.m_lengthA + }, + GetLengthB: function () { + return this.m_lengthB + }, + GetRatio: function () { + return this.m_ratio + }, + GetCurrentLengthA: function () { + var p = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var s = this.m_groundAnchorA; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + GetCurrentLengthB: function () { + var p = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var s = this.m_groundAnchorB; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + ShiftOrigin: function (newOrigin) { + this.m_groundAnchorA.Subtract(newOrigin); + this.m_groundAnchorB.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_uA.Assign(b2Vec2.Add(cA, b2Vec2.Subtract(this.m_rA, this.m_groundAnchorA))); + this.m_uB.Assign(b2Vec2.Add(cB, b2Vec2.Subtract(this.m_rB, this.m_groundAnchorB))); + var lengthA = this.m_uA.Length(); + var lengthB = this.m_uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + this.m_uA.Multiply(1 / lengthA) + } else { + this.m_uA.SetZero() + } + if (lengthB > 10 * b2_linearSlop) { + this.m_uB.Multiply(1 / lengthB) + } else { + this.m_uB.SetZero() + } + var ruA = b2Cross_v2_v2(this.m_rA, this.m_uA); + var ruB = b2Cross_v2_v2(this.m_rB, this.m_uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + this.m_mass = mA + this.m_ratio * this.m_ratio * mB; + if (this.m_mass > 0) { + this.m_mass = 1 / this.m_mass + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var PA = b2Vec2.Multiply(-(this.m_impulse), this.m_uA); + var PB = b2Vec2.Multiply((-this.m_ratio * this.m_impulse), this.m_uB); + vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); + vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = -b2Dot_v2_v2(this.m_uA, vpA) - this.m_ratio * b2Dot_v2_v2(this.m_uB, vpB); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var PA = b2Vec2.Multiply(-impulse, this.m_uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, this.m_uB)); + vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); + vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var uA = b2Vec2.Add(cA, b2Vec2.Subtract(rA, this.m_groundAnchorA)); + var uB = b2Vec2.Add(cB, b2Vec2.Subtract(rB, this.m_groundAnchorB)); + var lengthA = uA.Length(); + var lengthB = uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + uA.Multiply(1 / lengthA) + } else { + uA.SetZero() + } + if (lengthB > 10 * b2_linearSlop) { + uB.Multiply(1 / lengthB) + } else { + uB.SetZero() + } + var ruA = b2Cross_v2_v2(rA, uA); + var ruB = b2Cross_v2_v2(rB, uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + var mass = mA + this.m_ratio * this.m_ratio * mB; + if (mass > 0) { + mass = 1 / mass + } + var C = this.m_constant - lengthA - this.m_ratio * lengthB; + var linearError = b2Abs(C); + var impulse = -mass * C; + var PA = b2Vec2.Multiply(-impulse, uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, uB)); + cA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + aA += this.m_invIA * b2Cross_v2_v2(rA, PA); + cB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + aB += this.m_invIB * b2Cross_v2_v2(rB, PB); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.groundAnchorA = this.m_groundAnchorA._serialize(); + obj.groundAnchorB = this.m_groundAnchorB._serialize(); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.lengthA = this.m_lengthA; + obj.lengthB = this.m_lengthB; + obj.ratio = this.m_ratio; + return obj + } +}; +b2PulleyJoint._extend(b2Joint); + +function b2RopeJointDef() { + this.parent.call(this); + this.type = b2Joint.e_ropeJoint; + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.maxLength = 0; + Object.seal(this) +} +b2RopeJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxLength = data.maxLength + } +}; +b2RopeJointDef._extend(b2JointDef); + +function b2RopeJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_maxLength = def.maxLength; + this.m_mass = 0; + this.m_impulse = 0; + this.m_state = b2Joint.e_inactiveLimit; + this.m_length = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0 +} +b2RopeJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxLength: function (length) { + this.m_maxLength = length + }, + GetMaxLength: function () { + return this.m_maxLength + }, + GetLimitState: function () { + return this.m_state + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_u.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA)); + this.m_length = this.m_u.Length(); + var C = this.m_length - this.m_maxLength; + if (C > 0) { + this.m_state = b2Joint.e_atUpperLimit + } else { + this.m_state = b2Joint.e_inactiveLimit + } + if (this.m_length > b2_linearSlop) { + this.m_u.Multiply(1 / this.m_length) + } else { + this.m_u.SetZero(); + this.m_mass = 0; + this.m_impulse = 0; + return + } + var crA = b2Cross_v2_v2(this.m_rA, this.m_u); + var crB = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crA * crA + this.m_invMassB + this.m_invIB * crB * crB; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var C = this.m_length - this.m_maxLength; + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + if (C < 0) { + Cdot += data.step.inv_dt * C + } + var impulse = -this.m_mass * Cdot; + var oldImpulse = this.m_impulse; + this.m_impulse = b2Min(0, this.m_impulse + impulse); + impulse = this.m_impulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_maxLength; + C = b2Clamp(C, 0, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return length - this.m_maxLength < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxLength = this.m_maxLength; + return obj + } +}; +b2RopeJoint._extend(b2Joint); +var expf = Math.exp; + +function b2RopeDef() { + this.vertices = null; + this.count = 0; + this.masses = null; + this.gravity = new b2Vec2(); + this.damping = 0.1; + this.k2 = 0.9; + this.k3 = 0.1 +} + +function b2Rope() { + this.m_count = 0; + this.m_ps = null; + this.m_p0s = null; + this.m_vs = null; + this.m_ims = null; + this.m_Ls = null; + this.m_as = null; + this.m_damping = 0; + this.m_gravity = new b2Vec2(); + this.m_k2 = 1; + this.m_k3 = 0.1 +} +b2Rope.prototype = { + Initialize: function (def) { + this.m_count = def.count; + this.m_ps = new Array(this.m_count); + this.m_p0s = new Array(this.m_count); + this.m_vs = new Array(this.m_count); + this.m_ims = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + this.m_ps[i] = def.vertices[i].Clone(); + this.m_p0s[i] = def.vertices[i].Clone(); + this.m_vs[i] = new b2Vec2(); + var m = def.masses[i]; + if (m > 0) { + this.m_ims[i] = 1 / m + } else { + this.m_ims[i] = 0 + } + } + var count2 = this.m_count - 1; + var count3 = this.m_count - 2; + this.m_Ls = new Array(count2); + this.m_as = new Array(count3); + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + this.m_Ls[i] = b2Distance(p1, p2) + } + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + this.m_as[i] = b2Atan2(a, b) + } + this.m_gravity = def.gravity.Clone(); + this.m_damping = def.damping; + this.m_k2 = def.k2; + this.m_k3 = def.k3 + }, + Step: function (h, iterations) { + if (h == 0) { + return + } + var d = expf(-h * this.m_damping); + for (var i = 0; i < this.m_count; ++i) { + this.m_p0s[i].Assign(this.m_ps[i]); + if (this.m_ims[i] > 0) { + this.m_vs[i].Add(b2Vec2.Multiply(h, this.m_gravity)) + } + this.m_vs[i].Multiply(d); + this.m_ps[i].Add(b2Vec2.Multiply(h, this.m_vs[i])) + } + for (var i = 0; i < iterations; ++i) { + this.SolveC2(); + this.SolveC3(); + this.SolveC2() + } + var inv_h = 1 / h; + for (var i = 0; i < this.m_count; ++i) { + this.m_vs[i] = b2Vec2.Multiply(inv_h, b2Vec2.Subtract(this.m_ps[i], this.m_p0s[i])) + } + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertices: function () { + return this.m_ps + }, + Draw: function (draw) { + var c = new b2Color(0.4, 0.5, 0.7); + for (var i = 0; i < this.m_count - 1; ++i) { + draw.DrawSegment(this.m_ps[i], this.m_ps[i + 1], c) + } + }, + SetAngle: function (angle) { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + this.m_as[i] = angle + } + }, + SolveC2: function () { + var count2 = this.m_count - 1; + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var d = b2Vec2.Subtract(p2, p1); + var L = d.Normalize(); + var im1 = this.m_ims[i]; + var im2 = this.m_ims[i + 1]; + if (im1 + im2 == 0) { + continue + } + var s1 = im1 / (im1 + im2); + var s2 = im2 / (im1 + im2); + p1.Subtract(b2Vec2.Multiply(this.m_k2 * s1 * (this.m_Ls[i] - L), d)); + p2.Add(b2Vec2.Multiply(this.m_k2 * s2 * (this.m_Ls[i] - L), d)) + } + }, + SolveC3: function () { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var m1 = this.m_ims[i]; + var m2 = this.m_ims[i + 1]; + var m3 = this.m_ims[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var L1sqr = d1.LengthSquared(); + var L2sqr = d2.LengthSquared(); + if (L1sqr * L2sqr == 0) { + continue + } + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + var angle = b2Atan2(a, b); + var Jd1 = b2Vec2.Multiply((-1 / L1sqr), d1.Skew()); + var Jd2 = b2Vec2.Multiply((1 / L2sqr), d2.Skew()); + var J1 = b2Vec2.Negate(Jd1); + var J2 = b2Vec2.Subtract(Jd1, Jd2); + var J3 = Jd2; + var mass = m1 * b2Dot_v2_v2(J1, J1) + m2 * b2Dot_v2_v2(J2, J2) + m3 * b2Dot_v2_v2(J3, J3); + if (mass == 0) { + continue + } + mass = 1 / mass; + var C = angle - this.m_as[i]; + while (C > b2_pi) { + angle -= 2 * b2_pi; + C = angle - this.m_as[i] + } + while (C < -b2_pi) { + angle += 2 * b2_pi; + C = angle - this.m_as[i] + } + var impulse = -this.m_k3 * mass * C; + p1.Add(b2Vec2.Multiply((m1 * impulse), J1)); + p2.Add(b2Vec2.Multiply((m2 * impulse), J2)); + p3.Add(b2Vec2.Multiply((m3 * impulse), J3)) + } + } +}; +var b2JsonSerializer = { + serialize: function (world) { + var shapes = []; + var i; + var serialized; + var b; + var f; + var shape; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + shape = f.GetShape(); + f.__temp_shape_id = shapes.length; + shapes.push(shape._serialize()) + } + } + var fixtures = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + b.__temp_fixture_ids = []; + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + serialized = f._serialize(); + serialized.shape = f.__temp_shape_id; + delete f.__temp_shape_id; + b.__temp_fixture_ids.push(fixtures.length); + fixtures.push(serialized) + } + } + var bodies = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + serialized = b._serialize(); + serialized.fixtures = []; + for (i = 0; i < b.__temp_fixture_ids.length; ++i) { + serialized.fixtures.push(b.__temp_fixture_ids[i]) + } + delete b.__temp_fixture_ids; + b.__temp_body_id = bodies.length; + bodies.push(serialized) + } + var joints = []; + var j; + for (j = world.GetJointList(), i = 0; j; j = j.GetNext(), ++i) { + j.__temp_joint_id = i + } + for (j = world.GetJointList(); j; j = j.GetNext()) { + if (j.GetType() === b2Joint.e_mouseJoint) { + continue + } + serialized = j._serialize(); + serialized.bodyA = j.GetBodyA().__temp_body_id; + serialized.bodyB = j.GetBodyB().__temp_body_id; + joints.push(serialized) + } + for (j = world.GetJointList(); j; j = j.GetNext()) { + delete j.__temp_joint_id + } + for (b = world.GetBodyList(); b; b = b.GetNext()) { + delete b.__temp_body_id + } + return { + shapes: shapes, + fixtures: fixtures, + bodies: bodies, + joints: joints + } + }, + deserialize: function (serialized, world, clear) { + var deserialized = JSON.parse(serialized); + if (clear) { + for (var b = world.GetBodyList(); b;) { + var next = b.GetNext(); + world.DestroyBody(b); + b = next + } + for (var j = world.GetJointList(); j;) { + var next = j.GetNext(); + world.DestroyJoint(j); + j = next + } + } + var shapes = []; + for (var i = 0; i < deserialized.shapes.length; ++i) { + var shapeData = deserialized.shapes[i]; + var shape; + switch (shapeData.m_type) { + case b2Shape.e_circle: + shape = new b2CircleShape(); + break; + case b2Shape.e_edge: + shape = new b2EdgeShape(); + break; + case b2Shape.e_chain: + shape = new b2ChainShape(); + break; + case b2Shape.e_polygon: + shape = new b2PolygonShape(); + break + } + shape._deserialize(shapeData); + shapes.push(shape) + } + var fixtures = []; + for (i = 0; i < deserialized.fixtures.length; ++i) { + var fixtureData = deserialized.fixtures[i]; + var fixture = new b2FixtureDef(); + fixture._deserialize(fixtureData); + fixture.shape = shapes[fixtureData.shape]; + fixtures.push(fixture) + } + var bodies = []; + for (i = 0; i < deserialized.bodies.length; ++i) { + var bodyData = deserialized.bodies[i]; + var def = new b2BodyDef(); + def._deserialize(bodyData); + var body = world.CreateBody(def); + for (var x = 0; x < bodyData.fixtures.length; ++x) { + body.CreateFixture(fixtures[bodyData.fixtures[x]]) + } + bodies.push(body) + } + var joints = []; + var gears = []; + for (i = 0; i < deserialized.joints.length; ++i) { + var jointData = deserialized.joints[i]; + var jointDef; + switch (jointData.type) { + case b2Joint.e_revoluteJoint: + jointDef = new b2RevoluteJointDef(); + break; + case b2Joint.e_prismaticJoint: + jointDef = new b2PrismaticJointDef(); + break; + case b2Joint.e_distanceJoint: + jointDef = new b2DistanceJointDef(); + break; + case b2Joint.e_pulleyJoint: + jointDef = new b2PulleyJointDef(); + break; + case b2Joint.e_gearJoint: + jointDef = new b2GearJointDef(); + break; + case b2Joint.e_wheelJoint: + jointDef = new b2WheelJointDef(); + break; + case b2Joint.e_weldJoint: + jointDef = new b2WeldJointDef(); + break; + case b2Joint.e_frictionJoint: + jointDef = new b2FrictionJointDef(); + break; + case b2Joint.e_ropeJoint: + jointDef = new b2RopeJointDef(); + break; + case b2Joint.e_motorJoint: + jointDef = new b2MotorJointDef(); + break; + default: + throw new Error("unknown joint") + } + jointDef._deserialize(jointData, bodies); + if (jointData.type === b2Joint.e_gearJoint) { + gears.push([jointDef, joints.length]); + joints.push(null) + } else { + var joint = world.CreateJoint(jointDef); + joints.push(joint) + } + } + for (i = 0; i < gears.length; ++i) { + gears[i][0].joint1 = joints[gears[i][0].joint1]; + gears[i][0].joint2 = joints[gears[i][0].joint2]; + joint = world.CreateJoint(gears[i][0]); + joints[gears[i][1]] = joint + } + } +}; +var b2RUBELoader = (function () { + function parseVector(obj) { + return new b2Vec2(obj ? (obj.x || 0) : 0, obj ? (obj.y || 0) : 0) + } + + function parseVectorArray(obj) { + var vals = new Array(obj.x.length); + for (var i = 0; i < vals.length; ++i) { + vals[i] = new b2Vec2(obj.x[i], obj.y[i]) + } + return vals + } + + function parseProperty(obj, instance) { + var name = obj.name; + var val; + if (typeof (obj["int"]) !== "undefined") { + val = obj["int"] + } else { + if (typeof (obj["float"]) !== "undefined") { + val = obj["float"] + } else { + if (typeof (obj.string) !== "undefined") { + val = obj.string + } else { + if (typeof (obj.bool) !== "undefined") { + val = obj.bool + } else { + if (typeof (obj.vec2) !== "undefined") { + val = parseVector(obj.vec2) + } else { + throw new Error("unknown property type") + } + } + } + } + } + if (instance.hasOwnProperty(name)) { + throw new Error("custom property possibly overwriting an existing one") + } + instance[name] = val + } + + function parseFixture(obj, body) { + var def = new b2FixtureDef(); + def.density = obj.density || 0; + def.filter.categoryBits = typeof (obj["filter-categoryBits"]) === "undefined" ? 1 : obj["filter-categoryBits"]; + def.filter.maskBits = typeof (obj["filter-maskBits"]) === "undefined" ? 65535 : obj["filter-maskBits"]; + def.filter.groupIndex = typeof (obj["filter-groupIndex"]) === "undefined" ? 0 : obj["filter-groupIndex"]; + def.friction = obj.friction || 0; + def.restitution = obj.restitution || 0; + def.isSensor = obj.sensor || 0; + var shape; + if (typeof (obj.circle) !== "undefined") { + shape = new b2CircleShape(); + shape.m_p = parseVector(obj.circle.center); + shape.m_radius = obj.circle.radius || 0 + } else { + if (typeof (obj.polygon) !== "undefined") { + var vertices = parseVectorArray(obj.polygon.vertices); + shape = new b2PolygonShape(); + shape.Set(vertices, vertices.length) + } else { + if (typeof (obj.chain) !== "undefined") { + var vertices = parseVectorArray(obj.chain.vertices); + shape = new b2ChainShape(); + shape.m_count = vertices.length; + shape.m_vertices = vertices; + if (shape.m_hasNextVertex = obj.chain.hasNextVertex) { + shape.m_nextVertex = parseVector(obj.chain.nextVertex) + } + if (shape.m_hasPrevVertex = obj.chain.hasPrevVertex) { + shape.m_prevVertex = parseVector(obj.chain.prevVertex) + } + } else { + throw new Error("unknown shape type") + } + } + } + def.shape = shape; + var fixture = body.CreateFixture(def); + fixture.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, fixture) + } + } + } + + function parseBody(obj, world) { + var def = new b2BodyDef(); + def.type = obj.type || b2Body.b2_staticBody; + def.angle = obj.angle || 0; + def.angularDamping = obj.angularDamping || 0; + def.angularVelocity = obj.angularVelocity || 0; + def.awake = obj.awake || false; + def.bullet = obj.bullet || false; + def.fixedRotation = obj.fixedRotation || false; + def.linearDamping = obj.linearDamping || false; + def.linearVelocity = parseVector(obj.linearVelocity); + def.gravityScale = typeof (obj.gravityScale) !== "undefined" ? obj.gravityScale : 1; + var md = new b2MassData(); + md.mass = obj["massData-mass"] || 0; + md.center = parseVector(obj["massData-center"]); + md.I = obj["massData-I"] || 0; + def.position = parseVector(obj.position); + var body = world.CreateBody(def); + body.name = obj.name; + body.SetMassData(md); + if (obj.fixture) { + for (var i = 0; i < obj.fixture.length; ++i) { + parseFixture(obj.fixture[i], body) + } + } + if (obj.customProperties) { + for (i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, body) + } + } + return body + } + var jointsList = { + revolute: b2RevoluteJointDef, + distance: b2DistanceJointDef, + prismatic: b2PrismaticJointDef, + wheel: b2WheelJointDef, + rope: b2RopeJointDef, + motor: b2MotorJointDef, + weld: b2WeldJointDef, + friction: b2FrictionJointDef + }; + + function parseJoint(obj, world, bodies) { + if (!jointsList[obj.type]) { + throw new Error("unknown joint type") + } + var jd = new jointsList[obj.type](); + switch (jd.type) { + case b2Joint.e_revoluteJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.lowerAngle = obj.lowerLimit || 0; + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperAngle = obj.upperLimit || 0; + break; + case b2Joint.e_distanceJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequency || 0; + jd.length = obj.length || 0; + break; + case b2Joint.e_prismaticJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.lowerTranslation = obj.lowerLimit || 0; + jd.maxMotorForce = obj.maxMotorForce || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperTranslation = obj.upperLimit || 0; + break; + case b2Joint.e_wheelJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.dampingRatio = obj.springDampingRatio || 0; + jd.frequencyHz = obj.springFrequency || 0; + break; + case b2Joint.e_ropeJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxLength = obj.maxLength || 0; + break; + case b2Joint.e_motorJoint: + jd.linearOffset = parseVector(obj.anchorA); + jd.angularOffset = obj.refAngle || 0; + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + jd.correctionFactor = obj.correctionFactor || 0; + break; + case b2Joint.e_weldJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.referenceAngle = obj.refAngle || 0; + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequencyHz || 0; + break; + case b2Joint.e_frictionJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + break; + default: + throw new Error("wat?") + } + jd.bodyA = bodies[obj.bodyA || 0]; + jd.bodyB = bodies[obj.bodyB || 0]; + jd.collideConnected = obj.collideConnected || false; + var joint = world.CreateJoint(jd); + joint.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, joint) + } + } + return joint + } + + function b2RubeParameters() { + this.world = null; + this.positionIterations = 0; + this.velocityIterations = 0; + this.stepsPerSecond = 0; + this.fixtures = {}; + this.bodies = {}; + this.joints = {}; + Object.seal(this) + } + + function parseWorld(obj, world) { + var params = new b2RubeParameters(); + params.world = world = world || new b2World(new b2Vec2(0, 0)); + params.positionIterations = obj.positionIterations || 0; + params.velocityIterations = obj.velocityIterations || 0; + params.stepsPerSecond = obj.stepsPerSecond || 0; + if (obj.gravity) { + world.SetGravity(parseVector(obj.gravity)) + } + world.SetAllowSleeping(obj.allowSleep || false); + world.SetAutoClearForces(obj.autoClearForces || false); + world.SetWarmStarting(obj.warmStarting || false); + world.SetContinuousPhysics(obj.continuousPhysics || false); + world.SetSubStepping(obj.subStepping || false); + var bodies = []; + var bl = obj.body; + if (bl) { + for (var i = 0; i < bl.length; ++i) { + var body = parseBody(bl[i], world); + bodies.push(body); + for (var f = body.GetFixtureList(); f; f = f.GetNext()) { + if (!params.fixtures[f.name]) { + params.fixtures[f.name] = [] + } + params.fixtures[f.name].push(f) + } + if (!params.bodies[body.name]) { + params.bodies[body.name] = [] + } + params.bodies[body.name].push(body) + } + } + var joints = []; + var jl = obj.joint; + if (jl) { + for (i = 0; i < jl.length; ++i) { + var joint = parseJoint(jl[i], world, bodies); + joints.push(joint); + if (!params.joints[joint.name]) { + params.joints[joint.name] = [] + } + params.joints[joint.name].push(joint) + } + } + return params + } + return { + parseWorld: parseWorld + } +})(); +var mappings = [{ + trimmed: "version", + name: "b2_version", + def: b2_version +}, { + trimmed: "Vec2", + name: "b2Vec2", + def: b2Vec2 +}, { + trimmed: "Vec3", + name: "b2Vec3", + def: b2Vec3 +}, { + trimmed: "Mat22", + name: "b2Mat22", + def: b2Mat22 +}, { + trimmed: "Mat33", + name: "b2Mat33", + def: b2Mat33 +}, { + trimmed: "Rot", + name: "b2Rot", + def: b2Rot +}, { + trimmed: "Transform", + name: "b2Transform", + def: b2Transform +}, { + trimmed: "Sweep", + name: "b2Sweep", + def: b2Sweep +}, { + trimmed: "Dot_v2_v2", + name: "b2Dot_v2_v2", + def: b2Dot_v2_v2 +}, { + trimmed: "Cross_v2_v2", + name: "b2Cross_v2_v2", + def: b2Cross_v2_v2 +}, { + trimmed: "Cross_v2_f", + name: "b2Cross_v2_f", + def: b2Cross_v2_f +}, { + trimmed: "Cross_f_v2", + name: "b2Cross_f_v2", + def: b2Cross_f_v2 +}, { + trimmed: "Mul_m22_v2", + name: "b2Mul_m22_v2", + def: b2Mul_m22_v2 +}, { + trimmed: "MulT_m22_v2", + name: "b2MulT_m22_v2", + def: b2MulT_m22_v2 +}, { + trimmed: "Distance", + name: "b2Distance", + def: b2Distance +}, { + trimmed: "DistanceSquared", + name: "b2DistanceSquared", + def: b2DistanceSquared +}, { + trimmed: "Dot_v3_v3", + name: "b2Dot_v3_v3", + def: b2Dot_v3_v3 +}, { + trimmed: "Cross_v3_v3", + name: "b2Cross_v3_v3", + def: b2Cross_v3_v3 +}, { + trimmed: "Mul_m22_m22", + name: "b2Mul_m22_m22", + def: b2Mul_m22_m22 +}, { + trimmed: "MulT_m22_m22", + name: "b2MulT_m22_m22", + def: b2MulT_m22_m22 +}, { + trimmed: "Mul_m33_v3", + name: "b2Mul_m33_v3", + def: b2Mul_m33_v3 +}, { + trimmed: "Mul22_m33_v2", + name: "b2Mul22_m33_v2", + def: b2Mul22_m33_v2 +}, { + trimmed: "Mul_r_r", + name: "b2Mul_r_r", + def: b2Mul_r_r +}, { + trimmed: "MulT_r_r", + name: "b2MulT_r_r", + def: b2MulT_r_r +}, { + trimmed: "Mul_r_v2", + name: "b2Mul_r_v2", + def: b2Mul_r_v2 +}, { + trimmed: "MulT_r_v2", + name: "b2MulT_r_v2", + def: b2MulT_r_v2 +}, { + trimmed: "Mul_t_v2", + name: "b2Mul_t_v2", + def: b2Mul_t_v2 +}, { + trimmed: "Min_v2", + name: "b2Min_v2", + def: b2Min_v2 +}, { + trimmed: "Max_v2", + name: "b2Max_v2", + def: b2Max_v2 +}, { + trimmed: "Clamp", + name: "b2Clamp", + def: b2Clamp +}, { + trimmed: "MulT_t_v2", + name: "b2MulT_t_v2", + def: b2MulT_t_v2 +}, { + trimmed: "Mul_t_t", + name: "b2Mul_t_t", + def: b2Mul_t_t +}, { + trimmed: "MulT_t_t", + name: "b2MulT_t_t", + def: b2MulT_t_t +}, { + trimmed: "Clamp_v2", + name: "b2Clamp_v2", + def: b2Clamp_v2 +}, { + trimmed: "NextPowerOfTwo", + name: "b2NextPowerOfTwo", + def: b2NextPowerOfTwo +}, { + trimmed: "Abs_v2", + name: "b2Abs_v2", + def: b2Abs_v2 +}, { + trimmed: "Abs_m22", + name: "b2Abs_m22", + def: b2Abs_m22 +}, { + trimmed: "IsPowerOfTwo", + name: "b2IsPowerOfTwo", + def: b2IsPowerOfTwo +}, { + trimmed: "RandomFloat", + name: "b2RandomFloat", + def: b2RandomFloat +}, { + trimmed: "Timer", + name: "b2Timer", + def: b2Timer +}, { + trimmed: "Color", + name: "b2Color", + def: b2Color +}, { + trimmed: "Draw", + name: "b2Draw", + def: b2Draw +}, { + trimmed: "ContactID", + name: "b2ContactID", + def: b2ContactID +}, { + trimmed: "ManifoldPoint", + name: "b2ManifoldPoint", + def: b2ManifoldPoint +}, { + trimmed: "Manifold", + name: "b2Manifold", + def: b2Manifold +}, { + trimmed: "WorldManifold", + name: "b2WorldManifold", + def: b2WorldManifold +}, { + trimmed: "GetPointStates", + name: "b2GetPointStates", + def: b2GetPointStates +}, { + trimmed: "ClipVertex", + name: "b2ClipVertex", + def: b2ClipVertex +}, { + trimmed: "RayCastInput", + name: "b2RayCastInput", + def: b2RayCastInput +}, { + trimmed: "RayCastOutput", + name: "b2RayCastOutput", + def: b2RayCastOutput +}, { + trimmed: "AABB", + name: "b2AABB", + def: b2AABB +}, { + trimmed: "CollideCircles", + name: "b2CollideCircles", + def: b2CollideCircles +}, { + trimmed: "CollidePolygonAndCircle", + name: "b2CollidePolygonAndCircle", + def: b2CollidePolygonAndCircle +}, { + trimmed: "FindMaxSeparation", + name: "b2FindMaxSeparation", + def: b2FindMaxSeparation +}, { + trimmed: "FindIncidentEdge", + name: "b2FindIncidentEdge", + def: b2FindIncidentEdge +}, { + trimmed: "CollidePolygons", + name: "b2CollidePolygons", + def: b2CollidePolygons +}, { + trimmed: "CollideEdgeAndCircle", + name: "b2CollideEdgeAndCircle", + def: b2CollideEdgeAndCircle +}, { + trimmed: "EPAxis", + name: "b2EPAxis", + def: b2EPAxis +}, { + trimmed: "TempPolygon", + name: "b2TempPolygon", + def: b2TempPolygon +}, { + trimmed: "ReferenceFace", + name: "b2ReferenceFace", + def: b2ReferenceFace +}, { + trimmed: "EPCollider", + name: "b2EPCollider", + def: b2EPCollider +}, { + trimmed: "CollideEdgeAndPolygon", + name: "b2CollideEdgeAndPolygon", + def: b2CollideEdgeAndPolygon +}, { + trimmed: "ClipSegmentToLine", + name: "b2ClipSegmentToLine", + def: b2ClipSegmentToLine +}, { + trimmed: "TestShapeOverlap", + name: "b2TestShapeOverlap", + def: b2TestShapeOverlap +}, { + trimmed: "TestOverlap", + name: "b2TestOverlap", + def: b2TestOverlap +}, { + trimmed: "Shape", + name: "b2Shape", + def: b2Shape +}, { + trimmed: "CircleShape", + name: "b2CircleShape", + def: b2CircleShape +}, { + trimmed: "EdgeShape", + name: "b2EdgeShape", + def: b2EdgeShape +}, { + trimmed: "ChainShape", + name: "b2ChainShape", + def: b2ChainShape +}, { + trimmed: "PolygonShape", + name: "b2PolygonShape", + def: b2PolygonShape +}, { + trimmed: "Pair", + name: "b2Pair", + def: b2Pair +}, { + trimmed: "PairLessThan", + name: "b2PairLessThan", + def: b2PairLessThan +}, { + trimmed: "BroadPhase", + name: "b2BroadPhase", + def: b2BroadPhase +}, { + trimmed: "DistanceProxy", + name: "b2DistanceProxy", + def: b2DistanceProxy +}, { + trimmed: "SimplexCache", + name: "b2SimplexCache", + def: b2SimplexCache +}, { + trimmed: "DistanceInput", + name: "b2DistanceInput", + def: b2DistanceInput +}, { + trimmed: "DistanceOutput", + name: "b2DistanceOutput", + def: b2DistanceOutput +}, { + trimmed: "SimplexVertex", + name: "b2SimplexVertex", + def: b2SimplexVertex +}, { + trimmed: "Simplex", + name: "b2Simplex", + def: b2Simplex +}, { + trimmed: "DistanceFunc", + name: "b2DistanceFunc", + def: b2DistanceFunc +}, { + trimmed: "TreeNode", + name: "b2TreeNode", + def: b2TreeNode +}, { + trimmed: "DynamicTree", + name: "b2DynamicTree", + def: b2DynamicTree +}, { + trimmed: "TOIInput", + name: "b2TOIInput", + def: b2TOIInput +}, { + trimmed: "TOIOutput", + name: "b2TOIOutput", + def: b2TOIOutput +}, { + trimmed: "SeparationFunction", + name: "b2SeparationFunction", + def: b2SeparationFunction +}, { + trimmed: "TimeOfImpact", + name: "b2TimeOfImpact", + def: b2TimeOfImpact +}, { + trimmed: "BodyDef", + name: "b2BodyDef", + def: b2BodyDef +}, { + trimmed: "Body", + name: "b2Body", + def: b2Body +}, { + trimmed: "Filter", + name: "b2Filter", + def: b2Filter +}, { + trimmed: "FixtureDef", + name: "b2FixtureDef", + def: b2FixtureDef +}, { + trimmed: "Fixture", + name: "b2Fixture", + def: b2Fixture +}, { + trimmed: "DestructionListener", + name: "b2DestructionListener", + def: b2DestructionListener +}, { + trimmed: "ContactFilter", + name: "b2ContactFilter", + def: b2ContactFilter +}, { + trimmed: "ContactImpulse", + name: "b2ContactImpulse", + def: b2ContactImpulse +}, { + trimmed: "ContactListener", + name: "b2ContactListener", + def: b2ContactListener +}, { + trimmed: "QueryCallback", + name: "b2QueryCallback", + def: b2QueryCallback +}, { + trimmed: "RayCastCallback", + name: "b2RayCastCallback", + def: b2RayCastCallback +}, { + trimmed: "TimeStep", + name: "b2TimeStep", + def: b2TimeStep +}, { + trimmed: "Position", + name: "b2Position", + def: b2Position +}, { + trimmed: "Velocity", + name: "b2Velocity", + def: b2Velocity +}, { + trimmed: "SolverData", + name: "b2SolverData", + def: b2SolverData +}, { + trimmed: "World", + name: "b2World", + def: b2World +}, { + trimmed: "MixFriction", + name: "b2MixFriction", + def: b2MixFriction +}, { + trimmed: "MixRestitution", + name: "b2MixRestitution", + def: b2MixRestitution +}, { + trimmed: "ContactRegister", + name: "b2ContactRegister", + def: b2ContactRegister +}, { + trimmed: "ContactEdge", + name: "b2ContactEdge", + def: b2ContactEdge +}, { + trimmed: "Contact", + name: "b2Contact", + def: b2Contact +}, { + trimmed: "CircleContact", + name: "b2CircleContact", + def: b2CircleContact +}, { + trimmed: "PolygonContact", + name: "b2PolygonContact", + def: b2PolygonContact +}, { + trimmed: "ChainAndCircleContact", + name: "b2ChainAndCircleContact", + def: b2ChainAndCircleContact +}, { + trimmed: "ChainAndPolygonContact", + name: "b2ChainAndPolygonContact", + def: b2ChainAndPolygonContact +}, { + trimmed: "EdgeAndCircleContact", + name: "b2EdgeAndCircleContact", + def: b2EdgeAndCircleContact +}, { + trimmed: "EdgeAndPolygonContact", + name: "b2EdgeAndPolygonContact", + def: b2EdgeAndPolygonContact +}, { + trimmed: "PolygonAndCircleContact", + name: "b2PolygonAndCircleContact", + def: b2PolygonAndCircleContact +}, { + trimmed: "defaultFilter", + name: "b2_defaultFilter", + def: b2_defaultFilter +}, { + trimmed: "defaultListener", + name: "b2_defaultListener", + def: b2_defaultListener +}, { + trimmed: "ContactManager", + name: "b2ContactManager", + def: b2ContactManager +}, { + trimmed: "VelocityConstraintPoint", + name: "b2VelocityConstraintPoint", + def: b2VelocityConstraintPoint +}, { + trimmed: "ContactPositionConstraint", + name: "b2ContactPositionConstraint", + def: b2ContactPositionConstraint +}, { + trimmed: "ContactVelocityConstraint", + name: "b2ContactVelocityConstraint", + def: b2ContactVelocityConstraint +}, { + trimmed: "PositionSolverManifold", + name: "b2PositionSolverManifold", + def: b2PositionSolverManifold +}, { + trimmed: "ContactSolverDef", + name: "b2ContactSolverDef", + def: b2ContactSolverDef +}, { + trimmed: "ContactSolver", + name: "b2ContactSolver", + def: b2ContactSolver +}, { + trimmed: "Island", + name: "b2Island", + def: b2Island +}, { + trimmed: "Jacobian", + name: "b2Jacobian", + def: b2Jacobian +}, { + trimmed: "JointEdge", + name: "b2JointEdge", + def: b2JointEdge +}, { + trimmed: "JointDef", + name: "b2JointDef", + def: b2JointDef +}, { + trimmed: "Joint", + name: "b2Joint", + def: b2Joint +}, { + trimmed: "RevoluteJointDef", + name: "b2RevoluteJointDef", + def: b2RevoluteJointDef +}, { + trimmed: "RevoluteJoint", + name: "b2RevoluteJoint", + def: b2RevoluteJoint +}, { + trimmed: "MouseJointDef", + name: "b2MouseJointDef", + def: b2MouseJointDef +}, { + trimmed: "MouseJoint", + name: "b2MouseJoint", + def: b2MouseJoint +}, { + trimmed: "DistanceJointDef", + name: "b2DistanceJointDef", + def: b2DistanceJointDef +}, { + trimmed: "DistanceJoint", + name: "b2DistanceJoint", + def: b2DistanceJoint +}, { + trimmed: "PrismaticJointDef", + name: "b2PrismaticJointDef", + def: b2PrismaticJointDef +}, { + trimmed: "PrismaticJoint", + name: "b2PrismaticJoint", + def: b2PrismaticJoint +}, { + trimmed: "FrictionJointDef", + name: "b2FrictionJointDef", + def: b2FrictionJointDef +}, { + trimmed: "FrictionJoint", + name: "b2FrictionJoint", + def: b2FrictionJoint +}, { + trimmed: "WeldJointDef", + name: "b2WeldJointDef", + def: b2WeldJointDef +}, { + trimmed: "WeldJoint", + name: "b2WeldJoint", + def: b2WeldJoint +}, { + trimmed: "WheelJointDef", + name: "b2WheelJointDef", + def: b2WheelJointDef +}, { + trimmed: "WheelJoint", + name: "b2WheelJoint", + def: b2WheelJoint +}, { + trimmed: "GearJointDef", + name: "b2GearJointDef", + def: b2GearJointDef +}, { + trimmed: "GearJoint", + name: "b2GearJoint", + def: b2GearJoint +}, { + trimmed: "MotorJointDef", + name: "b2MotorJointDef", + def: b2MotorJointDef +}, { + trimmed: "MotorJoint", + name: "b2MotorJoint", + def: b2MotorJoint +}, { + trimmed: "PulleyJointDef", + name: "b2PulleyJointDef", + def: b2PulleyJointDef +}, { + trimmed: "PulleyJoint", + name: "b2PulleyJoint", + def: b2PulleyJoint +}, { + trimmed: "RopeJointDef", + name: "b2RopeJointDef", + def: b2RopeJointDef +}, { + trimmed: "RopeJoint", + name: "b2RopeJoint", + def: b2RopeJoint +}, { + trimmed: "RopeDef", + name: "b2RopeDef", + def: b2RopeDef +}, { + trimmed: "Rope", + name: "b2Rope", + def: b2Rope +}, { + trimmed: "maxManifoldPoints", + name: "b2_maxManifoldPoints", + def: b2_maxManifoldPoints +}, { + trimmed: "maxPolygonVertices", + name: "b2_maxPolygonVertices", + def: b2_maxPolygonVertices +}, { + trimmed: "aabbExtension", + name: "b2_aabbExtension", + def: b2_aabbExtension +}, { + trimmed: "aabbMultiplier", + name: "b2_aabbMultiplier", + def: b2_aabbMultiplier +}, { + trimmed: "linearSlop", + name: "b2_linearSlop", + def: b2_linearSlop +}, { + trimmed: "angularSlop", + name: "b2_angularSlop", + def: b2_angularSlop +}, { + trimmed: "polygonRadius", + name: "b2_polygonRadius", + def: b2_polygonRadius +}, { + trimmed: "maxSubSteps", + name: "b2_maxSubSteps", + def: b2_maxSubSteps +}, { + trimmed: "maxTOIContacts", + name: "b2_maxTOIContacts", + def: b2_maxTOIContacts +}, { + trimmed: "velocityThreshold", + name: "b2_velocityThreshold", + def: b2_velocityThreshold +}, { + trimmed: "maxLinearCorrection", + name: "b2_maxLinearCorrection", + def: b2_maxLinearCorrection +}, { + trimmed: "maxAngularCorrection", + name: "b2_maxAngularCorrection", + def: b2_maxAngularCorrection +}, { + trimmed: "maxTranslation", + name: "b2_maxTranslation", + def: b2_maxTranslation +}, { + trimmed: "maxTranslationSquared", + name: "b2_maxTranslationSquared", + def: b2_maxTranslationSquared +}, { + trimmed: "maxRotation", + name: "b2_maxRotation", + def: b2_maxRotation +}, { + trimmed: "maxRotationSquared", + name: "b2_maxRotationSquared", + def: b2_maxRotationSquared +}, { + trimmed: "baumgarte", + name: "b2_baumgarte", + def: b2_baumgarte +}, { + trimmed: "toiBaugarte", + name: "b2_toiBaugarte", + def: b2_toiBaugarte +}, { + trimmed: "timeToSleep", + name: "b2_timeToSleep", + def: b2_timeToSleep +}, { + trimmed: "linearSleepTolerance", + name: "b2_linearSleepTolerance", + def: b2_linearSleepTolerance +}, { + trimmed: "angularSleepTolerance", + name: "b2_angularSleepTolerance", + def: b2_angularSleepTolerance +}, { + trimmed: "epsilon", + name: "b2_epsilon", + def: b2_epsilon +}, { + trimmed: "JsonSerializer", + name: "b2JsonSerializer", + def: b2JsonSerializer +}, { + trimmed: "RUBELoader", + name: "b2RUBELoader", + def: b2RUBELoader +}, { + trimmed: "Profiler", + name: "b2Profiler", + def: b2Profiler +}]; + + +if (typeof (b2_compatibility) !== "undefined" && typeof (window) !== "undefined") { + for (var i = 0; i < mappings.length; ++i) { + window[mappings[i].name] = mappings[i].def + } +} else { + var b2 = {}; + for (var i = 0; i < mappings.length; ++i) { + b2[mappings[i].trimmed] = mappings[i].def + } + if (typeof (module) !== "undefined") { + module.exports = b2 + } else { + window.b2 = b2 + } +} \ No newline at end of file diff --git a/js/draw_p5js.js b/js/draw_p5js.js new file mode 100644 index 0000000000000000000000000000000000000000..aa25c107ecd4a1240c003897a33ab57668e4a61b --- /dev/null +++ b/js/draw_p5js.js @@ -0,0 +1,592 @@ +p5.disableFriendlyErrors = true; // disables FES + +// Colors to be used for the joints +let JOINTS_COLORS = { + "creeper": "#00B400", + "hip": "#FF7818", + "knee": "#F4BE18", + "neck": "#0000FF", + "shoulder": "#6CC9FF", + "elbow": "#FF00AA", + "hand": "#FF8CFF", + "grip": "#FF0000", +}; + +// Secondary off-screen canvas +let drawing_canvas; // Used to draw the terrain shapes +let trace_canvas; // Used to draw the erase and assets traces following the mouse +let forbidden_canvas; // Used to draw the forbidden red area on the terrain startpad +let tmp_canvas; + +/** + * Creates the different canvas and sets them up. Called automatically when the programs starts. + */ +function setup() { + let canvas_container = document.querySelector('#canvas_container'); + RENDERING_VIEWER_W = canvas_container.offsetWidth; + window.canvas = createCanvas(RENDERING_VIEWER_W, RENDERING_VIEWER_H); + INIT_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 1.05 * TERRAIN_STEP * SCALE); + THUMBNAIL_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 0.99 * TERRAIN_STEP * SCALE); + canvas.parent("canvas_container"); + canvas.style('display', 'block'); + canvas.style('margin-left', 'auto'); + canvas.style('margin-right', 'auto'); + + // Creates the off-screen canvas. Height is bigger than main canvas' so that one can scroll vertically when drawing. + drawing_canvas = createGraphics(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + trace_canvas = createGraphics(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + forbidden_canvas = createGraphics(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + tmp_canvas = createGraphics(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); + + // Prevents automatic calls the draw() function + noLoop(); +} + +/** + * Converts one rgb component to hexadecimal. + * @param c {number} + * @return {string} + */ +function componentToHex(c) { + let hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; +} + +/** + * Converts the rgb array to hexadecimal string. + * @param rgb {Array} + * @return {string} + */ +function rgbToHex(rgb) { + return "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); +} + +/** + * Converts hexadecimal string to rgb array + * @param hex + * @return {[number, number, number]} + */ +function hexToRgb(hex) { + let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + let rgb = [ + parseInt(result[1], 16), + parseInt(result[2], 16), + parseInt(result[3], 16) + ]; + return result ? rgb : null; +} + +/** + * Color agent's head depending on its 'dying' state. + * @param agent {Object} + * @param c1 {Array} + * @param c2 {Array} + * @return {Array} + */ +function color_agent_head(agent, c1, c2){ + let ratio = 0; + if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + ratio = agent.nb_steps_outside_water / agent.agent_body.nb_steps_can_survive_outside_water; + } + else { + ratio = agent.nb_steps_under_water / agent.agent_body.nb_steps_can_survive_under_water; + } + + let color1 = [ + c1[0] + ratio * (1.0 - c1[0]), + c1[1] + ratio * (0.0 - c1[1]), + c1[2] + ratio * (0.0 - c1[2]) + ] + let color2 = c2; + return [color1, color2]; +} + +/** + * Renders all the elements of the environment. + */ +function draw() { + if(window.game != null){ + let env = window.game.env; + push(); + + drawTerrain(env); + + // Renders the agents if not drawing mode + if(!window.is_drawing()){ + for(let agent of env.agents){ + + // Draws the agent morphology + drawAgent(agent, env.scale); + + // Draws the agent's lidars + if(window.draw_lidars){ + drawLidars(agent.lidars, env.scale); + } + + // Draws the agent's observation + if(window.draw_observation){ + drawObservation(agent, env.scale); + } + + // Draws the agent's rewards + if(window.draw_reward){ + drawReward(agent, env.scale); + } + + // Draws the agent's joints + if(window.draw_joints){ + + // Agent motors + let joints = [...agent.agent_body.motors]; + + // Adds neck joint and grip joints for climbers + if(agent.agent_body.body_type == BodyTypesEnum.CLIMBER){ + joints.push(agent.agent_body.neck_joint); + let grip_joints = [...agent.agent_body.sensors.map(s => s.GetUserData().has_joint ? s.GetUserData().joint : null)]; + joints = joints.concat(grip_joints); + } + drawJoints(joints, env.scale); + } + + // Draws the agent's name + if(window.draw_names){ + drawName(agent, env.scale); + } + } + } + + // Draws creepers joints + if(window.draw_joints) { + drawJoints(env.creepers_joints, env.scale); + } + + pop(); + } +} + +/** + * Draws the given sensors. + * @param sensors {Array} + * @param scale {number} - Scale of the environment + */ +function drawSensors(sensors, scale){ + for(let i = 0; i < sensors.length; i++){ + let radius = sensors[i].GetFixtureList().GetShape().m_radius + 0.01; + let sensor_world_center = sensors[i].GetPosition()//sensors[i].GetWorldCenter(); + noStroke(); + fill(255, 0, 0, 255); + //fill("#FFFF00"); + circle(sensor_world_center.x, VIEWPORT_H - sensor_world_center.y, radius); + } +} + +/** + * Draws the given joints. + * @param joints + * @param scale {number} - Scale of the environment + */ +function drawJoints(joints, scale){ + for(let i = 0; i < joints.length; i++){ + if(joints[i] != null){ + let posA = joints[i].m_bodyA.GetWorldPoint(joints[i].m_localAnchorA); + let posB = joints[i].m_bodyB.GetWorldPoint(joints[i].m_localAnchorB); + noStroke(); + let joint_type = joints[i].GetUserData().name; + fill(JOINTS_COLORS[joint_type]); + let radius = joint_type == "creeper" ? 5 : 7; + circle(posA.x, VIEWPORT_H - posA.y, radius/scale); + circle(posB.x, VIEWPORT_H - posB.y, radius/scale); + } + } +} + +/** + * Draws the name of the given agent. + * @param agent {Object} + * @param scale {number} - Scale of the environment + */ +function drawName(agent, scale){ + let pos = agent.agent_body.reference_head_object.GetPosition(); + fill(0); + noStroke() + textSize(25 / scale); + textAlign(CENTER); + let x_pos = pos.x; + let y_pos; + if(agent.morphology == "bipedal"){ + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT/3; + } + else if(agent.morphology == "spider"){ + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT / 2; + } + else if(agent.morphology == "chimpanzee"){ + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT/2; + } + else if(agent.morphology == "fish"){ + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT * 2; + } + let age = agent.age == "adult" ? "" : " (" + window.lang_dict[window.get_language()]['morphologies'][agent.age] + ")"; + text(agent.name + age, x_pos, RENDERING_VIEWER_H - y_pos); +} + +/** + * Draws all the body parts of the given agent. + * @param agent {Object} + * @param scale {number} - Scale of the environment + */ +function drawAgent(agent, scale){ + let stroke_coef = 1; + + if(agent.is_selected){ + stroke_coef = 2; + } + + let polys = agent.agent_body.get_elements_to_render(); + for(let poly of polys){ + let shape = poly.GetFixtureList().GetShape(); + + let vertices = []; + for(let i = 0; i < shape.m_count; i++){ + let world_pos = poly.GetWorldPoint(shape.m_vertices[i]); + vertices.push([world_pos.x, world_pos.y]); + } + + strokeWeight(stroke_coef * 2/scale); + stroke(poly.color2); + let color1 = poly.color1; + if(poly == agent.agent_body.reference_head_object){ + let rgb01 = hexToRgb(poly.color1).map(c => c / 255); + let rgb255 = color_agent_head(agent, rgb01, poly.color2)[0].map(c => Math.round(c * 255)); + color1 = rgbToHex(rgb255); + } + drawPolygon(vertices, color1); + } +} + +/** + * Draws the given lidars. + * @param lidars {Array} + * @param scale {number} - Scale of the environment + */ +function drawLidars(lidars, scale){ + for(let i = 0; i < lidars.length; i++){ + let lidar = lidars[i]; + + // Draws a red line representing the lidar + let vertices = [ + [lidar.p1.x, lidar.p1.y], + [lidar.p2.x, lidar.p2.y] + ]; + strokeWeight(1/scale); + drawLine(vertices, "#FF0000"); + + } +} + +/** + * Draws the different parts of the agent's observation. + * @param agent {Object} + * @param scale {number} - Scale of the environment + */ +function drawObservation(agent, scale){ + + // Draws a circle depending to the surface detected by the lidar and the fraction of the lidar + for(let i = 0; i < agent.lidars.length; i++) { + let lidar = agent.lidars[i]; + if(lidar.fraction < 1){ + if(lidar.is_water_detected){ + noStroke(); + fill(0, 50 + (1 - lidar.fraction) * 160, 150 + (1 - lidar.fraction) * 105); + circle(lidar.p2.x, VIEWPORT_H - lidar.p2.y, 5/scale); + } + else if(lidar.is_creeper_detected){ + noStroke(); + fill(0, 120 + (1 - lidar.fraction) * 135, 0); + circle(lidar.p2.x, VIEWPORT_H - lidar.p2.y, 5/scale); + } + else{ + noStroke(); + fill(0, 120 + (1 - lidar.fraction) * 135, 0); + circle(lidar.p2.x, VIEWPORT_H - lidar.p2.y, 5/scale); + } + } + } + + // Draws a line corresponding to the agent's head angle + let head = agent.agent_body.reference_head_object; + let pos = head.GetPosition(); + let angle = head.GetAngle(); + let length = 2 * agent.agent_body.AGENT_WIDTH; + if(agent.morphology == "spider"){ + length = agent.agent_body.AGENT_WIDTH / 2; + } + let vertices = [ + [pos.x - length * Math.cos(angle), pos.y - length * Math.sin(angle)], + [pos.x + length * Math.cos(angle), pos.y + length * Math.sin(angle)] + ]; + let color; + if(Math.abs(angle) > Math.PI / 10){ + color = "#FF0000"; + } + else if(Math.abs(angle) > Math.PI / 40){ + color = "#F4BE18"; + } + else{ + color = "#00B400"; + } + strokeWeight(2/scale); + drawLine(vertices, color); + + // Draws an arrow corresponding to the agent's linear velocity + let vel = head.GetLinearVelocity().Length(); + let x_pos; + let y_pos; + if(agent.morphology == "bipedal"){ + x_pos = pos.x - agent.agent_body.AGENT_WIDTH; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT / 4; + } + else if(agent.morphology == "spider"){ + x_pos = pos.x - agent.agent_body.AGENT_WIDTH / 2; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT / 4; + } + else if(agent.morphology == "chimpanzee"){ + x_pos = pos.x - agent.agent_body.AGENT_WIDTH; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT / 3; + } + else if(agent.morphology == "fish"){ + x_pos = pos.x - agent.agent_body.AGENT_WIDTH; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT * 1.5; + } + vertices = [ + [x_pos, y_pos], + [x_pos + vel / 2, y_pos] + ]; + strokeWeight(2/scale); + drawLine(vertices, "#0070FF"); + + vertices = [ + [x_pos + vel / 2 - 0.25, y_pos + Math.sin(Math.PI / 12)], + [x_pos + vel / 2, y_pos] + ] + drawLine(vertices, "#0070FF"); + + vertices = [ + [x_pos + vel / 2 - 0.25, y_pos - Math.sin(Math.PI / 12)], + [x_pos + vel / 2, y_pos] + ] + drawLine(vertices, "#0070FF"); +} + +/** + * Draws the agent's step and episodic reward. + * @param agent {Object} + * @param scale {number} - Scale of the environment + */ +function drawReward(agent, scale){ + // Text reward + if(window.game.rewards.length > 0){ + + let dict = window.lang_dict[window.get_language()]['advancedOptions']; + + let pos = agent.agent_body.reference_head_object.GetPosition(); + + let x_pos; + let y_pos; + if(agent.morphology == "bipedal"){ + x_pos = pos.x + agent.agent_body.AGENT_WIDTH * 3/2; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT; + } + else if(agent.morphology == "spider"){ + x_pos = pos.x + agent.agent_body.AGENT_WIDTH / 2; + y_pos = pos.y + agent.agent_body.AGENT_HEIGHT * 3/2; + } + else if(agent.morphology == "chimpanzee"){ + x_pos = pos.x + 8 * agent.agent_body.AGENT_WIDTH; + y_pos = pos.y - agent.agent_body.AGENT_HEIGHT; + } + else if(agent.morphology == "fish"){ + x_pos = pos.x + 9 * agent.agent_body.AGENT_WIDTH; + y_pos = pos.y; + } + + noStroke() + fill(0); + textSize(20/ scale); + textAlign(RIGHT); + text(dict['stepReward'] + " = ", x_pos, RENDERING_VIEWER_H - y_pos); + text(dict['totalReward'] + " = ", x_pos, RENDERING_VIEWER_H - (y_pos - 1)); + + let reward = window.game.rewards[window.game.rewards.length - 1][agent.id].toPrecision(3); + if(reward > 0.35){ + fill("#00B400"); + } + else if(reward > 0.15){ + fill("#F4BE18"); + } + else { + fill("#FF0000"); + } + + textAlign(LEFT); + text(reward, x_pos, RENDERING_VIEWER_H - y_pos); + + let ep_reward = agent.episodic_reward.toPrecision(3); + if(ep_reward > 230){ + fill("#00B400"); + } + else { + fill(0); + } + text(ep_reward, x_pos, RENDERING_VIEWER_H - (y_pos - 1)); + } +} + +/** + * Draws the sky and the clouds + * @param env + */ +function drawSkyClouds(env){ + push(); + + // Sky + background("#E6F0FF"); + + // Translation to scroll horizontally and vertically + translate(- env.scroll[0]/3, env.scroll[1]/3); + + // Rescaling + scale(env.scale); + scale(env.zoom * 3/4); + + // Translating so that the environment is always horizontally centered + translate(0, (1 - env.scale * env.zoom) * VIEWPORT_H/(env.scale * env.zoom)); + translate(0, (env.zoom - 1) * (env.ceiling_offset)/env.zoom * 1/3); + + // Clouds + for(let cloud of env.cloud_polys){ + noStroke(); + drawPolygon(cloud.poly, "#FFFFFF"); + } + + pop(); +} + +/** + * Draws all the bodies composing the terrain of the given environment. + * @param env {Object} + */ +function drawTerrain(env){ + // Updates scroll to stay centered on the agent position + if(window.agent_followed != null){ + env.set_scroll(window.agent_followed, null, null); + } + + // Sky & clouds + drawSkyClouds(env); + + // Translation to scroll horizontally and vertically + translate(- env.scroll[0], env.scroll[1]); + + // Rescaling + scale(env.scale); + scale(env.zoom); + + // Translating so that the environment is always horizontally centered + translate(0, (1 - env.scale * env.zoom) * VIEWPORT_H/(env.scale * env.zoom)); + translate(0, (env.zoom - 1) * (env.ceiling_offset)/env.zoom * 1/3); + + // Water + let vertices = [ + [-RENDERING_VIEWER_W, -RENDERING_VIEWER_H], + [-RENDERING_VIEWER_W, env.water_y], + [2 * RENDERING_VIEWER_W, env.water_y], + [2 * RENDERING_VIEWER_W, -RENDERING_VIEWER_H] + ]; + noStroke(); + drawPolygon(vertices, "#77ACE5"); + + // Draws all background elements + for(let i = 0; i < env.background_polys.length; i++) { + let poly = env.background_polys[i]; + noStroke(); + drawPolygon(poly.vertices, poly.color); + } + + // Draws all terrain elements + for(let i = 0; i < env.terrain_bodies.length; i++) { + let poly = env.terrain_bodies[i]; + let shape = poly.body.GetFixtureList().GetShape(); + let vertices = []; + + if(poly.type == "creeper"){ + for(let i = 0; i < shape.m_count; i++){ + let world_pos = poly.body.GetWorldPoint(shape.m_vertices[i]); + vertices.push([world_pos.x, world_pos.y]); + } + noStroke(); + drawPolygon(vertices, poly.color1); + } + else{ + let v1 = poly.body.GetWorldPoint(shape.m_vertex1); + let v2 = poly.body.GetWorldPoint(shape.m_vertex2); + vertices = [[v1.x, v1.y], [v2.x, v2.y]]; + strokeWeight(1/env.scale); + drawLine(vertices, poly.color); + } + } + + // Draws a flag on startpad + let flag_y1 = TERRAIN_HEIGHT; + let flag_y2 = flag_y1 + 90 / env.scale; + let flag_x = TERRAIN_STEP * 3; + vertices = [ + [flag_x, flag_y1], + [flag_x, flag_y2] + ] + drawLine(vertices, "#000000"); + vertices = [ + [flag_x, flag_y2], + [flag_x, flag_y2 - 20 / env.scale], + [flag_x + 40 / env.scale, flag_y2 - 10 / env.scale] + ] + drawPolygon(vertices, "#E63300"); + + // Draws all assets + for(let asset of env.assets_bodies){ + let shape = asset.body.GetFixtureList().GetShape(); + + let stroke_coef = asset.is_selected ? 2 : 1; + + if(asset.type == "circle"){ + let center = asset.body.GetWorldCenter(); + strokeWeight(stroke_coef * 2/env.scale); + stroke(asset.color2); + fill(asset.color1); + circle(center.x, RENDERING_VIEWER_H - center.y, shape.m_radius * 2); + } + } +} + +/** + * Draws a polygon in the canvas with the given vertices. + * @param vertices {Array} + * @param color {string} + */ +function drawPolygon(vertices, color){ + fill(color); + beginShape(); + for(let v of vertices){ + vertex(v[0], VIEWPORT_H - v[1]); + } + endShape(CLOSE); +} + +/** + * Draws a line in the canvas between the two vertices. + * @param vertices {Array} + * @param color {string} + */ +function drawLine(vertices, color){ + stroke(color); + line(vertices[0][0], VIEWPORT_H - vertices[0][1], vertices[1][0], VIEWPORT_H - vertices[1][1]); +} \ No newline at end of file diff --git a/js/envs/multi_agents_continuous_parkour.js b/js/envs/multi_agents_continuous_parkour.js new file mode 100644 index 0000000000000000000000000000000000000000..1bbb4e7dbb8e7ca9c6912641570589d0e4cc0c6a --- /dev/null +++ b/js/envs/multi_agents_continuous_parkour.js @@ -0,0 +1,1264 @@ +//region Constants + +const FPS = 50; +const SCALE = 30; // affects how fast-paced the game is, forces should be adjusted as well +const VIEWPORT_W = 600; +const VIEWPORT_H = 400; + +let RENDERING_VIEWER_W = VIEWPORT_W; +let RENDERING_VIEWER_H = VIEWPORT_H + +const NB_LIDAR = 10; +const LIDAR_RANGE = 160/SCALE; + +const TERRAIN_STEP = 14/SCALE; +const TERRAIN_LENGTH = 200; // in steps +const TERRAIN_HEIGHT = VIEWPORT_H/SCALE/4; +const TERRAIN_END = 5; +const INITIAL_TERRAIN_STARTPAD = 20; // in steps +const FRICTION = 2.5; +const WATER_DENSITY = 1.0; +const CREEPER_UNIT = 1; + +const SCROLL_X_MAX = 500; +const SCROLL_Y_MAX = 300; +const INIT_SCROLL_X = -0.035 * RENDERING_VIEWER_W; +const THUMBNAIL_SCROLL_X = 0; +let THUMBNAIL_ZOOM = 0.27; +let INIT_ZOOM = 0.27; + +//endregion + +/** + * @classdesc This environment can host multiple agents and its terrain can be generated either with lists of points for ground and ceiling or with a CPPN. + */ +class MultiAgentsContinuousParkour { + + /** + * @constructor + * @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents + * @param input_CPPN_dim {number} - Dimension of the array that encodes the CPPN + * @param [terrain_cppn_scale=10] {number} - Smoothing + * @param [ceiling_offset=200] {number} + * @param [ceiling_clip_offset=0] {number} + * @param [water_clip=20] {number} + * @param [movable_creepers=false] {boolean} + * @param ground {Array} - List of points {x, y} composing the ground + * @param ceiling {Array} - List of points {x, y} composing the ceiling + * @param align_terrain {Object} + */ + constructor(agents, input_CPPN_dim=3, terrain_cppn_scale=10, + ceiling_offset=200, ceiling_clip_offset=0, water_clip=20, + movable_creepers=false, ground, ceiling, align_terrain){ + + // Initializes class attributes + this.scale = SCALE; + this.zoom = INIT_ZOOM; + this.movable_creepers = movable_creepers; + this.terrain_bodies = []; + this.background_polys = []; + this.creepers_joints = []; + this.ground = ground; + this.ceiling = ceiling; + this.align_terrain = align_terrain; + + // Initializes Box2D + this.contact_listener = new ContactDetector(this); + let gravity = new b2.Vec2(0, -10); + this.world = new b2.World(gravity); + this.world.SetContactListener(this.contact_listener); + + // Creates the agents + this.agents = []; + console.assert(agents.morphologies.length == agents.policies.length && agents.morphologies.length == agents.positions.length); + for(let i = 0; i < agents.morphologies.length; i++){ + this.create_agent(agents.morphologies[i], agents.policies[i], agents.positions[i]); + //this.create_agent("spider", {name: "random", path: null}, null); + } + + // Initializes dynamics + this.water_dynamics = new WaterDynamics(this.world.m_gravity); + this.climbing_dynamics = new ClimbingDynamics(); + + // Creates the Box2D fixtures + this.create_terrain_fixtures(); + + // Initializes the CPPN and scales the terrain + this.terrain_CPPN = new CPPN(TERRAIN_LENGTH, input_CPPN_dim); + this.set_terrain_cppn_scale(terrain_cppn_scale, ceiling_offset, ceiling_clip_offset); + } + + /** + * Creates an agent with the given parameters. + * @param morphology {string} - Name of the morphology + * @param policy {{name: string, age: string, path: string}} - Name and path of the policy model + * @param init_pos {{x: number, y: number}} - Initial position of the agent + */ + create_agent(morphology, policy, init_pos){ + + let agent = { + id: this.agents.length, + name: policy.name, + age: policy.age, + is_selected: false, + morphology: morphology, + policy: policy, + init_pos: init_pos, + prev_shaping: null, + episodic_reward: 0, + }; + + // Initializes the agent's body and lidars according to the morphology + if(morphology == "bipedal") { + agent.agent_body = new ClassicBipedalBody(SCALE); + agent.lidars_config = this.set_lidars_type("down"); + } + else if(morphology == "chimpanzee") { + agent.agent_body = new ClimbingProfileChimpanzee(SCALE); + agent.lidars_config = this.set_lidars_type("up"); + } + else if(morphology == "fish"){ + agent.agent_body = new FishBody(SCALE, 80, WATER_DENSITY, 600); + agent.lidars_config = this.set_lidars_type("full"); + } + else if(morphology == "spider"){ + agent.agent_body = new SpiderBody(SCALE); + agent.lidars_config = this.set_lidars_type("down"); + } + else { + agent.agent_body = new ClassicBipedalBody(SCALE); + agent.lidars_config = this.set_lidars_type("down"); + } + + // Adds the new agent to the list of agents + this.agents.push(agent); + } + + /** + * Seeds the random generator according to the terrain parameters. + */ + seed(){ + // Creates a string with all the terrain parameters + let seed = ""; + for(let dim of this.CPPN_input_vector){ + seed += dim; + } + seed += this.water_level; + seed += this.TERRAIN_CPPN_SCALE; + seed += this.creepers_width; + seed += this.creepers_height; + seed += this.creepers_spacing; + seed += this.movable_creepers;; + + Math.seedrandom(seed); + } + + /** + * Returns a lidars configuration according to the given type. + * @param lidars_type {string} - 'down', 'up', or 'full' + * @returns {{lidar_angle: number, lidar_y_offset: number}} + */ + set_lidars_type(lidars_type){ + // Use 'down' for walkers, 'up' for climbers and 'full' for swimmers. + let lidar_config = {}; + if(lidars_type == "down") { + lidar_config.lidar_angle = 1.5; + lidar_config.lidar_y_offset = 0; + } + else if(lidars_type == "up") { + lidar_config.lidar_angle = 2.3; + lidar_config.lidar_y_offset = 1.5; + } + else if(lidars_type == "full") { + lidar_config.lidar_angle = Math.PI; + lidar_config.lidar_y_offset = 0; + } + return lidar_config; + } + + /** + * Scales the terrain according to the smoothing. + * @param terrain_cppn_scale {number} - Smoothing + * @param ceiling_offset {number} + * @param ceiling_clip_offset {number} + */ + set_terrain_cppn_scale(terrain_cppn_scale, ceiling_offset, ceiling_clip_offset){ + console.assert(terrain_cppn_scale > 1); + this.TERRAIN_CPPN_SCALE = terrain_cppn_scale; + this.CEILING_LIMIT = 1000 / this.TERRAIN_CPPN_SCALE; + this.GROUND_LIMIT = -1000 / INITIAL_TERRAIN_STARTPAD; + this.ceiling_offset = ceiling_offset / this.TERRAIN_CPPN_SCALE; + this.ceiling_clip_offset = ceiling_clip_offset / this.TERRAIN_CPPN_SCALE; + } + + /** + * Sets the parameters for terrain generation. + * Must be called before `reset()`. + * @param input_vector {Array} - 3-dimensional array that encodes the CPPN + * @param water_level {number} + * @param creepers_width {number} + * @param creepers_height {number} + * @param creepers_spacing {number} + * @param terrain_cppn_scale {number} - Smoothing + * @param movable_creepers {boolean} + */ + set_environment(input_vector, water_level, creepers_width=null, + creepers_height=null, creepers_spacing=0.1, terrain_cppn_scale=10, movable_creepers){ + + this.CPPN_input_vector = input_vector; + this.water_level = water_level > 0 ? water_level : - 0.01; + this.creepers_width = creepers_width; + this.creepers_height = creepers_height; + this.creepers_spacing = Math.max(0.01, creepers_spacing); + this.movable_creepers = movable_creepers; + this.set_terrain_cppn_scale(terrain_cppn_scale, + this.ceiling_offset * this.TERRAIN_CPPN_SCALE, + this.ceiling_clip_offset * this.TERRAIN_CPPN_SCALE); + this.seed(); + } + + /** + * Destroys all the bodies composing the terrain and the agents + */ + _destroy(){ + this.world.SetContactListener(null); + for(let t of this.terrain_bodies){ + this.world.DestroyBody(t.body); + } + this.terrain_bodies = []; + this.creepers_joints = []; + for(let agent of this.agents){ + agent.agent_body.destroy(this.world); + } + } + + /** + * Resets the environment. + * @returns {*[]} - Array that contains the observation state and reward of each agent. + */ + reset(){ + this._destroy(); + this.contact_listener = new ContactDetector(this); + this.world.SetContactListener(this.contact_listener); + this.scroll = [0, 0]; + this.water_y = this.GROUND_LIMIT; + this.assets_bodies = []; + + for(let agent of this.agents){ + agent.nb_steps_outside_water = 0; + agent.nb_steps_under_water = 0; + agent.critical_contact = false; + } + + // Generates the terrain and the agents + this.generate_game(); + + // Initializes all the agents + for(let agent of this.agents) { + this.init_agent(agent); + } + + // Runs a simulation step and returns the results + return this.step(); + } + + /** + * Initializes the given agent. + * @param agent {Object} + */ + init_agent(agent){ + // Creates the lidars of the agent + agent.lidars = []; + for(let i = 0; i < NB_LIDAR; i++){ + agent.lidars.push(new LidarCallback(agent.agent_body.reference_head_object.GetFixtureList().GetFilterData().maskBits)); + } + + // Initializes the agent with motionless actions + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); + + agent.nb_steps_outside_water = 0; + agent.nb_steps_under_water = 0; + agent.episodic_reward = 0; + } + + /** + * Initializes the position of the given climber agent so that it hangs from the ceiling. + * @param agent {Object} + */ + init_climber_pos(agent){ + let y_diff = 0; + for(let i = 0; i < agent.agent_body.sensors.length; i++){ + + // Tells this sensor to grasp + agent.actions[agent.actions.length - i - 1] = 1; + + let sensor = agent.agent_body.sensors[agent.agent_body.sensors.length - i - 1]; + let sensor_position = sensor.GetPosition(); + + // Finds the best y-coordinate of the ceiling according to the x-coordinate of the sensor + let ceiling_y = find_best_y(sensor_position.x, this.terrain_ceiling); + + // Computes the vertical offset + if(y_diff == 0){ + y_diff = ceiling_y - sensor_position.y; + } + + // Sets the position of the sensor + sensor.SetTransform(new b2.Vec2(sensor_position.x, ceiling_y), + sensor.GetAngle()); + } + + // Shifts the position of each body part by the vertical offset + for(let body_part of agent.agent_body.body_parts){ + let body_part_pos = body_part.GetPosition(); + body_part.SetTransform(new b2Vec2(body_part_pos.x, body_part_pos.y + y_diff), + body_part.GetAngle()); + } + } + + /** + * Runs one step and updates the observation of the agents + * @returns {Array} - List of return of each agent : [state, reward, done, {success: boolean}] + */ + step(){ + // Checks if agents are dead according to their morphology + for(let agent of this.agents){ + if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + if(agent.nb_steps_outside_water > agent.agent_body.nb_steps_can_survive_outside_water){ + agent.is_dead = true; + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); + } + else{ + agent.is_dead = false; + } + } + else{ + if(agent.nb_steps_under_water > agent.agent_body.nb_steps_can_survive_under_water){ + agent.is_dead = true; + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); + } + else{ + agent.is_dead = false; + } + } + + // Makes the agent moves according to its actions + agent.agent_body.activate_motors(agent.actions); + + // Prepares climbing dynamics according to the grasping actions (i.e. readies sensor to grasp or release sensor grip by destroying joint) + if(agent.agent_body.body_type == BodyTypesEnum.CLIMBER){ + this.climbing_dynamics.before_step_climbing_dynamics(agent.actions, agent.agent_body, this.world); + } + } + + // Updates Box2D world + //this.world.Step(1.0 / FPS, 45, 15); + this.world.Step(1.0 / FPS, 3 * 30, 1 * 30); + + for(let agent of this.agents) { + // Creates joints between sensors ready to grasp if collision with graspable area was detected + if(agent.agent_body.body_type == BodyTypesEnum.CLIMBER){ + this.climbing_dynamics.after_step_climbing_dynamics(this.world.m_contactManager.m_contactListener.climbing_contact_detector, this.world); + } + } + + // Filters null fixture pairs to avoid errors with water collisions + this.world.m_contactManager.m_contactListener.water_contact_detector.fixture_pairs = this.world.m_contactManager.m_contactListener.water_contact_detector.fixture_pairs.filter(function(fp, index, array){ + return fp[0].GetShape() != null && fp[1].GetShape() != null; + }); + // Calculates water physics + this.water_dynamics.calculate_forces(this.world.m_contactManager.m_contactListener.water_contact_detector.fixture_pairs); + + let ret = []; + + // Observation state for each agent + for(let agent of this.agents) { + let head = agent.agent_body.reference_head_object; + let pos = head.GetPosition(); + let vel = head.GetLinearVelocity(); + + this.update_lidars(agent); + + let is_under_water = pos.y <= this.water_y; + if(!agent.is_dead){ + if(is_under_water){ + agent.nb_steps_under_water += 1; + agent.nb_steps_outside_water = 0; + } + else{ + agent.nb_steps_under_water = 0; + agent.nb_steps_outside_water += 1; + } + } + + let state = [ + head.GetAngle(), // Normal angles up to 0.5 here, but sure more is possible. + 2.0 * head.GetAngularVelocity() / FPS, + 0.3 * vel.x * (VIEWPORT_W / SCALE) / FPS, // Normalized to get [-1, 1] range + 0.3 * vel.y * (VIEWPORT_H / SCALE) / FPS, + is_under_water ? 1.0 : 0.0, + agent.is_dead ? 1.0 : 0.0 + ]; + + // Adds motor-related state + state = state.concat(agent.agent_body.get_motors_state()); + + // Adds sensor-related state for climbers + if(agent.agent_body.body_type == BodyTypesEnum.CLIMBER){ + state = state.concat(agent.agent_body.get_sensors_state()); + } + + // Adds lidar-related state with distance and surface detected + let nb_of_water_detected = 0; + let surface_detected = []; + for(let lidar of agent.lidars){ + state.push(lidar.fraction); + if(lidar.is_water_detected){ + surface_detected.push(-1); + nb_of_water_detected += 1; + } + else if(lidar.is_creeper_detected){ + surface_detected.push(1) + } + else{ + surface_detected.push(0); + } + } + state = state.concat(surface_detected) + + let shaping = 130 * pos.x / SCALE; // moving forward is a way to receive reward (normalized to get 300 on completion) + if(agent.agent_body.remove_reward_on_head_angle){ + shaping -= 5.0 * Math.abs(state[0]); // keep head straight, other than that and falling, any behavior is unpunished + } + + let reward = 0; + if(agent.prev_shaping != null){ + reward = shaping - agent.prev_shaping; + } + agent.prev_shaping = shaping; + + for(let a of agent.actions){ + reward -= agent.agent_body.TORQUE_PENALTY * 80 * Math.max(0, Math.min(Math.abs(a), 1)); + // normalized to about -50.0 using heuristic, more optimal agent should spend less + } + + // Ending conditions + let done = false; + if(agent.critical_contact || pos.x < 0){ + reward -= 100; + done = true; + } + if(pos.x > (TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD - TERRAIN_END) * TERRAIN_STEP){ + done = true; + } + agent.episodic_reward += reward; + + ret.push([state, reward, done, {"success": agent.episodic_reward > 230}]); + } + + return ret; + } + + /** + * Updates the lidars of the given agent by casting a ray for each lidar. + * @param agent {Object} + */ + update_lidars(agent){ + let pos = agent.agent_body.reference_head_object.GetPosition(); + for(let i = 0; i < NB_LIDAR; i++){ + agent.lidars[i].fraction = 1.0; + agent.lidars[i].p1 = pos; + agent.lidars[i].p2 = new b2.Vec2( + pos.x + Math.sin(agent.lidars_config.lidar_angle * i / NB_LIDAR + agent.lidars_config.lidar_y_offset) * LIDAR_RANGE, + pos.y - Math.cos(agent.lidars_config.lidar_angle * i / NB_LIDAR + agent.lidars_config.lidar_y_offset) * LIDAR_RANGE + ); + this.world.RayCast(agent.lidars[i], agent.lidars[i].p1, agent.lidars[i].p2); + } + } + + /** + * Closes the environment. + */ + close(){ + this.world.SetContactListener(null); + this.contact_listener.Reset(); + this._destroy(); + } + + // region Rendering + // ------------------------------------------ RENDERING ------------------------------------------ + + /** + * Renders the environment. + */ + render() { + // Calls p5.js draw function once + redraw(); + } + + /** + * Sets the rendering viewer variables. + * @param width {number} + * @param height {number} + * @param keep_ratio {boolean} + */ + _SET_RENDERING_VIEWPORT_SIZE(width, height=null, keep_ratio=true){ + RENDERING_VIEWER_W = width; + if(keep_ratio || height == null){ + RENDERING_VIEWER_H = Math.floor(RENDERING_VIEWER_W / (2 * VIEWPORT_W / VIEWPORT_H)); + } + else{ + RENDERING_VIEWER_H = height; + } + } + //endregion + + //region Fixtures Initialization + // ------------------------------------------ FIXTURES INITIALIZATION ------------------------------------------ + + /** + * Creates all the Box2D fixtures to be used to generate the terrain. + */ + create_terrain_fixtures(){ + + // Polygon fixture + this.fd_polygon = new b2.FixtureDef(); + this.fd_polygon.shape = new b2.PolygonShape(); + let vertices = [ + new b2.Vec2(0, 0), + new b2.Vec2(1, 0), + new b2.Vec2(1, -1), + new b2.Vec2(0, -1)]; + this.fd_polygon.shape.Set(vertices, 4); + this.fd_polygon.friction = FRICTION; + this.fd_polygon.filter.categoryBits = 0x1; + this.fd_polygon.filter.maskBits = 0xFFFF; + + // Edge fixture + this.fd_edge = new b2.FixtureDef(); + this.fd_edge.shape = new b2.EdgeShape(); + this.fd_edge.shape.Set(new b2.Vec2(0, 0), new b2.Vec2(1, 1)); + this.fd_edge.friction = FRICTION; + this.fd_edge.filter.categoryBits = 0x1; + this.fd_edge.filter.maskBits = 0xFFFF; + + // Water fixture + this.fd_water = new b2.FixtureDef(); + this.fd_water.shape = new b2.PolygonShape(); + vertices = [ + new b2.Vec2(0, 0), + new b2.Vec2(1, 0), + new b2.Vec2(1, -1), + new b2.Vec2(0, -1)]; + this.fd_water.shape.Set(vertices, 4); + this.fd_water.density = WATER_DENSITY; + this.fd_water.isSensor = true; + + // Creeper fixture + this.fd_creeper = new b2.FixtureDef(); + this.fd_creeper.shape = new b2.PolygonShape(); + vertices = [ + new b2.Vec2(0, 0), + new b2.Vec2(1, 0), + new b2.Vec2(1, -1), + new b2.Vec2(0, -1)]; + this.fd_creeper.shape.Set(vertices, 4); + this.fd_creeper.density = 5.0; + this.fd_creeper.isSensor = true; + + // Circle fixture + this.fd_circle = new b2.FixtureDef(); + this.fd_circle.shape = new b2.CircleShape(); + this.fd_circle.density = 5.0; + this.fd_circle.friction = FRICTION; + this.fd_circle.filter.categoryBits = 0x1; + this.fd_circle.filter.maskBits = 0xFFFF; + + } + //endregion + + // region Game Generation + // ------------------------------------------ GAME GENERATION ------------------------------------------ + + /** + * Generates the different elements of the environment. + */ + generate_game(){ + this._generate_terrain(); + this._generate_clouds(); + + for(let agent of this.agents){ + this._generate_agent(agent); + } + } + + /** + * Generates all the Box2D bodies composing the terrain. + */ + _generate_terrain(){ + + // Arrays to contain the actual points of ground and ceiling + this.terrain_ground = []; + this.terrain_ceiling = []; + + // Smooths ground and ceiling by removing points that are too close in order to reduce the number of bodies created + let ground = smoothTerrainFiler(this.ground, TERRAIN_STEP); + let ceiling = smoothTerrainFiler(this.ceiling, TERRAIN_STEP); + + // Creates startpad + for(let i = 0; i < INITIAL_TERRAIN_STARTPAD; i++){ + this.terrain_ground.push({x: i * TERRAIN_STEP, y: TERRAIN_HEIGHT}); + this.terrain_ceiling.push({x: i * TERRAIN_STEP, y: TERRAIN_HEIGHT + this.ceiling_offset}); + } + + /* DRAWING GENERATION: generates the terrain from the ground and ceiling arrays of points */ + if(window.is_drawing() || ground.length > 0 || ceiling.length > 0){ + + // Creates ground terrain + if(ground.length > 0){ + + // Handles smoothing and alignment of the ground with the startpad + let ground_y_offset = 0; + if(this.align_terrain.align && this.align_terrain.smoothing != null){ + + // Applies the smoothing as the ratio: current smoothing / previous smoothing + ground = [...ground.map(p => { + return {x: p.x, y: p.y / (this.TERRAIN_CPPN_SCALE / this.align_terrain.smoothing)}; + })]; + + // Aligns the ground with the startpad + if(this.align_terrain.ground_offset == null){ + ground_y_offset = TERRAIN_HEIGHT - ground[0].y; + } + // Keeps the same ground alignment (adjusted to fit the smoothing) + else{ + ground_y_offset = this.align_terrain.ground_offset - ground[0].y; + } + + } + + for(let p of ground){ + this.terrain_ground.push({x: p.x, y: p.y + ground_y_offset}); + } + } + + // Creates ceiling terrain + if(ceiling.length > 0) { + + // Handles smoothing and alignment of the ceiling with the startpad + let ceiling_y_offset = 0 + if(this.align_terrain.align && this.align_terrain.smoothing != null){ + + // Applies the smoothing as the ratio: current smoothing / previous smoothing + ceiling = [...ceiling.map(p => { + return {x: p.x, y: p.y / (this.TERRAIN_CPPN_SCALE / this.align_terrain.smoothing)}; + })]; + + // Aligns the ceiling with the startpad + if(this.align_terrain.ceiling_offset == null){ + ceiling_y_offset = TERRAIN_HEIGHT + this.ceiling_offset - ceiling[0].y; + } + // Keeps the same ceiling alignment (adjusted to fit the smoothing) + else{ + ceiling_y_offset = (this.ceiling_offset - ceiling[0].y) - this.align_terrain.ceiling_offset; + } + } + + for(let p of ceiling){ + this.terrain_ceiling.push({x: p.x, y: p.y + ceiling_y_offset}); + } + } + } + /* CPPN GENERATION: generates the terrain from the output of the CPPN model encoded with the input vector */ + else{ + let cppn_y = this.terrain_CPPN.generate(this.CPPN_input_vector).arraySync(); + cppn_y = cppn_y.map(e => [e[0] / this.TERRAIN_CPPN_SCALE, e[1] / this.TERRAIN_CPPN_SCALE]); + + // Gets y values for the ground and aligns them with the startpad + let ground_offset = TERRAIN_HEIGHT - cppn_y[0][0]; + let cppn_ground_y = cppn_y.map(e => e[0] + ground_offset); + + // Gets y values for the ceiling and aligns them with the startpad + let ceiling_offset = TERRAIN_HEIGHT + this.ceiling_offset - cppn_y[0][1]; + let cppn_ceiling_y = cppn_y.map(e => e[1] + ceiling_offset); + + // Pushes the terrain values in the lists + for(let i = 0; i < TERRAIN_LENGTH; i++){ + this.terrain_ground.push({x: (INITIAL_TERRAIN_STARTPAD + i) * TERRAIN_STEP, y: cppn_ground_y[i]}); + + // Clips ceiling so that it does not overlaps the ground + let ceiling_val = cppn_ground_y[i] + this.ceiling_clip_offset; + if(cppn_ceiling_y[i] >= ceiling_val){ + ceiling_val = cppn_ceiling_y[i]; + } + this.terrain_ceiling.push({x: (INITIAL_TERRAIN_STARTPAD + i) * TERRAIN_STEP, y: ceiling_val}); + } + } + + // Stores the terrain shapes (without the startpad) in global variables + window.ground = [...this.terrain_ground]; + window.ground.splice(0, INITIAL_TERRAIN_STARTPAD); + window.ceiling = [...this.terrain_ceiling]; + window.ceiling.splice(0, INITIAL_TERRAIN_STARTPAD); + + /* BOX2D TERRAIN CREATION */ + this.terrain_bodies = []; + this.background_polys = []; + let poly; + let poly_data; + + // Water + this.min_ground_y = Math.min(...this.terrain_ground.map(p => p.y)); + this.air_max_distance = Math.max(...this.terrain_ceiling.map(p => p.y)) - this.min_ground_y; + this.water_y = this.min_ground_y + this.water_level * this.air_max_distance; + + let water_poly = [ + [this.terrain_ground[0].x - 1000, this.GROUND_LIMIT], + [this.terrain_ground[0].x - 1000, this.water_y], + [this.terrain_ground[this.terrain_ground.length - 1].x + 1000, this.water_y], + [this.terrain_ground[this.terrain_ground.length - 1].x + 1000, this.GROUND_LIMIT] + ]; + + this.fd_water.shape.Set([new b2.Vec2(water_poly[0][0], water_poly[0][1]), + new b2.Vec2(water_poly[1][0], water_poly[1][1]), + new b2.Vec2(water_poly[2][0], water_poly[2][1]), + new b2.Vec2(water_poly[3][0], water_poly[3][1])], + 4); + let body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_staticBody; + let t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_water); + t.SetUserData(new CustomUserData("water", CustomUserDataObjectTypes.WATER)); + let color = "#77ACE5"; // [0.465, 0.676, 0.898]; + this.water_poly = { + type : "water", + color: color, + vertices: water_poly, + body : t + }; + + // Ground + for(let i = 0; i < this.terrain_ground.length - 1; i++){ + poly = [ + [this.terrain_ground[i].x, this.terrain_ground[i].y], + [this.terrain_ground[i + 1].x, this.terrain_ground[i + 1].y] + ]; + this.fd_edge.shape.Set(new b2.Vec2(poly[0][0], poly[0][1]), + new b2.Vec2(poly[1][0], poly[1][1])); + let body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_staticBody; + let t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_edge); + t.SetUserData(new CustomUserData("grass", CustomUserDataObjectTypes.TERRAIN)); + let color = i % 2 == 0 ? "#4dff4d" : "#4dcc4d"; // [0.3, 1.0, 0.3] : [0.3, 0.8, 0.3] + poly_data = { + type : "ground", + color : color, + body : t, + } + this.terrain_bodies.push(poly_data); + + // Visual poly to fill the ground + if(i <= this.terrain_ground.length / 2){ + poly.push([poly[1][0] + 10 * TERRAIN_STEP, 2 * this.GROUND_LIMIT]); + poly.push([poly[0][0], 2 * this.GROUND_LIMIT]); + } + else{ + poly.push([poly[1][0], 2 * this.GROUND_LIMIT]); + poly.push([poly[0][0] - 10 * TERRAIN_STEP, 2 * this.GROUND_LIMIT]); + } + + color = "#66994D"; //[0.4, 0.6, 0.3]; + poly_data = { + type : "ground", + color : color, + vertices : poly, + } + this.background_polys.push(poly_data); + } + + // Ceiling + for(let i = 0; i < this.terrain_ceiling.length - 1; i++){ + poly = [ + [this.terrain_ceiling[i].x, this.terrain_ceiling[i].y], + [this.terrain_ceiling[i + 1].x, this.terrain_ceiling[i + 1].y] + ]; + this.fd_edge.shape.Set(new b2.Vec2(poly[0][0], poly[0][1]), + new b2.Vec2(poly[1][0], poly[1][1])); + body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_staticBody; + t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_edge); + t.SetUserData(new CustomUserData("rock", CustomUserDataObjectTypes.GRIP_TERRAIN)); // TODO: CustomUserData + color = "#004040"; // [0, 0.25, 0.25]; + poly_data = { + type : "ceiling", + color : color, + body : t, + } + this.terrain_bodies.push(poly_data); + + // Visual poly to fill the ceiling + if(i <= this.terrain_ceiling.length / 2){ + poly.push([poly[1][0] + 10 * TERRAIN_STEP, 2 * this.CEILING_LIMIT]); + poly.push([poly[0][0], 2 * this.CEILING_LIMIT]); + } + else{ + poly.push([poly[1][0], 2 * this.CEILING_LIMIT]); + poly.push([poly[0][0] - 10 * TERRAIN_STEP, 2 * this.CEILING_LIMIT]); + } + color = "#808080"; // [0.5, 0.5, 0.5]; + poly_data = { + type : "ceiling", + color : color, + vertices : poly, + } + this.background_polys.push(poly_data); + } + + // Creepers + if(this.creepers_width != null && this.creepers_height != null){ + let creeper_width = Math.max(0.2, this.creepers_width); + let nb_creepers = Math.floor(this.terrain_ceiling[this.terrain_ceiling.length - 1].x / (this.creepers_spacing + creeper_width)); + + for(let i = 1; i < nb_creepers; i++){ + let creeper_height = Math.max(0.2, Math.random() * (0.1 - (- 0.1)) + this.creepers_height - 0.1); + let creeper_x_init_pos = i * (this.creepers_spacing + creeper_width); + let creeper_y_init_pos = find_best_y(creeper_x_init_pos, this.terrain_ceiling); + + // Breaks creepers in multiple dynamic bodies linked by joints + if(this.movable_creepers){ + + // Creates a static base to which the creeper is attached + this.fd_creeper.shape.SetAsBox(creeper_width/2, 0.2); + body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_staticBody; + body_def.position.Set(creeper_x_init_pos, creeper_y_init_pos - 0.1); + t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_creeper); + t.SetUserData(new CustomUserData("creeper", CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN)); + let previous_creeper_part = t; + + // Cuts the creeper in unit parts + for(let w = 0; w < Math.ceil(creeper_height); w++){ + let h; + // last iteration: rest of the creeper + if(w == Math.floor(creeper_height / CREEPER_UNIT)){ + h = Math.max(0.2, creeper_height % CREEPER_UNIT); + } + else{ + h = CREEPER_UNIT; + } + + this.fd_creeper.shape.SetAsBox(creeper_width/2, h/2); + body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_dynamicBody; + body_def.position.Set(creeper_x_init_pos, creeper_y_init_pos - (w * CREEPER_UNIT) - h/2); + t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_creeper); + t.SetUserData(new CustomUserData("creeper", CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN)); + color = "#6F8060"; // [0.437, 0.504, 0.375]; + poly_data = { + type : "creeper", + color1 : color, + color2 : color, + body : t, + } + this.terrain_bodies.push(poly_data); + + let rjd_def = new b2.RevoluteJointDef(); + let anchor = new b2.Vec2(creeper_x_init_pos, creeper_y_init_pos - (w * CREEPER_UNIT)); + rjd_def.Initialize(previous_creeper_part, t, anchor); + rjd_def.enableMotor = false; + rjd_def.enableLimit = true; + rjd_def.lowerAngle = -0.4 * Math.PI; + rjd_def.upperAngle = 0.4 * Math.PI; + let joint = this.world.CreateJoint(rjd_def); + joint.SetUserData(new CustomMotorUserData("creeper", 6, false)); + this.creepers_joints.push(joint); + previous_creeper_part = t; + } + } + + // Creates only one static creeper body + else{ + this.fd_creeper.shape.SetAsBox(creeper_width/2, creeper_height/2); + body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_staticBody; + body_def.position.Set(creeper_x_init_pos, creeper_y_init_pos - creeper_height/2); + t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_creeper); + t.SetUserData(new CustomUserData("creeper", CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN)); + color = "#6F8060"; // [0.437, 0.504, 0.375]; + poly_data = { + type : "creeper", + color1 : color, + body : t, + } + this.terrain_bodies.push(poly_data); + } + } + } + } + + /** + * Generates random clouds. + */ + _generate_clouds(){ + this.cloud_polys = []; + for(let i = 0; i < Math.ceil(TERRAIN_LENGTH/10); i++){ + let x = (Math.random() * 5 * TERRAIN_LENGTH - TERRAIN_LENGTH) * TERRAIN_STEP; + let y = Math.random() * RENDERING_VIEWER_H/SCALE + RENDERING_VIEWER_H/SCALE * 1/5; + let poly = []; + for(let a = 0; a < 10; a++){ + poly.push([ + x + 15 * TERRAIN_STEP * Math.sin(Math.PI * 2 * a / 5) + Math.random() * (0 - 5 * TERRAIN_STEP) + 5 * TERRAIN_STEP, + y + 5 * TERRAIN_STEP * Math.cos(Math.PI * 2 * a / 5) + Math.random() * (0 - 5 * TERRAIN_STEP) + 5 * TERRAIN_STEP + ]) + } + let x1 = Math.min(...poly.map(p => p[0])); + let x2 = Math.max(...poly.map(p => p[0])); + this.cloud_polys.push({poly: poly, x1: x1, x2: x2}); + } + } + + /** + * Generates the given agent by computing its initial position and creating its physics body. + * @param agent {Object} + * @param init_x {number} + * @param init_y {number} + */ + _generate_agent(agent, init_x=null, init_y=null){ + + if(init_x == null){ + // If an init_pos is given for the agent (reset due to terrain reshaping), init_y is computed accordingly + if(agent.init_pos != null){ + init_x = agent.init_pos.x; + + // Computes the best y position corresponding to init_x to always generate the walkers on the ground + if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { + init_y = find_best_y(init_x, this.terrain_ground) + agent.agent_body.AGENT_CENTER_HEIGHT; + } + + // Computes the best y position corresponding to init_x to always generate the swimmers between the ground and the ceiling + else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + let y_ground = find_best_y(init_x, this.terrain_ground, agent.agent_body.AGENT_WIDTH); + if(y_ground == null){ + y_ground = -Infinity; + } + let y_ceiling = find_best_y(init_x, this.terrain_ceiling, agent.agent_body.AGENT_WIDTH); + if(y_ceiling == null){ + y_ceiling = Infinity; + } + init_y = Math.max(y_ground + 4 * agent.agent_body.AGENT_CENTER_HEIGHT, Math.min(y_ceiling - 4 * agent.agent_body.AGENT_CENTER_HEIGHT, agent.init_pos.y)); + } + } + + // If no init_pos is given (add_agent), the agent is generated on the startpad + else{ + init_x = TERRAIN_STEP * INITIAL_TERRAIN_STARTPAD / 2; + + // Sets init_y position according to the agent + init_y = TERRAIN_HEIGHT + agent.agent_body.AGENT_CENTER_HEIGHT; + if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + init_y = TERRAIN_HEIGHT + 4 * agent.agent_body.AGENT_CENTER_HEIGHT; + } + } + } + + // Creates the Box2D bodies of the agent's morphology + agent.agent_body.draw(this.world, init_x, init_y, 0); + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); + + // If the agent is a climber, initializes its position + if(agent.agent_body.body_type == BodyTypesEnum.CLIMBER){ + this.init_climber_pos(agent); + } + } + + /** + * Sets the position of an agent. + * @param agent {Object} + * @param init_x {number} + * @param init_y {number} + */ + set_agent_position(agent, init_x, init_y) { + agent.agent_body.destroy(this.world); + + if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { + // Computes the best y position corresponding to init_x to always generate the walkers on the ground + init_y = find_best_y(init_x, this.terrain_ground) + agent.agent_body.AGENT_CENTER_HEIGHT; + } + + // Computes the best y position corresponding to init_x to always generate the swimmers between the ground and the ceiling + else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ + let y_ground = find_best_y(init_x, this.terrain_ground, agent.agent_body.AGENT_WIDTH); + if(y_ground == null){ + y_ground = -Infinity; + } + let y_ceiling = find_best_y(init_x, this.terrain_ceiling, agent.agent_body.AGENT_WIDTH); + if(y_ceiling == null){ + y_ceiling = Infinity; + } + init_y = Math.max(y_ground + 4 * agent.agent_body.AGENT_CENTER_HEIGHT, Math.min(y_ceiling - 4 * agent.agent_body.AGENT_CENTER_HEIGHT, init_y)); + } + + this._generate_agent(agent, init_x, init_y); + this.update_lidars(agent); + } + + /** + * Sets the scroll to follow the given agent or to the given values. + * @param agent {Object} + * @param h {number} - Horizontal scroll + * @param v {number} - Vertical scroll + */ + set_scroll(agent=null, h=null, v=null){ + let terrain_length = Math.max(this.terrain_ground[this.terrain_ground.length - 1].x, this.terrain_ceiling[this.terrain_ceiling.length - 1].x); + + // Sets the scroll to follow the agent + if(agent != null){ + let x = agent.agent_body.reference_head_object.GetPosition().x; + let y = agent.agent_body.reference_head_object.GetPosition().y; + + this.scroll = [ + (x * this.scale - RENDERING_VIEWER_W/5) * this.zoom, + (y * this.scale - RENDERING_VIEWER_H * 2/5) * this.zoom + ]; + } + + // Adjusts the scroll when dragging an agent outside of the canvas + else if(window.is_dragging_agent){ + + if(window.dragging_side == "left"){ + this.scroll[0] = window.agent_selected.agent_body.reference_head_object.GetPosition().x * this.scale * this.zoom - RENDERING_VIEWER_W * (0.1 + 0.05) + } + else if(window.dragging_side == "right"){ + this.scroll[0] = window.agent_selected.agent_body.reference_head_object.GetPosition().x * this.scale * this.zoom - RENDERING_VIEWER_W * (0.85 + 0.05) + } + + // Adjusts the vertical scroll to follow the vertical position of the agent + this.scroll[1] = (window.agent_selected.agent_body.reference_head_object.GetPosition().y * this.scale - RENDERING_VIEWER_H * 2/5) * this.zoom; + } + + // Sets the scroll to the given values + else{ + this.scroll = [h, v]; + } + + // Clamps scroll both horizontally and vertically when drawing + if(window.is_drawing()){ + this.scroll[0] = Math.max(INIT_SCROLL_X, Math.min(this.scroll[0], TERRAIN_LENGTH * TERRAIN_STEP * this.scale * this.zoom - RENDERING_VIEWER_W * 0.9 + SCROLL_X_MAX)); + this.scroll[1] = Math.max(-SCROLL_Y_MAX, Math.min(this.scroll[1], SCROLL_Y_MAX)); + } + else{ + // Clamps scroll only horizontally when not drawing + this.scroll[0] = Math.max(INIT_SCROLL_X, Math.min(this.scroll[0], terrain_length * this.scale * this.zoom - RENDERING_VIEWER_W * 0.9)); + } + } + + /** + * Sets the zoom to the given value and clamps it in the authorized range. + * @param zoom + */ + set_zoom(zoom){ + this.zoom = Math.max(0.2, Math.min(parseFloat(zoom), 1.5)); + } + + /** + * Adds an agent to the environment, initializes it and runs one step. + * @param morphology {string} + * @param policy {{name: string, path: string}} + * @param pos {{x: number, y: number}} + */ + add_agent(morphology, policy, pos){ + this.create_agent(morphology, policy, pos); + if(pos != null){ + this._generate_agent(this.agents[this.agents.length - 1], pos.x, pos.y); + } + else{ + this._generate_agent(this.agents[this.agents.length - 1]); + } + this.init_agent(this.agents[this.agents.length - 1]); + let step_rets = this.step(); + window.game.obs.push([...step_rets.map(e => e[0])]); + window.game.rewards.push([...step_rets.map(e => e[1])]); + } + + /** + * Deletes the agent corresponding to the given index in the list of agents. + * @param agent_index {number} + */ + delete_agent(agent_index){ + if(this.agents.length > 0 && agent_index < this.agents.length){ + + // Removes the agent from the list and destroys its body + let agent = this.agents[agent_index]; + this.agents.splice(agent_index, 1); + agent.agent_body.destroy(this.world); + + // Adjusts the id of the other agents + for(let i = 0; i < this.agents.length; i++){ + this.agents[i].id = i; + } + + // Removes the observation of this agent from the list of observations. + window.game.obs[window.game.obs.length - 1].splice(agent_index, 1); + window.game.rewards[window.game.rewards.length - 1].splice(agent_index, 1); + } + } + + /** + * Creates a circle body at the given position and with the given radius. + * @param pos {{x: number, y: number}} + * @param radius {number} + */ + create_circle_asset(pos, radius){ + // Computes the best y position corresponding to pos.x to always generate the assets between the ground and the ceiling + let y_ground = find_best_y(pos.x, this.terrain_ground, radius); + if(y_ground == null){ + y_ground = -Infinity; + } + let y_ceiling = find_best_y(pos.x, this.terrain_ceiling, radius); + if(y_ceiling == null){ + y_ceiling = Infinity; + } + let y = Math.max(y_ground + radius, Math.min(y_ceiling - radius, pos.y)); + + // Box2D creation + this.fd_circle.shape.m_radius = radius; + let body_def = new b2.BodyDef(); + body_def.type = b2.Body.b2_dynamicBody; + body_def.position.Assign(new b2.Vec2(pos.x, y)); + let t = this.world.CreateBody(body_def); + t.CreateFixture(this.fd_circle); + t.SetUserData(new CustomUserData("circle", CustomUserDataObjectTypes.TERRAIN)); + let poly_data = { + type : "circle", + color1 : "#885C00", // [136, 92, 0]; + color2 : "#5F3D0E", // [95, 61, 14]; + body : t, + is_selected: false + } + this.assets_bodies.push(poly_data); + } + + /** + * Sets the position of the given asset to the given position. + * @param asset {Object} + * @param pos {{x: number, y: number}} + */ + set_asset_position(asset, pos){ + let shape = asset.body.GetFixtureList().GetShape(); + let radius; + // Only supports circle assets for now + if(shape.m_type == b2.Shape.e_circle){ + radius = shape.m_radius; + } + + // Computes the best y position corresponding to pos.x to always generate the assets between the ground and the ceiling + let y_ground = find_best_y(pos.x, this.terrain_ground, radius); + if(y_ground == null){ + y_ground = -Infinity; + } + let y_ceiling = find_best_y(pos.x, this.terrain_ceiling, radius); + if(y_ceiling == null){ + y_ceiling = Infinity; + } + let y = Math.max(y_ground + radius, Math.min(y_ceiling - radius, pos.y)); + asset.body.SetTransform(new b2.Vec2(pos.x, y), + asset.body.GetAngle()); + asset.body.SetLinearVelocity(new b2.Vec2(0, -0.1)); + } + + /** + * Deletes the given asset. + * @param asset {Object} + */ + delete_asset(asset){ + if(this.assets_bodies.length > 0){ + let index = this.assets_bodies.indexOf(asset); + if(index != -1){ + // Removes the asset from the list and destroys its body + this.assets_bodies.splice(index, 1); + this.world.DestroyBody(asset.body); + } + } + } + //endregion +} + +/** + * Finds the best y value corresponding to the given x value according to the points in the given array. + * @param x {number} + * @param array {Array} + * @param [max_dist=null] {number} - Maximum horizontal distance to consider if no good y position has been found + * @return {number} + */ +function find_best_y(x, array, max_dist=null){ + // Finds the closest point to x in array according to the x-coordinate + let p1 = array.reduce(function(prev, curr) { + return (Math.abs(curr.x - x) < Math.abs(prev.x - x) ? curr : prev); + }); + + // Gets the index of p1 + let i1 = array.indexOf(p1); + + // Gets p2 so that x in [p1.x, p2.x] or x in [p2.x, p1.x] + let p2; + + // Case x > p1.x --> x in [p1.x, p2.x] + if(x > p1.x){ + if(i1 < array.length - 1){ + p2 = array[i1 + 1]; + } + else{ + p2 = p1; + } + } + // Case x <= p1.x --> x in [p2.x, p1.x] + else{ + if(i1 > 0){ + p2 = array[i1 - 1]; + } + else{ + p2 = p1; + } + } + + let y = p1.y; + // Computes the equation of the line between p1 and p2 and finds y corresponding to x + if(p1.x != p2.x){ + let a = (p2.y - p1.y) / (p2.x - p1.x); + let b = p1.y - a * p1.x; + y = a * x + b; + } + + // If p1 and p2 are the same point and x is too distant from it, returns null to indicate that no good point has been found + else if(max_dist != null && Math.abs(x - p1.x) > max_dist){ + y = null; + } + return y; +} + +/** + * Smoothes the terrain by filtering points that are horizontally too close according to the given epsilon value. + * @param terrain {Array} - Array of points + * @param epsilon {number} - Minimal horizontal distance between two points + * @return {Array} - Filtered array of points + */ +function smoothTerrainFiler(terrain, epsilon){ + let smooth_terrain = []; + if(terrain.length > 0){ + smooth_terrain.push(terrain[0]); + let n = 0; + for(let i = 1; i < terrain.length - 1; i++){ + if(terrain[i].x >= smooth_terrain[n].x + epsilon){ + smooth_terrain.push(terrain[i]); + n += 1; + } + } + smooth_terrain.push(terrain[terrain.length - 1]); + } + return smooth_terrain; +} \ No newline at end of file diff --git a/js/game.js b/js/game.js new file mode 100644 index 0000000000000000000000000000000000000000..6f7650e9c70cb7c6a05a936d5e09923f985266e1 --- /dev/null +++ b/js/game.js @@ -0,0 +1,165 @@ +/** + * @classdesc Class that handles the simulation. + */ +class Game { + /** + * @constructor + * @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents + * @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN + * @param water_level {number} + * @param creepers_width {number} + * @param creepers_height {number} + * @param creepers_spacing {number} + * @param smoothing {number} + * @param creepers_type {boolean} + * @param ground {Array} - List of points {x, y} composing the ground + * @param ceiling {Array} - List of points {x, y} composing the ceiling + * @param align_terrain {Object} + */ + constructor(agents, cppn_input_vector, water_level, creepers_width, creepers_height, + creepers_spacing, smoothing, creepers_type, ground, ceiling, align_terrain) { + + this.run_fps = 60; + this.obs = []; + this.rewards = []; + this.initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, + creepers_type, ground, ceiling, align_terrain); + this.running = false; + } + + /** + * Initializes the environment. + * @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents + * @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN + * @param water_level {number} + * @param creepers_width {number} + * @param creepers_height {number} + * @param creepers_spacing {number} + * @param smoothing {number} + * @param creepers_type {boolean} + * @param ground {Array} - List of points {x, y} composing the ground + * @param ceiling {Array} - List of points {x, y} composing the ceiling + * @param align_terrain {Object} + */ + initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, + smoothing, creepers_type, ground, ceiling, align_terrain) { + + this.env = new MultiAgentsContinuousParkour( + agents, + 3, + smoothing, + 200, + 90, + 20, + creepers_type, + ground, + ceiling, + align_terrain); + + this.env.set_environment(cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, creepers_type); + let step_rets = this.env.reset(); + this.obs.push([...step_rets.map(e => e[0])]); + this.rewards.push([...step_rets.map(e => e[1])]); + } + + /** + * Pauses the simulation. + */ + pause(){ + clearInterval(this.runtime); + this.running = false; + } + + /** + * Runs the simulation. + * @returns {Promise} + */ + async run(){ + + // Loads the policy for each agent before launching the simulation + for(let agent of window.game.env.agents){ + if(agent.policy.path != null){ + agent.model = await tf.loadGraphModel(agent.policy.path + '/model.json'); + } + else{ + agent.model = null; + } + } + + // Creates a repeated interval over time + this.runtime = setInterval(() => { + this.play(); + }, 1000 / this.run_fps); + this.running = true; + } + + /** + * + * @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents + * @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN + * @param water_level {number} + * @param creepers_width {number} + * @param creepers_height {number} + * @param creepers_spacing {number} + * @param smoothing {number} + * @param creepers_type {boolean} + * @param ground {Array} - List of points {x, y} composing the ground + * @param ceiling {Array} - List of points {x, y} composing the ceiling + * @param align_terrain {Object} + */ + reset(agents, cppn_input_vector, water_level, creepers_width, creepers_height, + creepers_spacing, smoothing, creepers_type, ground, ceiling, align_terrain){ + + this.pause(); + let zoom = window.game.env.zoom; + let scroll = [...window.game.env.scroll]; + this.initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, + creepers_type, ground, ceiling, align_terrain); + + // Keeps the previous zoom and scroll + window.game.env.set_zoom(zoom); + window.game.env.set_scroll(null, scroll[0], scroll[1]); + this.env.render(); + } + + /** + * Plays one simulation step. + */ + play() { + + // Gets the actions to execute for each agent + for(let agent of window.game.env.agents){ + let state = this.obs[this.obs.length - 1][agent.id]; + + // Generates the actions thanks to the agent's policy model + if(agent.model != null){ + let envState = tf.tensor(state,[1, state.length]); + + let inputs = { + "Placeholder_1:0": envState + }; + + let output = 'main/mul:0' + + agent.actions = agent.model.execute(inputs, output).arraySync()[0]; + } + + // Generates random actions + else /*if(agent.policy.name == "random")*/{ + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => Math.random() * 2 - 1); + } + + // Generates motionless actions + /*else{ + agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); + }*/ + } + + // Runs one step and stores the resulted states for each agent + let step_rets = this.env.step(); + this.obs.push([...step_rets.map(e => e[0])]); + this.rewards.push([...step_rets.map(e => e[1])]); + + this.env.render(); + } +} diff --git a/js/i18n.js b/js/i18n.js new file mode 100644 index 0000000000000000000000000000000000000000..197275820111fdd73bb00d1cd385a0753acdb254 --- /dev/null +++ b/js/i18n.js @@ -0,0 +1,599 @@ +// Internationalization dictionary +window.lang_dict = { + + // English + 'EN': { + 'introTour': { + 'nextLabel': "Next", + 'prevLabel': "Back", + 'doneLabel': "Done", + 'welcomeTitle': "Welcome!", + 'welcomeText': "Here you can play with a simulation where autonomously trained agents are trying to navigate through a 2D environment.", + 'viewportTitle': "Viewport simulation", + 'viewportText': "Here is the viewport where the simulation is rendered in real time. It allows you to see the environment and visualize live how the agents are dealing with it.

      You can also interact with the simulation using the mouse in order to scroll, zoom or even drag and drop the agents.

      Try it now! ", + 'runTitle': "Run the simulation", + 'runText': 'Click the button to run the simulation.
      Then, click the button to pause it or the to reset it.

      Try it now!', + 'baseEnvsTitle': "Some environments", + 'baseEnvsText': "Here are some basic environments that will let you become more familiar with the different morphologies of agents.
      You will be able to load them into the simulation to visualize the behaviour of the different agents.", + 'morphologiesTitle': "Agents morphologies", + 'morphologiesText': "Here are all the morphologies available for the agents. You can select one of several agents for each morphology and add it to the simulation.

      Each agent has been trained to learn an optimal behaviour to navigate through the environment according to its morphology. Try to compare them!", + 'agentsListTitle': "List of running agents", + 'agentsListText': "In this section you can find all the agents that are currently running in the simulation.", + 'customEnvsTitle': "Custom environments", + 'customEnvsText': "Here you can save and download your custom environments but also upload them from previously downloaded files. Try to share them with your friends!", + 'furtherTitle': "Going further...", + 'furtherText': "If you want to customize the environment, access more advanced options or learn more about the context of this demo, open these tabs.

      Enjoy!", + }, + + 'introHints': { + 'buttonLabel': "Got it", + 'tips': `Tips + +
      ` + }, + + 'agentsList': { + 'title': "List of running agents", + 'follow': "Follow", + 'followTooltip' : "Center the viewport on the agent", + 'savePosTooltip': "Save the agent's position", + 'resetPosTooltip': "Reset the agent's position", + 'deleteAgentTooltip': "Delete the agent", + }, + + 'mainButtons':{ + 'runBtnTooltip': "Run the simulation", + 'pauseBtnTooltip': "Pause the simulation", + 'resetBtnTooltip': "Reset the simulation", + 'saveBtnTooltip': "Save the current environment" + }, + + 'drawingMode': { + 'intro': 'Here you can draw your own parkour!', + 'text': `Select the Ground or Ceiling button to start drawing the corresponding terrain shape with the mouse.
      + Be careful not to draw more than one line at different heights if you want the result to be optimal.
      + You can use the Erase button if you need to correct your drawing or the Clear one to clear all your drawing.
      + When you are satisfied with the result, just click the Generate Terrain button.`, + 'ground': "Ground", + 'ceiling': "Ceiling", + 'erase': "Erase", + 'clear': "Clear", + 'generateTerrain': "Generate Terrain", + 'draw': "Draw", + }, + + 'parkourConfig': { + 'terrainGeneration': "Terrain Generation", + 'generalParameters': "General Parameters", + 'creepers': "Creepers", + 'drawTabBtn': "Draw Yourself!", + 'procGenTabBtn': "Procedural Generation", + 'procGenText': `You can also use these three sliders to generate the terrain shapes automatically.`, + 'smoothing': "Smoothing", + 'waterLevel': "Water level", + 'creepersWidth': "Width", + 'creepersHeight': "Height", + 'creepersSpacing': "Spacing", + //'creepersType': "Type", + 'rigid': "Rigid", + 'swingable': "Swingable", + }, + + 'morphologies': { + 'title': "Add an agent", + 'text': "Here you can add an agent to the simulation with the morphology of your choice.", + 'policySelectTooltip': "Select an agent", + 'addBtnTooltip': "Add the agent to the simulation", + 'baby': "baby", + 'teenager': "teenager", + 'adult': "adult", + 'bipedal': { + 'title': "Bipedal", + 'description': "This morphology is composed of a head and two legs which allow it to walk on the floor." + }, + 'spider': { + 'title': "Spider", + 'description': "This morphology is composed of a body and four legs which allow it to walk on the floor." + }, + 'chimpanzee': { + 'title': "Chimpanzee", + 'description': "This morphology is composed of a head, a torso and two arms and legs. It can only move by climbing the ceiling and grasping the creepers.", + }, + 'fish': { + 'title': "Fish", + 'description': "This morphology is composed of a head, a tail and a fin, allowing it to swim in the water.", + }, + }, + + 'envsSets': { + 'baseSetText': `To begin you can select one of the following environments to load it into the simulation, and then run it by clicking the button.`, + 'customSetText': `In this section you can store your own custom environments by saving them thanks to the button above or by uploading them from a JSON file.`, + 'uploadCard': { + 'title': "Upload an environment", + 'text': `Choose a JSON file then click the button below to save the corresponding environment in your collection.`, + 'uploadBtnTooltip': "Upload the environment from the selected file", + }, + 'downloadBtnTooltip': "Download the environment", + 'deleteBtnTooltip': "Delete the environment", + }, + + 'advancedOptions': { + 'renderingOptions': ` Rendering Options `, + 'drawJoints': "Draw joints", + 'drawJointsTooltip': "Joints are what bind the different bodies together. They also act as motors for the agents morphologies.", + 'drawLidars': "Draw lidars", + 'drawLidarsTooltip': "Lidars are sensors which enable agents to detect nearby obstacles and water.", + 'drawNames': "Draw names", + 'drawNamesTooltip': "Name of the agents.", + 'drawObservation': "Draw observations", + 'drawObservationTooltip': "The observation is a partial view of the environment state at each step on which the agents rely to take an action.", + 'drawReward': "Draw rewards", + 'drawRewardTooltip': "The reward is a value that indicates how good or bad the current state is, according to the objective of the agent.", + 'stepReward': "Step reward", + 'totalReward': "Cumulative reward", + 'assetsTitle': ` Assets `, + 'assetsText': "Here you can find several types of assets, which are objects that you can add to the simulation using the mouse.", + 'circle': ` Ball`, + 'comingSoon': "More assets coming soon...", + }, + + 'globalElements': { + 'demoTitle': "Interactive Deep Reinforcement Learning Demo", + 'gettingStarted': "Getting Started", + 'parkourCustomization': "Parkour Customization", + 'advancedOptions': "Advanced Options", + 'about': "About...", + 'saveEnvModal': { + 'title': `Please enter a name and a description for the current environment.`, + 'text': "This environment will be saved in your collection of custom environments so that you could reload it later or download it to share it.", + 'nameLabel': "Name", + 'descriptionLabel': "Description", + 'cancelBtn': "Cancel", + 'confirmBtn': "Save", + }, + }, + + 'aboutTab': { + 'purposeTitle': "Purpose of the demo", + 'purposeText': `

      + The goal of this demo is to showcase the challenge of generalization to unknown tasks + for Deep Reinforcement Learning (DRL) agents. +

      + +

      + DRL is a Machine Learning approach for teaching virtual agents + how to solve tasks by combining Reinforcement Learning and Deep Learning methods. + This approach has been used for a diverse set of applications including robotics (e.g. Solving Rubik's Cube [1]), + video games and boardgames (e.g. AlphaGo [2]). +

      + +

      + In this demo, all the agents have been autonomously trained to learn an efficient behaviour to navigate through a 2D environment, + combining a DRL algorithm and a teacher algorithm (see below) so that they can be able to generalize their behaviour to never-seen-before situations. +

      + +

      + The demo provides different tools to customize the environment in order to test and challenge the + robustness of the agents on different situations. +

      `, + 'rlTitle': "Reinforcement Learning", + 'rlText': `

      + Reinforcement Learning (RL) is the study of agents and how they learn by trial and error. + The main idea is to reward or punish an agent according to the actions it takes in order to make it learn an efficient behavior to reach an objective. +
      + The RL approaches generally feature an agent which evolves and interacts with a world. + At each interaction step, the agent sees a partial observation of the current state of the environment and decides of an action to take. + Each action taken by the agent changes the state of the world. + The agent also receives a reward signal at each step, that indicates how good or bad the current state is + according to the objective the agent has to reach. +

      + +
      +
      +

      + The diagram on the right presents this interaction process between the agent and the environment, + with the different information they exchange at each step. +
      + Maximizing the reward over steps is a way for the agent to learn a behaviour, also called policy, + to achieve its objective. +

      +
      +
      + RL diagram +
      +
      `, + 'drlTitle': "Deep RL", + 'drlText': `

      + In order to remember and improve the actions taken by the agent, DRL algorithms utilize artificial neural networks. + With training, these neural networks are able to learn to predict an optimal action to take at each step from the observation received, + thanks to all the observations and rewards previously received after each action during training. + Thanks to this, DRL algorithms are able to produce behaviours that are very effective in situations similar to those they were trained on. +

      + +
      + RL demo diagram +
      + +

      + However, in real-world applications, the environment rarely remains still and frequently evolves. Therefore one would + want DRL agents to be able to generalize their behaviour to previously unseen changes of the environment so that + they can adapt to a large range of situations. +

      `, + 'aclTitle': "Automatic Curriculum Learning", + 'aclText': `

      + One solution to handle this challenge is to train DRL agents on procedurally generated environments. +
      + Procedural generation is a method of automatically creating environments according to some parameters. + Using this method, DRL agents can be trained on a very wide range of environments, hence allowing them + to generalize their behaviour to more different situations. +

      + +

      + However, randomly generating environments during training implies the risk to generate environments that are too difficult or too easy to resolve + for the agents, preventing them to continuously learn in an efficient way. +
      + Therefore, one would need smarter training strategies that propose relevant environments tailored to the current learning progress of the student (DRL agent). + This method is called Automatic Curriculum Learning (ACL) [3] and is embodied by a teacher algorithm which is trained to learn to generate + the most relevant environments throughout the entire training process according to the student performances. +
      + This way, the teacher proposes easy environments to the student at the beginning and gradually increases the difficulty + and the diversity of the tasks in order to guarantee that the student is progressing while not always facing the same situation or forgetting what it has already learned. +

      `, + 'aboutDemoTitle': "About the demo", + 'aboutDemoText': ` +

      + In this demo, all the available agents were trained using Soft Actor Critic [4] + as the DRL student algorithm alongside different ACL teacher algorithms such as ALP-GMM [5]. +
      + They successfully learned efficient behaviours to move through the environment and to generalize to never-seen-before situations. +

      + +

      + The physics of the simulation are handled by the box2d.js physics engine + which is a direct port to JavaScript of the Box2D physics engine. +
      + The pre-trained policies (agents behaviours) are loaded in the browser thanks to TensorFlow.js. +

      `, + 'creditsTitle': "Credits", + 'creditsText': `

      + This demo was designed by Paul Germon as part of an internship within Flowers + research team at Inria. This internship was monitored by Rémy Portelas and Clément Romac, + and supervised by Pierre-Yves Oudeyer. Special thanks to Nikita Melkozerov for its very helpful contribution. + Recommended citation format: +

      +                                @misc{germon2021demo,
      +                                  title={Interactive Deep Reinforcement Learning Demo},
      +                                  author={Germon, Paul and Romac, Clément and Portelas, Rémy and Pierre-Yves, Oudeyer},
      +                                  url={https://developmentalsystems.org/Interactive_DeepRL_Demo/},
      +                                  year={2021}
      +                                }
      +                                
      +

      + + `, + 'referencesTitle': "References", + 'referencesText': ``, + + } + }, + + // French + 'FR': { + 'introTour': { + 'nextLabel': "Suivant", + 'prevLabel': "Précédent", + 'doneLabel': "Fermer", + 'welcomeTitle': "Bienvenue !", + 'welcomeText': "Ici tu peux jouer avec une simulation dans laquelle des agents entraînés de manière autonome essayent de se déplacer au travers d'un environnement 2D.", + 'viewportTitle': "Fenêtre d'affichage", + 'viewportText': "C'est dans cet espace que la simulation est affichée en temps réel. Cela va te permettre de visualiser en direct comment les agents essayent de s'adapter à leur environment.

      Tu peux aussi interagir avec la simulation à l'aide de la souris pour faire défiler l'environnement, zoomer ou encore déplacer les agents.

      Tu peux essayer dès maintenant !", + 'runTitle': "Lancer la simulation", + 'runText': 'Clique sur le bouton pour lancer la simulation.
      Tu peux ensuite cliquer sur le bouton pour la mettre en pause ou sur le bouton pour la réinitialiser.

      Tu peux essayer dès maintenant !', + 'baseEnvsTitle': "Quelques environnements", + 'baseEnvsText': "Voici quelques environnements de base qui t'aideront à te familiariser avec les différentes morphologies d'agents.
      Tu pourras les charger dans la simulation pour voir les comportements des différents agents.", + 'morphologiesTitle': "Les différentes morphologies d'agents", + 'morphologiesText': "Voici toutes les morphologies disponibles pour les agents. Tu peux choisir parmi plusieurs agents différents pour chaque morphologie et l'ajouter à la simulation.

      Chaque agent a été entraîné pour apprendre un comportement efficace pour se déplacer à travers l'environnement en fonction de sa morphologie. Essaye de les comparer !", + 'agentsListTitle': "List des agents actifs", + 'agentsListText': "Dans cette section sont affichés tous les agents actuellement présents dans la simulation.", + 'customEnvsTitle': "Environnements personnalisés", + 'customEnvsText': "Ici tu peux sauvegarder et télécharger tes environnements personnalisés mais aussi en importer depuis des fichiers précédemment téléchargés. Essaye de les échanger avec tes amis !", + 'furtherTitle': "Pour aller plus loin...", + 'furtherText': "Si tu veux personnaliser ton propre environnement, accéder à des options avancées ou en apprendre davantage à propos du contexte autour de cette démo, ouvre ces onglets.

      Amuse-toi bien !", + }, + + 'introHints': { + 'buttonLabel': "Ok", + 'tips': `Astuces + +
      ` + }, + + 'agentsList': { + 'title': "Liste des agents actifs", + 'follow': "Suivre", + 'followTooltip' : "Centrer la fenêtre d'affichage sur l'agent", + 'savePosTooltip': "Sauvegarder la position de l'agent", + 'resetPosTooltip': "Réinitiliaser la position de l'agent", + 'deleteAgentTooltip': "Supprimer l'agent", + }, + + 'mainButtons':{ + 'runBtnTooltip': "Lancer la simulation", + 'pauseBtnTooltip': "Mettre la simulation en pause", + 'resetBtnTooltip': "Réinitialiser la simulation", + 'saveBtnTooltip': "Sauvegarder l'environnement actuel" + }, + + 'drawingMode': { + 'intro': 'Ici tu peux dessiner ton propre parkour !', + 'text': `Selectionne les boutons Sol ou Plafond pour commencer à dessiner l'élément du terrain correspondant avec la souris.
      + Fais attention à ne pas superposer plusieurs traits à différentes hauteurs pour obtenir un résultat optimal.
      + Tu peux utiliser le bouton Gommer pour corriger ton dessin ou le bouton Effacer pour tout effacer.
      + Une fois que tu es satisfait du résultat, clique sur le bouton Générer le terrain.`, + 'ground': "Sol", + 'ceiling': "Plafond", + 'erase': "Gommer", + 'clear': "Effacer", + 'generateTerrain': "Générer le terrain", + 'draw': "Dessiner", + }, + + 'parkourConfig': { + 'terrainGeneration': "Génération du terrain", + 'generalParameters': "Paramètres Généraux", + 'creepers': "Lianes", + 'drawTabBtn': "Dessine par toi-même !", + 'procGenTabBtn': "Génération procédurale", + 'procGenText': `Tu peux aussi utiliser ces trois curseurs pour générer les formes du terrain de manière automatique.`, + 'smoothing': "Lissage", + 'waterLevel': "Niveau d'eau", + 'creepersWidth': "Largeur", + 'creepersHeight': "Hauteur", + 'creepersSpacing': "Espacement", + //'creepersType': "Type", + 'rigid': "Rigides", + 'swingable': "Flexibles", + }, + + 'morphologies': { + 'title': "Ajouter un agent", + 'text': "Ici tu peux ajouter un agent à la simulation avec la morphologie de ton choix.", + 'policySelectTooltip': "Sélectionner un agent", + 'addBtnTooltip': "Ajouter l'agent à la simulation", + 'baby': "bébé", + 'teenager': "adolescent", + 'adult': "adulte", + 'bipedal': { + 'title': "Bipède", + 'description': "Cette morphologie est composée d'une tête et de deux jambes qui lui permettent de marcher sur le sol." + }, + 'spider': { + 'title': "Araignée", + 'description': "Cette morphologie est composée d'un corps et de quatre pattes qui lui permettent de marcher sur le sol." + }, + 'chimpanzee': { + 'title': "Chimpanzé", + 'description': "Cette morphologie est composée d'une tête, d'un corps ainsi que de deux bras et deux jambes. Elle peut uniquement se déplacer en s'accrochant au plafond ou en se balançant de lianes en lianes.", + }, + 'fish': { + 'title': "Poisson", + 'description': "Cette morphologie est composée d'une tête, d'une queue et d'une nageoire, ce qui lui permet de nager dans l'eau.", + }, + }, + + 'envsSets': { + 'baseSetText': `Pour commencer tu peux sélectionner un des environnments suivants en cliquant dessus pour le charger dans la simulation, puis lancer celle-ci en cliquant sur le bouton .`, + 'customSetText': `Dans cette section tu peux stocker tes propres environnements personnalisés en les sauvegardant grâce au bouton ci-dessus ou en les important depuis un fichier JSON.`, + 'uploadCard': { + 'title': "Importer un environnement", + 'text': `Choisis un fichier JSON puis clique sur le bouton ci-dessous pour importer l'environnement correspondant dans ta collection.`, + 'uploadBtnTooltip': "Importer l'environnement depuis le fichier sélectionné", + }, + 'downloadBtnTooltip': "Télécharger l'environnement", + 'deleteBtnTooltip': "Supprimer l'environnement", + }, + + 'advancedOptions': { + 'renderingOptions': ` Options d'affichage `, + 'drawJoints': "Afficher les joints", + 'drawJointsTooltip': "Les joints sont les liens qui attachent les différents objets physiques ensemble. Ils servent aussi de moteurs pour les morphologies des agents.", + 'drawLidars': "Afficher les lidars", + 'drawLidarsTooltip': "Les lidars sont des capteurs qui permettent aux agents de détecter les obstacles et l'eau à proximité.", + 'drawNames': "Afficher les noms", + 'drawNamesTooltip': "Nom des agents.", + 'drawObservation': "Afficher les observations", + 'drawObservationTooltip': "L'observation d'un agent est une vue partielle de l'état actuel de l'environnement à chaque pas de temps, sur laquelle les agents s'appuient pour effectuer une action.", + 'drawReward': "Afficher les récompenses", + 'drawRewardTooltip': "La récompense est une valeur qui indique la qualité de l'état actuel de l'environnement selon l'objectif que l'agent doit atteindre.", + 'stepReward': "Récompense courante", + 'totalReward': "Récompense cumulée", + 'assetsTitle': ` Objets `, + 'assetsText': "Ici tu peux trouver plusieurs types d'objets que tu peux ajouter à la simulation avec la souris.", + 'circle': ` Boule`, + 'comingSoon': "Plus d'objets à venir...", + }, + + 'globalElements': { + 'demoTitle': "Démo Interactive de Deep Reinforcement Learning", + 'gettingStarted': "Commencer", + 'parkourCustomization': "Personnalisation du parkour", + 'advancedOptions': "Options avancées", + 'about': "À propos...", + 'saveEnvModal': { + 'title': `Saisis un nom et une description pour l'environnement actuel`, + 'text': "Cet environnement sera sauvegardé dans ta collection d'environnements personnalisés pour que tu puisses le recharger plus tard ou le télécharger pour le partager.", + 'nameLabel': "Nom", + 'descriptionLabel': "Description", + 'cancelBtn': "Annuler", + 'confirmBtn': "Sauvegarder", + }, + }, + + 'aboutTab': { + 'purposeTitle': "Objectif de la démo", + 'purposeText': `

      + Le but de cette démonstration est de mettre en évidence le challenge de généralisation + à des nouvelles tâches pour des agents entraînés par Apprentissage par Renforcement Profond (ARP). +

      + +

      + L'ARP est une approche d'Apprentissage automatique (Machine Learning) + qui permet d'apprendre à des agents virtuels à résoudre des tâches en combinant des méthodes + d'Apprentissage par renforcement (Reinforcement Learning) et d'Apprentissage profond (Deep Learning). + Cette approche a été utilisée pour diverses applications dont notamment la robotique (e.g. Solving Rubik's Cube) [1], + les jeux vidéo et les jeux de plateau (e.g. AlphaGo) [2]. +

      + +

      + Dans cette démo, tous les agents ont été entraînés de manière autonome dans le but d'apprendre un + comportement efficace pour traverser un environnement 2D. + Ils ont été entraînés en combinant un algorithme d'ARP et un algorithme enseignant (voir ci-dessous) pour qu'ils soient capables + de généraliser leur comportement à des situations inédites. +

      + +

      + La démo fournit différents outils pour personnaliser l'environnement dans le but de tester et mettre la + robustesse des agents à l'épreuve lorsqu'ils font face à différentes situations. +

      `, + 'rlTitle': "Apprentissage par Renforcement", + 'rlText': `

      + L'Apprentissage par renforcement (AR) est l'étude des agents virtuels et de leur apprentissage par essais et erreurs. + L'idée principale est de récompenser ou punir un agent en fonction des actions qu'il effectue pour qu'il apprenne un comportement efficace pour atteindre un objectif. +
      + Les approches d'AR sont généralement composées d'un agent qui évolue dans un monde ou environnement et interagit avec. + À chaque pas de temps, l'agent voit une observation partielle de l'état actuel de l'environnement et décide d'effectuer une action. + Chaque action effectuée par l'agent change l'état de l'environnement. L'agent reçoit également une récompense + à chaque pas de temps, qui indique à quel point l'état actuel du monde est bon ou mauvais selon l'objectif que l'agent doit atteindre. +

      + +
      +
      +

      + Le schéma ci-contre présente ce processus d'interaction entre l'agent et l'environment, + avec les différentes informations qu'ils échangent à chaque pas de temps. +
      + Maximiser la récompense au cours du temps est un moyen pour l'agent d'apprendre un comportement optimal (ou politique) + pour atteindre son objectif. +

      +
      +
      + Schéma AR +
      +
      `, + 'drlTitle': "Apprentissage par renforcement profond", + 'drlText': `

      + Pour améliorer continuellement les actions effectuées par les agents, les algorithmes d'ARP utilisent + des réseaux de neurones artificiels. + Avec de l'entraînement, ces réseaux de neurones sont capables d'apprendre à prédire une action optimale + à effectuer à chaque étape à partir de l'observation reçue grâce à toutes les + observations et les récompenses préalablement reçues après chaque action effectuée au cours de l'entraînement. + Grâce à cela, les algorithmes d'ARP sont capables de produire des comportements très efficaces + dans des situations similaires à celles sur lesquelles ils ont été entraînés. +

      + +
      + RL demo diagram +
      + +

      + Cependant, dans des applications réelles, l'environnement reste rarement identique en permanence mais évolue. Par conséquent, + l'idéal serait que les agents d'ARP soient capables de généraliser leur comportement + à des changements inédits du monde pour qu'ils puissent s'adapter à un large éventail de situations. +

      `, + 'aclTitle': "Programme d'apprentissage automatique", + 'aclText': `

      + Une solution pour résoudre en partie ce problème est d'entraîner les agents d'ARP sur des environnements générés procéduralement. +
      + La génération procédurale est une méthode permettant de créer automatiquement des environnements en fonction de quelques paramètres. + En utilisant cette méthode, les agents peuvent être entraînés sur un très large éventail d'environnements, leur permettant ainsi + de généraliser leur comportement à plus de situations différentes. +

      + +

      + Néanmoins, le fait de générer des environnements aléatoires au cours de l'entraînement implique le risque de générer + des environnements trop difficiles ou trop faciles à résoudre pour les agents, les empêchant par conséquent d'apprendre en continu de manière efficace. +
      + L'idéal serait donc de disposer de stratégies d'entraînement plus intelligentes qui proposeraient des + environnements pertinents adaptés à l'avancement de l'apprentissage de l'élève (agent). + Cette méthode est appelée programme d'apprentissage automatique (Automatic Curriculum Learning) [3] + et est incarnée par un algorithme enseignant qui est entraîné dans le but d'apprendre à générer des environnements + les plus pertinents possibles tout au long du processus d'entraînement de l'élève en fonction de l'évolution de ses performances. +
      + De cette manière, l'enseignant commence par proposer des environnements faciles à l'élève puis augmente leur difficulté et leur diversité petit à petit + pour garantir que l'élève progresse continuellement tout en ne rencontrant pas toujours la même situation et en n'oubliant pas + ce qu'il a déjà appris. +

      `, + 'aboutDemoTitle': "À propos de la démo", + 'aboutDemoText': ` +

      + Dans cette démo, tous les agents ont été entraînés avec Soft Actor Critic [4] + comme algorithme élève d'ARP aux côtés de différents algorithmes enseignants comme par exemple ALP-GMM [5]. +
      + Les agents ont ainsi appris avec succès des comportements efficaces pour se déplacer à travers les envirionnements 2D en + généralisant leur comportement à des situations inédites. +

      + +

      + La physique de la simulation est gérée par le moteur physique box2d.js + qui est un portage direct en JavaScript du moteur physique Box2D. +
      + Les politiques pré-entraînées (comportements des agents) sont chargées dans le navigateur grâce à TensorFlow.js. +

      `, + 'creditsTitle': "Crédits", + 'creditsText': `

      + Cette démo a été conçue par Paul Germon dans le cadre d'un stage au sein de + l'équipe de recherche Flowers au laboratoire Inria. + Ce stage était encadré par Rémy Portelas et Clément Romac, et supervisé par Pierre-Yves Oudeyer. + Remerciements particuliers à Nikita Melkozerov pour sa contribution. + Citation recommandée: +

      +                                @misc{germon2021demo,
      +                                  title={Interactive Deep Reinforcement Learning Demo},
      +                                  author={Germon, Paul and Romac, Clément and Portelas, Rémy and Pierre-Yves, Oudeyer},
      +                                  url={https://developmentalsystems.org/Interactive_DeepRL_Demo/},
      +                                  year={2021}
      +                                }
      +                                
      +

      + + `, + 'referencesTitle': "Références", + 'referencesText': ``, + + } + } +} \ No newline at end of file diff --git a/js/ui_state/components/about_tab.js b/js/ui_state/components/about_tab.js new file mode 100644 index 0000000000000000000000000000000000000000..c1cab808bb91c444e053d77ea66e18523f39923c --- /dev/null +++ b/js/ui_state/components/about_tab.js @@ -0,0 +1,54 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for "About..." tab. + */ +export default class AboutTab extends Component { + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#about-tab'), + eventName: 'aboutTabChange' + }); + } + + /** + * Renders the global UI elements. + */ + render() { + let dict = window.lang_dict[store.state.language]['aboutTab']; + + // Purpose section + this.element.querySelector('#purpose-title').innerHTML = dict['purposeTitle']; + this.element.querySelector('#purpose-text').innerHTML = dict['purposeText']; + + // RL section + this.element.querySelector('#rl-title').innerHTML = dict['rlTitle']; + this.element.querySelector('#rl-text').innerHTML = dict['rlText']; + + // DRL section + this.element.querySelector('#drl-title').innerHTML = dict['drlTitle']; + this.element.querySelector('#drl-text').innerHTML = dict['drlText']; + + // ACL section + this.element.querySelector('#acl-title').innerHTML = dict['aclTitle']; + this.element.querySelector('#acl-text').innerHTML = dict['aclText']; + + // About demo section + this.element.querySelector('#about-demo-title').innerHTML = dict['aboutDemoTitle']; + this.element.querySelector('#about-demo-text').innerHTML = dict['aboutDemoText']; + + // Credits section + this.element.querySelector('#credits-title').innerHTML = dict['creditsTitle']; + this.element.querySelector('#credits-text').innerHTML = dict['creditsText']; + + // References section + this.element.querySelector('#references-title').innerHTML = dict['referencesTitle']; + this.element.querySelector('#references-text').innerHTML = dict['referencesText']; + } +}; \ No newline at end of file diff --git a/js/ui_state/components/advanced_options.js b/js/ui_state/components/advanced_options.js new file mode 100644 index 0000000000000000000000000000000000000000..0fd1928253dc7998846f8bcb1f3d438d010f0d79 --- /dev/null +++ b/js/ui_state/components/advanced_options.js @@ -0,0 +1,83 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for advanced options. + */ +export default class AdvancedOptions extends Component { + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#advancedOptions'), + eventName: 'advancedOptionsChange' + }); + } + + /** + * Renders the advanced options UI elements. + */ + render() { + + const state = store.state.advancedOptionsState; + + let dict = window.lang_dict[store.state.language]['advancedOptions']; + + /* Rendering Options */ + this.element.querySelector('#renderingOptionsTitle').innerHTML = dict['renderingOptions']; + + + let drawJointsSwitch = this.element.querySelector('#drawJointsSwitch'); + let drawLidarsSwitch = this.element.querySelector('#drawLidarsSwitch'); + let drawNamesSwitch = this.element.querySelector('#drawNamesSwitch'); + let drawObservationSwitch = this.element.querySelector('#drawObservationSwitch'); + let drawRewardSwitch = this.element.querySelector('#drawRewardSwitch'); + + // Checks the draw switches + drawJointsSwitch.checked = state.drawJoints; + drawLidarsSwitch.checked = state.drawLidars; + drawNamesSwitch.checked = state.drawNames; + drawObservationSwitch.checked = state.drawObservation; + drawRewardSwitch.checked = state.drawReward; + + // Tooltips + drawJointsSwitch.title = dict['drawJointsTooltip']; + drawLidarsSwitch.title = dict['drawLidarsTooltip']; + drawNamesSwitch.title = dict['drawNamesTooltip']; + drawObservationSwitch.title = dict['drawObservationTooltip']; + drawRewardSwitch.title = dict['drawRewardTooltip']; + + // Switches labels + this.element.querySelector('#drawJointsLabel').innerText = dict['drawJoints']; + this.element.querySelector('#drawLidarsLabel').innerText = dict['drawLidars']; + this.element.querySelector('#drawNamesLabel').innerText = dict['drawNames']; + this.element.querySelector('#drawObservationLabel').innerText = dict['drawObservation']; + this.element.querySelector('#drawRewardLabel').innerText = dict['drawReward']; + + /* Assets */ + + this.element.querySelector('#assetsTitle').innerHTML = dict['assetsTitle']; + this.element.querySelector('#assetsText').innerText = dict['assetsText']; + this.element.querySelector('#comingSoon').innerText = dict['comingSoon']; + + // Renders the assets buttons + let circleAssetButton = this.element.querySelector('#circleAssetButton'); + circleAssetButton.innerHTML = dict['circle']; + if(state.assets.circle){ + circleAssetButton.className = "btn btn-asset"; + } + else{ + circleAssetButton.className = "btn btn-outline-asset"; + } + + /* Initializes tooltips */ + this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + return new bootstrap.Tooltip(el, { + trigger: 'hover' + }); + }); + } +}; \ No newline at end of file diff --git a/js/ui_state/components/agents_list.js b/js/ui_state/components/agents_list.js new file mode 100644 index 0000000000000000000000000000000000000000..dc97ca2c532e71010f3d00901f739f19a6bc267c --- /dev/null +++ b/js/ui_state/components/agents_list.js @@ -0,0 +1,134 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +const thumbnails_path = "images/agents_thumbnails/"; + +/** + * @classdesc UI component for the list of running agents. + */ +export default class AgentsList extends Component { + constructor() { + super({ + store, + element: document.querySelector('#agents_list_container'), + eventName: 'agentsListChange' + }); + } + + /** + * Renders the list of running agents and adds event listeners to the different elements. + */ + render() { + let dict = window.lang_dict[store.state.language]['agentsList']; + let morph_dict = window.lang_dict[store.state.language]['morphologies']; + this.element.querySelector('#agents_list_title').innerHTML = `${dict['title']}`; + this.element.querySelector('#agents_list').innerHTML = store.state.agents.map(agent => { + let age = agent.age == "adult" ? "" : " (" + window.lang_dict[window.get_language()]['morphologies'][agent.age] + ")"; + // Creates a list item for each agent + return `
    • + + + ${agent.morphology + + +
      + +
      + + + +
      + +
      + + +
      + + +
      + + + +
    • `; + }).join(''); + + // Renders the list items differently when drawing or if the agent is selected + this.element.querySelectorAll('li[name="agent-list-item"]').forEach((span, index) => { + if(store.state.drawingModeState.drawing){ + span.classList.add('disabled'); + } + else{ + if(store.state.agents[index] == store.state.simulationState.agentSelected){ + span.classList.add("active"); + } + else{ + span.classList.remove("active"); + } + } + }); + + /* EVENT LISTENERS */ + + // Deletes the agent + this.element.querySelectorAll('button[name="deleteButton"]').forEach((span, index) => { + span.addEventListener('click', () => { + store.dispatch('deleteAgent', {index: index}); + }); + }); + + // Saves the agent's current position as initial position + this.element.querySelectorAll('button[name="savePositionButton"]').forEach((span, index) => { + span.addEventListener('click', () => { + let pos = window.game.env.agents[index].agent_body.reference_head_object.GetPosition().Clone(); + store.dispatch('setAgentInitPos', {index: index, init_pos: pos}); + }); + }); + + // Resets the agent's initial position + this.element.querySelectorAll('button[name="resetPositionButton"]').forEach((span, index) => { + span.addEventListener('click', () => { + store.dispatch('setAgentInitPos', {index: index, init_pos: null}); + let init_x = TERRAIN_STEP * INITIAL_TERRAIN_STARTPAD / 2; + window.game.env.set_agent_position(window.game.env.agents[index], init_x, null); + window.game.env.render(); + }); + }); + + // Follows the agent + this.element.querySelectorAll('input[name="followSwitch"]').forEach((span, index) => { + span.addEventListener('input', () => { + store.dispatch('followAgent', {index: span.checked ? index : -1}); + }); + span.checked = store.state.simulationState.agentFollowed == store.state.agents[index]; + }); + + // Renames the agent + this.element.querySelectorAll('input[name="agentNameArea"]').forEach((span, index) => { + span.addEventListener('keydown', (event) => { + if(event.keyCode == '13'){ + store.dispatch('renameAgent', {index: index, value: span.value}); + } + }); + }); + + /* Initializes tooltips */ + this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + return new bootstrap.Tooltip(el, { + trigger: 'hover' + }); + }); + } +}; \ No newline at end of file diff --git a/js/ui_state/components/drawing_mode.js b/js/ui_state/components/drawing_mode.js new file mode 100644 index 0000000000000000000000000000000000000000..de71272087fa85a9f376e40854786e741c157c38 --- /dev/null +++ b/js/ui_state/components/drawing_mode.js @@ -0,0 +1,72 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for the drawing mode buttons. + */ +export default class DrawingMode extends Component { + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#draw-tab'), + eventName: 'drawingModeChange' + }); + } + + /** + * Renders the drawing mode buttons. + */ + render() { + const state = store.state.drawingModeState; + const dict = window.lang_dict[store.state.language]['drawingMode']; + + let drawGroundButton = this.element.querySelector('#drawGroundButton'); + let drawCeilingButton = this.element.querySelector('#drawCeilingButton'); + let eraseButton = this.element.querySelector('#eraseButton'); + let clearButton = this.element.querySelector('#clearButton'); + let generateTerrainButton = this.element.querySelector('#generateTerrainButton'); + + this.element.querySelector('#drawingIntro').innerHTML = dict['intro']; + this.element.querySelector('#drawingText').innerHTML = dict['text']; + + drawGroundButton.innerHTML = ` ${dict['ground']}`; + drawCeilingButton.innerHTML = ` ${dict['ceiling']}`; + eraseButton.innerHTML = ` ${dict['erase']}`; + clearButton.innerHTML = ` ${dict['clear']}`; + + // Enables the buttons when drawing mode is active + if(state.drawing){ + + drawGroundButton.className = "btn btn-outline-success"; + drawCeilingButton.className = "btn btn-outline-secondary"; + eraseButton.className = "btn btn-outline-warning"; + + // Fills the button corresponding to the current drawing mode + if(state.drawing_ground){ + drawGroundButton.className = "btn btn-success"; + } + else if(state.drawing_ceiling){ + drawCeilingButton.className = "btn btn-secondary"; + } + else if(state.erasing){ + eraseButton.className = "btn btn-warning"; + } + + generateTerrainButton.className = "btn btn-success"; + generateTerrainButton.innerText = dict['generateTerrain']; + } + + // Disables drawing buttons when drawing mode is inactive + else{ + drawGroundButton.className = "btn btn-outline-success disabled"; + drawCeilingButton.className = "btn btn-outline-secondary disabled"; + eraseButton.className = "btn btn-outline-warning disabled"; + + generateTerrainButton.className = "btn btn-primary"; + generateTerrainButton.innerText = dict['draw']; + } + } +}; \ No newline at end of file diff --git a/js/ui_state/components/envs_set.js b/js/ui_state/components/envs_set.js new file mode 100644 index 0000000000000000000000000000000000000000..4b42db5d72d25ac48870c84918407471d09e60a1 --- /dev/null +++ b/js/ui_state/components/envs_set.js @@ -0,0 +1,148 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for the sets of environments. + */ +export default class EnvsSet extends Component{ + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#getting-started-tab'), + eventName: 'envsSetChange' + }); + } + + /** + * Renders the sets of environments and adds event listeners to the different elements. + */ + render(){ + let dict = window.lang_dict[store.state.language]['envsSets']; + + this.element.querySelector('#baseSetText').innerHTML = dict['baseSetText']; + this.element.querySelector('#customSetText').innerHTML = dict['customSetText']; + + /* Base envs set */ + let baseEnvs = this.element.querySelector('#baseEnvsSet'); + + baseEnvs.innerHTML = store.state.envsSets.baseEnvsSet.map(e => { + // Creates a card for each environment in the base set + return `
      +
      + + + ${e.description.name} + + +
      +

      ${e.description[store.state.language]['name']}

      +

      ${e.description[store.state.language]['text']}

      +
      +
      +
      ` + }).join(''); + + /* Custom envs set */ + let customEnvs = this.element.querySelector('#customEnvsSet'); + + // Creates a special card for uploading files + let uploadCard = `
      +
      +
      +

      ${dict['uploadCard']['title']}

      +

      ${dict['uploadCard']['text']}

      +
      + +
      +
      + +
      +
      `; + + let envCards = store.state.envsSets.customEnvsSet.map((e, index) => { + // Creates a card for each environment in the custom set + return `
      +
      + + + ${e.description.name} + + +
      +

      ${e.description.name}

      +

      ${e.description.text}

      +
      + + + +
      +
      ` + }).join(''); + + customEnvs.innerHTML = [uploadCard, envCards].join(''); + + /* EVENT LISTENERS */ + + // Loads a base environment + baseEnvs.querySelectorAll('div[name="env-card"]').forEach((span, index) => { + span.addEventListener('click', () => { + store.dispatch('loadEnv', store.state.envsSets.baseEnvsSet[index]); + }) + }); + + // Loads a custom environment + customEnvs.querySelectorAll('div[name="env-card"]').forEach((span, index) => { + span.addEventListener('click', () => { + store.dispatch('loadEnv', store.state.envsSets.customEnvsSet[index]); + }) + }); + + // Parses the uploaded file and adds the corresponding environment to the custom set + customEnvs.querySelector('#uploadEnvBtn').addEventListener('click', () => { + let reader = new FileReader(); + reader.addEventListener('load', () => { + let env = JSON.parse(reader.result); + store.dispatch('addEnv',{set: 'custom', env: env}); + }); + let file = customEnvs.querySelector('#uploadEnvFile').files[0]; + if(file != null){ + reader.readAsText(file); + } + }); + + // Downloads a custom environment + customEnvs.querySelectorAll('button[name="downloadEnvBtn"]').forEach((span, index) => { + span.addEventListener('click', () => { + downloadObjectAsJson(store.state.envsSets.customEnvsSet[index], store.state.envsSets.customEnvsSet[index].description.name.split(' ').join('_')); + }) + }); + + // Deletes a custom environment + customEnvs.querySelectorAll('button[name="deleteEnvBtn"]').forEach((span, index) => { + span.addEventListener('click', () => { + store.dispatch('deleteEnv', index); + }) + }); + + /* Initializes tooltips */ + this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + return new bootstrap.Tooltip(el, { + trigger: 'hover' + }); + }); + } +}; \ No newline at end of file diff --git a/js/ui_state/components/global_elements.js b/js/ui_state/components/global_elements.js new file mode 100644 index 0000000000000000000000000000000000000000..4981d77acddb21fb08cd498587a1207997df3656 --- /dev/null +++ b/js/ui_state/components/global_elements.js @@ -0,0 +1,47 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for global elements. + */ +export default class GlobalElements extends Component{ + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.body, + eventName: 'globalElementsChange' + }); + } + + /** + * Renders the global UI elements. + */ + render() { + let dict = window.lang_dict[store.state.language]['globalElements']; + + // Title + this.element.querySelector('#demoTitle').innerText = dict['demoTitle']; + + // Tabs buttons + this.element.querySelector('#getting-started-btn').innerText = dict['gettingStarted']; + this.element.querySelector('#parkour-custom-btn').innerText = dict['parkourCustomization']; + this.element.querySelector('#advanced-options-btn').innerText = dict['advancedOptions']; + this.element.querySelector('#about-btn').innerHTML = ` ${dict['about']}`; + + // Changes the selected index of the language dropdown + this.element.querySelector('#langSelect').selectedIndex = store.state.language == 'EN' ? 0 : 1; + + // Save env modal + let modal = this.element.querySelector('#saveEnvModal'); + modal.querySelector('#save-modal-title').innerHTML = dict['saveEnvModal']['title']; + modal.querySelector('#save-modal-text').innerText = dict['saveEnvModal']['text']; + modal.querySelector('#env-name-label').innerText = dict['saveEnvModal']['nameLabel']; + modal.querySelector('#env-description-label').innerText = dict['saveEnvModal']['descriptionLabel']; + modal.querySelector('#save-cancel-btn').innerText = dict['saveEnvModal']['cancelBtn']; + modal.querySelector('#save-confirm-btn').innerText = dict['saveEnvModal']['confirmBtn']; + } +}; \ No newline at end of file diff --git a/js/ui_state/components/main_buttons.js b/js/ui_state/components/main_buttons.js new file mode 100644 index 0000000000000000000000000000000000000000..7520de276f37497351d850659d270187c6a70c8c --- /dev/null +++ b/js/ui_state/components/main_buttons.js @@ -0,0 +1,78 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for the main buttons. + */ +export default class MainButtons extends Component { + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#mainButtons'), + eventName: 'mainButtonsChange' + }); + } + + /** + * Renders the run, reset and save buttons. + */ + render() { + const status = store.state.simulationState.status; + + let runButton = this.element.querySelector("#runButton"); + let resetButton = this.element.querySelector("#resetButton"); + let saveEnvButton = this.element.querySelector('#saveEnvButton'); + + let dict = window.lang_dict[store.state.language]['mainButtons']; + + // Disables buttons while drawing + if(store.state.drawingModeState.drawing){ + runButton.className = "btn btn-success disabled"; + runButton.title = dict['runBtnTooltip']; + resetButton.className = "btn btn-danger disabled"; + saveEnvButton.className = "btn btn-primary mx-3 disabled"; + } + + // Enables buttons when not drawing + else{ + // Turns run button into pause button while running + if (status == 'running') { + runButton.className = "btn btn-warning"; + runButton.childNodes[0].classList.add("fa-pause"); + runButton.childNodes[0].classList.remove("fa-play"); + runButton.title = dict['pauseBtnTooltip']; + } + + // Turns pause button into run button when not running + else { + runButton.className = "btn btn-success"; + runButton.childNodes[0].classList.remove("fa-pause"); + runButton.childNodes[0].classList.add("fa-play"); + runButton.title = dict['runBtnTooltip']; + } + + // Disables save button during intro tour + if(store.state.simulationState.intro_tour){ + saveEnvButton.className = "btn btn-primary mx-3 disabled"; + } + else{ + saveEnvButton.className = "btn btn-primary mx-3"; + saveEnvButton.title = dict['saveBtnTooltip']; + } + + resetButton.className = "btn btn-danger"; + resetButton.title = dict['resetBtnTooltip']; + } + + /* Initializes tooltips */ + this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + return new bootstrap.Tooltip(el, { + trigger: 'hover' + }); + }); + } +}; \ No newline at end of file diff --git a/js/ui_state/components/morphologies_list.js b/js/ui_state/components/morphologies_list.js new file mode 100644 index 0000000000000000000000000000000000000000..fd61c80e9a8dfb99d98bada8884a7e925498b659 --- /dev/null +++ b/js/ui_state/components/morphologies_list.js @@ -0,0 +1,132 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +const thumbnails_path = "images/agents_thumbnails/"; + +/** + * @classdesc UI component for the list of morphologies. + */ +export default class MorphologiesList extends Component { + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#agents-selection'), + eventName: 'morphologiesChange' + }); + } + + /** + * Renders the list of morphologies and adds event listeners for the different elements. + */ + render() { + + let dict = window.lang_dict[store.state.language]['morphologies']; + + this.element.querySelector('#agents-selection-title').innerHTML = dict['title']; + this.element.querySelector('#agents-selection-text').innerText = dict['text']; + + this.element.querySelector('#morphologies-list').innerHTML = store.state.morphologies.map(m => { + // Creates a list item for each morphology + return `
    • + +
      +
      + + ${m.morphology +
      + +
      + + + + +
      + +
      + +
      +
      +
      +
      +
    • ` + }).join(''); + + // Renders the list items differently when drawing + if (store.state.drawingModeState.drawing) { + this.element.querySelectorAll('li[name="morph-list-item"]').forEach((span, index) => { + span.classList.add('disabled'); + }); + } + + /* EVENT LISTENERS */ + + // Adds all the compatible policies as options to the dropdown + this.element.querySelectorAll('select[name="policies"]').forEach((span, index) => { + + // Dict that contains HTML code for each optgroup corresponding to each agent name + let seed_names = {}; + + store.state.morphologies + .filter(m => m.morphology == store.state.morphologies[index].morphology) + .flatMap(morphology => morphology.seeds) + .map((seedEntry, idx) => { + + // Splits seed name between name and age + let seed = seedEntry.name.split('/'); + let name = seed[0]; + let age = seed[1]; + + // Adds options and optgroups + if(seed_names.hasOwnProperty(name)){ + seed_names[name] += ``; + + } + else { + seed_names[name] = ` + `; + } + }); + let options = []; + for(let name in seed_names){ + seed_names[name] += ``; + options.push(seed_names[name]); + } + span.innerHTML = options.join(``); + + // Selects a policy option + span.addEventListener('input', evt => { + store.dispatch('selectSeedIdx', {morphology: store.state.morphologies[index].morphology, index: span.selectedIndex}); + }); + + span.selectedIndex = store.state.currentSeedsIdx[store.state.morphologies[index].morphology]; + }); + + // Adds an agent to the environment with the corresponding morphology and the current policy selected + this.element.querySelectorAll('button[name="addAgentButton"]').forEach((span, index) => { + span.addEventListener('click', () => { + let morph = store.state.morphologies[index]; + let seed = morph.seeds[store.state.currentSeedsIdx[morph.morphology]].name.split('/'); + store.dispatch('addAgent', { + morphology: morph.morphology, + name: seed[0], + age: seed[1], + path: morph.seeds[store.state.currentSeedsIdx[morph.morphology]].path, + init_pos: null + }); + }); + }); + + /* Initializes tooltips */ + this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { + return new bootstrap.Tooltip(el, { + trigger: 'hover' + }); + }); + } +}; \ No newline at end of file diff --git a/js/ui_state/components/parkour_config.js b/js/ui_state/components/parkour_config.js new file mode 100644 index 0000000000000000000000000000000000000000..07909fe35eb4aef278fd4ac1d8fca9ceb2619571 --- /dev/null +++ b/js/ui_state/components/parkour_config.js @@ -0,0 +1,79 @@ +import Component from '../lib/component.js'; +import store from '../store/index.js'; + +/** + * @classdesc UI component for the parkour parameters. + */ +export default class ParkourConfig extends Component { + + /** + * @constructor + */ + constructor() { + super({ + store, + element: document.querySelector('#parkour-custom-tab'), + eventName: 'parkourConfigChange' + }); + } + + /** + * Renders the parkour parameters. + */ + render() { + + // TERRAIN CONFIG + const terrainConfig = store.state.parkourConfig.terrain; + let dict = window.lang_dict[store.state.language]['parkourConfig']; + + // Sections titles + this.element.querySelector('#terrain-generation-title').innerHTML = dict['terrainGeneration']; + this.element.querySelector('#general-parameters-title').innerText = dict['generalParameters']; + this.element.querySelector('#creepers-title').innerText = dict['creepers']; + + // Terrain generation tabs buttons + this.element.querySelector('#draw-tab-btn').innerText = dict['drawTabBtn']; + this.element.querySelector('#proc-gen-tab-btn').innerText = dict['procGenTabBtn']; + + // Procedural Generation text + this.element.querySelector('#proc-gen-text').innerHTML = dict['procGenText']; + + // Parameters labels + this.element.querySelector('#smoothing-label').innerText = dict['smoothing']; + this.element.querySelector('#water-level-label').innerText = dict['waterLevel']; + this.element.querySelector('#creepers-width-label').innerText = dict['creepersWidth']; + this.element.querySelector('#creepers-height-label').innerText = dict['creepersHeight']; + this.element.querySelector('#creepers-spacing-label').innerText = dict['creepersSpacing']; + //this.element.querySelector('#creepers-type-label').innerText = dict['creepersType']; + + this.element.querySelector('#rigid-otpion').innerText = dict['rigid']; + this.element.querySelector('#swingable-option').innerText = dict['swingable']; + + // Sliders values + this.element.querySelector("#dim1Slider").value = terrainConfig.dim1; + this.element.querySelector("#dim2Slider").value = terrainConfig.dim2; + this.element.querySelector("#dim3Slider").value = terrainConfig.dim3; + this.element.querySelector("#smoothingSlider").value = terrainConfig.smoothing; + this.element.querySelector("#waterSlider").value = terrainConfig.waterLevel; + + // Sliders text values + this.element.querySelector("#dim1Value").innerText = terrainConfig.dim1; + this.element.querySelector("#dim2Value").innerText = terrainConfig.dim2; + this.element.querySelector("#dim3Value").innerText = terrainConfig.dim3; + this.element.querySelector("#smoothingValue").innerText = terrainConfig.smoothing; + this.element.querySelector("#waterValue").innerText = terrainConfig.waterLevel; + + // CREEPERS CONFIG + const creepersConfig = store.state.parkourConfig.creepers; + + this.element.querySelector("#creepersWidthSlider").value = creepersConfig.width; + this.element.querySelector("#creepersHeightSlider").value = creepersConfig.height; + this.element.querySelector("#creepersSpacingSlider").value = creepersConfig.spacing; + + this.element.querySelector("#creepersWidthValue").innerText = creepersConfig.width; + this.element.querySelector("#creepersHeightValue").innerText = creepersConfig.height; + this.element.querySelector("#creepersSpacingValue").innerText = creepersConfig.spacing; + + this.element.querySelector("#creepersType").value = creepersConfig.type; + } +}; \ No newline at end of file diff --git a/js/ui_state/lib/component.js b/js/ui_state/lib/component.js new file mode 100644 index 0000000000000000000000000000000000000000..9b21cfe951f3395217089980ce7106a74f2c6881 --- /dev/null +++ b/js/ui_state/lib/component.js @@ -0,0 +1,23 @@ +import Store from '../store/store.js'; + +/** + * @classdesc Abstract class for UI components. + */ +export default class Component { + + /** + * @constructor + * @param props {{store: Store, element: HTMLElement, eventName: string}} + */ + constructor(props = {}) { + this.render = this.render || function () { }; + + // Adds props.eventName with this.render() as callback function to the list of events handled by the UI state manager + if (props.store instanceof Store) { + props.store.events.subscribe(props.eventName, () => this.render()); + } + if (props.hasOwnProperty('element')) { + this.element = props.element; + } + } +} \ No newline at end of file diff --git a/js/ui_state/lib/pubsub.js b/js/ui_state/lib/pubsub.js new file mode 100644 index 0000000000000000000000000000000000000000..7b96c3bad247634ac891b82ae42271e4fef912a4 --- /dev/null +++ b/js/ui_state/lib/pubsub.js @@ -0,0 +1,37 @@ +/** + * @classdesc UI state manager. + */ +export default class PubSub { + /** + * @constructor + */ + constructor() { + this.events = {}; + } + + /** + * Adds the given callback function to the given event and adds the event to the handled events if it is not in it yet. + * @param event {string} + * @param callback {function} + * @return {number} + */ + subscribe(event, callback) { + if (!this.events.hasOwnProperty(event)) { + this.events[event] = []; + } + return this.events[event].push(callback); + } + + /** + * Triggers all the callback functions for the given event. + * @param event {string} + * @param data + * @return {*[]|*} + */ + publish(event, data = {}) { + if (!this.events.hasOwnProperty(event)) { + return []; + } + return this.events[event].map(callback => callback(data)); + } +} \ No newline at end of file diff --git a/js/ui_state/store/actions.js b/js/ui_state/store/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..7ebe415c432a7163787d31442519765b67f795c3 --- /dev/null +++ b/js/ui_state/store/actions.js @@ -0,0 +1,399 @@ +// All available actions +export default { + + /** + * Adds the given environment to the specified set. + * @param context {Store} + * @param payload {{set: string, env: Object}} + */ + addEnv(context, payload){ + context.commit('addEnv', payload); + }, + + /** + * Removes the environment of the given index from the custom set. + * @param context {Store} + * @param payload {number} - Index of the environment to remove + */ + deleteEnv(context, payload){ + context.commit('deleteEnv', payload); + }, + + /** + * Loads the given environment into the simulation. + * @param context {Store} + * @param payload {Object} - Environment to load + */ + loadEnv(context, payload){ + + // Resets drawing mode + drawing_canvas.clear(); + window.terrain = { + ground: [], + ceiling: [] + }; + + window.ground = [...payload.terrain.ground]; + window.ceiling = [...payload.terrain.ceiling]; + + // Updates the values of the terrain sliders + for(let param in payload.terrain.parkourConfig){ + context.commit('updateParkourConfig', {name: param, value: payload.terrain.parkourConfig[param]}); + } + for(let param in payload.terrain.creepersConfig){ + context.commit('updateParkourConfig', {name: param, value: payload.terrain.creepersConfig[param]}); + } + + // Replaces previous agents by the ones of the env + while (context.state.agents.length > 0){ + context.commit('deleteAgent', {index: 0}); + } + for(let agent of payload.agents){ + context.commit('addAgent', { + morphology: agent.morphology, + name: agent.name, + age: agent.age, + path: agent.path, + init_pos: agent.init_pos + }); + } + + // Initializes the new environment + context.commit('init_default', {}); + }, + + /** + * Initializes the game with default parameters. + * @param context {Store} + * @param payload + */ + init_default(context, payload) { + context.commit('init_default', {}); + }, + + /** + * Changes the value of the given terrain parameter. + * @param context {Store} + * @param payload {{name: string, value: number}} - Name and value of the terrain parameter to change + */ + changeParkourConfig(context, payload){ + + // Case one of the cppn dims is changed : aligns the terrain with the startpad + if(['dim1', 'dim2', 'dim3'].indexOf(payload.name) != -1){ + + window.ground = []; + window.ceiling = []; + window.align_terrain = { + align: true, + ceiling_offset: null, // aligns the ceiling with the startpad + ground_offset: null, // aligns the ground with the startpad + smoothing: window.game.env.TERRAIN_CPPN_SCALE // previous smoothing + }; + } + // Case smoothing, water_level or creepers is changed + else{ + window.align_terrain = { + align: true, + ceiling_offset: window.align_terrain.ceiling_offset, // keeps the same + ground_offset: window.align_terrain.ground_offset, // keeps the same + smoothing: window.game.env.TERRAIN_CPPN_SCALE // previous smoothing + }; + } + + // Updates the parameter + context.commit('updateParkourConfig', payload); + + // Generates the terrain if drawing mode is active + if(context.state.drawingModeState.drawing){ + context.commit('generateTerrain', true); + } + + // Resets drawing mode + drawing_canvas.clear(); + window.terrain = { + ground: [], + ceiling: [] + }; + + // Resets the simulation and deselects agent + context.commit('resetSimulation', {keepPositions: true}); + context.commit('selectAgent', -1); + }, + + /** + * Changes the value of the given switch parameter. + * @param context {Store} + * @param payload {{name: string, value: number}} - Name and value of the switch to toggle + */ + toggleSwitch(context, payload) { + switch (payload.name) { + case 'drawJoints': + context.commit('drawJoints', payload.value); + break; + case 'drawLidars': + context.commit('drawLidars', payload.value); + break; + case 'drawNames': + context.commit('drawNames', payload.value); + break; + case 'drawObservation': + context.commit('drawObservation', payload.value); + break; + case 'drawReward': + context.commit('drawReward', payload.value); + break; + } + }, + + /** + * Changes the status of the simulation. + * @param context {Store} + * @param payload {} + */ + toggleRun(context, payload) { + const status = context.state.simulationState.status; + switch (status) { + case 'init': + context.commit('startSimulation', {}); + break; + case 'running': + context.commit('pauseSimulation', {}); + break; + case 'paused': + context.commit('startSimulation', {}); + break; + } + }, + + /** + * Resets the simulation. + * @param context {Store} + * @param payload {} + */ + resetSimulation(context, payload) { + // Updates the terrain alignment + window.align_terrain = { + align: true, // aligns the terrain with the startpad + ceiling_offset: window.ceiling.length > 0 ? window.game.env.ceiling_offset - window.ceiling[0].y : null, + ground_offset: window.ground.length > 0 ? window.ground[0].y : null, // first ground y value + smoothing: window.game.env.TERRAIN_CPPN_SCALE // smoothing of the current terrain + }; + + context.commit('selectAgent', {index: -1}); + context.commit('resetSimulation', {keepPositions: false}); + }, + + /** + * Adds the given agent to the simulation. + * @param context {Store} + * @param payload {{morphology: string, name: string, path: string, init_pos: {x: number, y: number}}} + */ + addAgent(context, payload) { + // Pauses the simulation if it is running + if (context.state.simulationState.status == 'running') { + context.commit('pauseSimulation', {}); + } + context.commit('addAgent', payload); + }, + + /** + * Deletes the agent of the given index from the simulation. + * @param context {Store} + * @param payload {{index: number}} + */ + deleteAgent(context, payload) { + context.commit('deleteAgent', payload); + }, + + /** + * Sets the initial position of the agent of the given index. + * @param context {Store} + * @param payload {{index: number, init_pos: {x: number, y: number}}} + */ + setAgentInitPos(context, payload){ + context.commit('setAgentInitPos', payload); + }, + + /** + * Selects the agent of the given index. + * @param context {Store} + * @param payload {{index: number}} + */ + selectAgent(context, payload){ + context.commit('selectAgent', payload); + }, + + /** + * Follows or not the agent of the given index according to the given boolean. + * @param context {Store} + * @param payload {{index: number, value: boolean}} + */ + followAgent(context, payload) { + context.commit('followAgent', payload); + }, + + /** + * Renames the agent of the given index with the given string value. + * @param context {Store} + * @param payload {{index: number, value: string}} + */ + renameAgent(context, payload){ + context.commit('renameAgent', payload); + }, + + /** + * Selects the seed option of the given index for the given morphology. + * @param context {Store} + * @param payload {{morphology: string, index: number}} + */ + selectSeedIdx(context, payload) { + context.commit('selectSeedIdx', payload); + }, + + /** + * Adds the given morphology with the given policy seeds to the list of morphologies. + * @param context {Store} + * @param payload {{morphology: string, seeds: []}} + */ + addMorphology(context, payload) { + context.commit('addMorphology', payload); + // Selects the first seed option + context.commit('selectSeedIdx', {morphology: payload.morphology, index: 0}); + }, + + /** + * Changes the active tab. + * @param context {Store} + * @param payload {string} - Name of the tab to activate + */ + switchTab(context, payload) { + + // Switch from 'Draw Yourself!' to another tab + if(context.state.activeTab == 'draw_yourself'){ + if(payload != 'draw_yourself' && context.state.drawingModeState.drawing) { + // Generates the terrain from the drawing + context.commit('generateTerrain', true); + } + } + // Switch to 'Draw Yourself!' from another tab + else if(payload == 'draw_yourself'){ + // Generates the drawing from the terrain + context.commit('generateTerrain', false); + } + context.commit('switchTab', payload); + }, + + /** + * Activates or deactivates the ground drawing mode. + * @param context {Store} + * @param payload {boolean} + */ + drawGround(context, payload) { + context.commit('drawGround', payload); + }, + + /** + * Activates or deactivates the ceiling drawing mode. + * @param context {Store} + * @param payload {boolean} + */ + drawCeiling(context, payload) { + context.commit('drawCeiling', payload); + }, + + /** + * Activates or deactivates the erasing mode. + * @param context {Store} + * @param payload {boolean} + */ + erase(context, payload) { + context.commit('erase', payload); + }, + + /** + * Activates or deactivates the drawing mode of the given asset. + * @param context {Store} + * @param payload {{name: string, value: boolean}} + */ + drawAsset(context, payload){ + // Only supports circle asset for now + switch (payload.name){ + case 'circle': + context.commit('drawCircle', payload.value); + break; + } + }, + + /** + * Handles clicks outside the canvas when drawing. + * @param context {Store} + * @param payload {} + */ + deselectDrawingButtons(context, payload){ + context.commit('deselectDrawingButtons', payload); + }, + + /** + * Resets drawing mode. + * @param context {Store} + * @param payload {} + */ + clear(context, payload) { + context.commit('clear', payload); + context.commit('generateTerrain', false); + }, + + /** + * Generates the terrain from the drawing (true) or vice-versa (false). + * @param context {Store} + * @param payload {boolean} + */ + generateTerrain(context, payload){ + context.commit('generateTerrain', payload); + }, + + refreshDrawing(context, payload){ + context.commit('refreshDrawing', payload); + }, + + /** + * Starts (true) or exits (false) intro tour. + * @param context {Store} + * @param payload {boolean} + */ + setIntroTour(context, payload){ + context.commit('setIntroTour', payload); + }, + + /** + * Sets the language. + * @param context {Store} + * @param payload {string} + */ + setLanguage(context, payload){ + context.commit('setLanguage', payload); + + // Resets the hints options of the intro + if(window.introTour != null){ + window.introTour.setOptions({ + hintButtonLabel: window.lang_dict[context.state.language]['introHints']['buttonLabel'], + hints: [ + { + hint: window.lang_dict[context.state.language]['introHints']['tips'], + element: document.querySelector('#canvas_container'), + hintPosition: 'top-right', + } + ] + }); + + // Removes the div element of the hints + let introDiv = document.getElementsByClassName("introjs-hints")[0]; + introDiv.parentNode.removeChild(introDiv); + + // Recreates the hints + window.introTour.addHints(); + } + + window.game.env.render(); + } +}; \ No newline at end of file diff --git a/js/ui_state/store/index.js b/js/ui_state/store/index.js new file mode 100644 index 0000000000000000000000000000000000000000..bacf082323b9fd06ad0e81e805c8c9e8be40936f --- /dev/null +++ b/js/ui_state/store/index.js @@ -0,0 +1,10 @@ +import actions from './actions.js'; +import mutations from './mutations.js'; +import state from './state.js'; +import Store from './store.js'; + +export default new Store({ + actions, + mutations, + state +}); \ No newline at end of file diff --git a/js/ui_state/store/mutations.js b/js/ui_state/store/mutations.js new file mode 100644 index 0000000000000000000000000000000000000000..5ad6847bcf584e02ab0e18de432e778c442a6c20 --- /dev/null +++ b/js/ui_state/store/mutations.js @@ -0,0 +1,712 @@ +// All available UI state mutations +export default { + + /** + * Adds the given environment to the specified set. + * @param state {Object} - UI state + * @param payload {{set: string, env: Object}} + * @return {Object} - UI state + */ + addEnv(state, payload){ + if(payload.set == 'base'){ + state.envsSets.baseEnvsSet.push(payload.env); + } + else if(payload.set == 'custom'){ + state.envsSets.customEnvsSet.push(payload.env); + } + + // Sorts the set in the lexicographic order according to the name of the envs + state.envsSets.baseEnvsSet.sort(function(a, b){ + + // Exception for env whose name begins with "Flat": always first + if(a.description["EN"].name.split(" ")[0] == "Flat"){ + return -1; + } + else if(b.description["EN"].name.split(" ")[0] == "Flat"){ + return 1; + } + else{ + return a.description["EN"].name.localeCompare(b.description["EN"].name); + } + }); + return state; + }, + + /** + * Removes the environment of the given index from the custom set. + * @param state {Object} - UI state + * @param payload {number} - Index of the environment to remove + * @return {Object} - UI state + */ + deleteEnv(state, payload){ + state.envsSets.customEnvsSet.splice(payload, 1); + return state; + }, + + /** + * Updates the given terrain parameter. + * @param state {Object} - UI state + * @param payload {{name: string, value: number}} - Name and value of the terrain parameter to change + * @return {Object} - UI state + */ + updateParkourConfig(state, payload){ + switch (payload.name) { + case 'dim1': + state.parkourConfig.terrain.dim1 = payload.value; + break; + case 'dim2': + state.parkourConfig.terrain.dim2 = payload.value; + break; + case 'dim3': + state.parkourConfig.terrain.dim3 = payload.value; + break; + case 'smoothing': + state.parkourConfig.terrain.smoothing = payload.value; + break; + case 'waterLevel': + state.parkourConfig.terrain.waterLevel = payload.value; + break; + case 'width': + state.parkourConfig.creepers.width = payload.value; + break; + case 'height': + state.parkourConfig.creepers.height = payload.value; + break; + case 'spacing': + state.parkourConfig.creepers.spacing = payload.value; + break; + case 'type': + state.parkourConfig.creepers.type = payload.value; + break; + } + return state; + }, + + /** + * Initializes the game with default parameters. + * @param state {Object} - UI state + * @param payload {} + * @return {Object} - UI state + */ + init_default(state, payload){ + state.simulationState.status = 'init'; + + if(window.game != null){ + window.align_terrain = { + align: false, // no alignment + ceiling_offset: window.ceiling.length > 0 ? window.game.env.ceiling_offset - window.ceiling[0].y : null, + ground_offset: window.ground.length > 0 ? window.ground[0].y : null, // first ground y value + smoothing: window.game.env.TERRAIN_CPPN_SCALE // current smoothing + }; + } + + let terrainConfig = state.parkourConfig.terrain; + let creepersConfig = state.parkourConfig.creepers; + init_game( + [terrainConfig.dim1, terrainConfig.dim2, terrainConfig.dim3], + terrainConfig.waterLevel, + creepersConfig.width, + creepersConfig.height, + creepersConfig.spacing, + terrainConfig.smoothing, + creepersConfig.type == 'Swingable', + window.ground, + window.ceiling, + window.align_terrain + ); + }, + + /** + * Runs the simulation. + * @param state {Object} - UI state + * @param payload {} + * @return {Object} - UI state + */ + startSimulation(state, payload) { + state.simulationState.status = 'running'; + window.game.run(); + return state; + }, + + /** + * Pauses the simulation. + * @param state {Object} - UI state + * @param payload {} + * @return {Object} - UI state + */ + pauseSimulation(state, payload) { + window.game.pause(); + state.simulationState.status = 'paused'; + return state; + }, + + /** + * Resets the simulation. + * @param state {Object} - UI state + * @param payload {{keepPositions: boolean}} + * @return {Object} - UI state + */ + resetSimulation(state, payload) { + state.simulationState.status = 'init'; + + // Gets the morphology, policy and position of the current running agents + const agents = { + morphologies: state.agents.map(a => a.morphology), + policies: state.agents.map(a => { + return { + name: a.name, + age: a.age, + path: a.path + }; + }), + positions: [] + } + // Gets the current position of each agent + if (payload.keepPositions) { + agents.positions = [...state.agents.map((agent, index) => window.game.env.agents[index].agent_body.reference_head_object.GetPosition())]; + } + // Gets the initial position of each agent + else { + agents.positions = [...state.agents.map((agent, index) => window.game.env.agents[index].init_pos)]; + } + + const terrainConfig = state.parkourConfig.terrain; + const creepersConfig = state.parkourConfig.creepers; + + // Updates the terrain alignment + window.align_terrain = { + align: true, // aligns the terrain with the startpad + ceiling_offset: window.align_terrain.ceiling_offset, // keeps the same + ground_offset: window.align_terrain.ground_offset, // keeps the same + smoothing: window.game.env.TERRAIN_CPPN_SCALE // smoothing of the current terrain + }; + + // Reinitializes the environment + window.game.reset( + agents, + [terrainConfig.dim1,terrainConfig.dim2,terrainConfig.dim3], + terrainConfig.waterLevel, + creepersConfig.width, + creepersConfig.height, + creepersConfig.spacing, + terrainConfig.smoothing, + creepersConfig.type == "Swingable", + window.ground, + window.ceiling, + window.align_terrain); + return state; + }, + + /** + * Adds the given agent to the environment and renders it. + * @param state {Object} - UI state + * @param payload {{morphology: string, name: string, age: string, path: string, init_pos: {x: number, y: number}}} + * @return {Object} - UI state + */ + addAgent(state, payload) { + state.agents.push(payload); + if(window.game != null){ + window.game.env.add_agent(payload.morphology, {name: payload.name, age: payload.age, path: payload.path}, payload.init_pos); + window.game.env.render(); + } + return state; + }, + + /** + * Removes the agent of the given index from environment and renders it. + * @param state {Object} - UI state + * @param payload {{index: number}} + * @return {Object} - UI state + */ + deleteAgent(state, payload) { + state.agents.splice(payload.index, 1); + if(window.game != null){ + window.game.env.delete_agent(payload.index); + window.game.env.render(); + } + return state; + }, + + /** + * Sets the initial position of the agent of the given index. + * @param state {Object} - UI state + * @param payload {{index: number, init_pos: {x: number, y: number}}} + * @return {Object} - UI state + */ + setAgentInitPos(state, payload){ + window.game.env.agents[payload.index].init_pos = payload.init_pos; + state.agents[payload.index].init_pos = payload.init_pos; + return state; + }, + + /** + * Selects the agent of the given index. + * @param state {Object} - UI state + * @param payload {{index: number}} + * @return {Object} - UI state + */ + selectAgent(state, payload) { + if(payload.index != -1){ + window.agent_selected = window.game.env.agents[payload.index]; + state.simulationState.agentSelected = state.agents[payload.index]; + } + // Sets the selected agent to null if index == -1 + else{ + window.agent_selected = null; + state.simulationState.agentSelected = null; + } + return state; + }, + + /** + * Follows the agent of the given index and renders the environment. + * @param state {Object} - UI state + * @param payload {{index: number}} + * @return {Object} - UI state + */ + followAgent(state, payload) { + if(payload.index != -1){ + window.agent_followed = window.game.env.agents[payload.index]; + state.simulationState.agentFollowed = state.agents[payload.index]; + } + // Sets the followed agent to null if index == -1 + else { + window.agent_followed = null; + state.simulationState.agentFollowed = null; + } + window.game.env.render(); + return state; + }, + + /** + * Renames the agent of the given index with the given string value. + * @param state {Object} - UI state + * @param payload {{index: number, value: string}} + * @return {Object} - UI state + */ + renameAgent(state, payload) { + state.agents[payload.index].name = payload.value; + window.game.env.agents[payload.index].name = payload.value; + window.game.env.render(); + return state; + }, + + /** + * Selects the seed option of the given index for the given morphology. + * @param state {Object} - UI state + * @param payload {{morphology: string, index: number}} + * @return {Object} - UI state + */ + selectSeedIdx(state, payload) { + state.currentSeedsIdx[payload.morphology] = payload.index; + return state; + }, + + /** + * Adds the given morphology with the given policy seeds to the list of morphologies. + * @param state {Object} - UI state + * @param payload {{morphology: string, seeds: []}} + * @return {Object} - UI state + */ + addMorphology(state, payload) { + state.morphologies.push(payload); + // Sorts the list of morphologies in the lexicographic order according to the name of the morphology + state.morphologies.sort(function(a, b){ + return a.morphology.localeCompare(b.morphology); + }); + return state; + }, + + /** + * Changes the active tab. + * @param state {Object} - UI state + * @param payload {string} - Name of the active tab + * @return {Object} - UI state + */ + switchTab(state, payload) { + state.activeTab = payload; + return state; + }, + + /** + * Activates or deactivates the ground drawing mode. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawGround(state, payload){ + state.drawingModeState.drawing_ground = payload; + state.drawingModeState.drawing_ceiling = false; + state.drawingModeState.erasing = false; + state.advancedOptionsState.assets.circle = false; + return state; + }, + + /** + * Activates or deactivates the ceiling drawing mode. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawCeiling(state, payload){ + state.drawingModeState.drawing_ground = false; + state.drawingModeState.drawing_ceiling = payload; + state.drawingModeState.erasing = false; + state.advancedOptionsState.assets.circle = false; + return state; + }, + + /** + * Activates or deactivates the erasing mode. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + erase(state, payload){ + state.drawingModeState.drawing_ground = false; + state.drawingModeState.drawing_ceiling = false; + state.drawingModeState.erasing = payload; + state.advancedOptionsState.assets.circle = false; + return state; + }, + + /** + * + * @param state {Object} - UI state + * @param payload + * @return {Object} - UI state + */ + drawCircle(state, payload){ + state.drawingModeState.drawing_ground = false; + state.drawingModeState.drawing_ceiling = false; + state.drawingModeState.erasing = false; + state.advancedOptionsState.assets.circle = payload; + return state; + }, + + /** + * Deactivates all drawing and erasing modes. + * @param state {Object} - UI state + * @param payload {} + * @return {Object} - UI state + */ + deselectDrawingButtons(state, payload){ + state.drawingModeState.drawing_ground = false; + state.drawingModeState.drawing_ceiling = false; + state.drawingModeState.erasing = false; + state.advancedOptionsState.assets.circle = false; + return state; + }, + + /** + * Clears the drawing canvas and resets the drawing mode variables. + * @param state {Object} - UI state + * @param payload + * @return {Object} - UI state + */ + clear(state, payload){ + + drawing_canvas.clear(); + window.ground = []; + window.ceiling = []; + window.terrain = { + ground: [], + ceiling: [] + }; + return state; + }, + + /** + * Generates the terrain from the drawing (true) or vice-versa (false). + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + generateTerrain(state, payload){ + + state.drawingModeState.drawing = !payload; + state.simulationState.status = 'init'; + + // Generates the terrain from the shapes drawn + if(payload) { + + // Horizontally sorts the ground points that have been drawn + window.terrain.ground.sort(function (a, b) { + return a.x - b.x; + }); + window.ground = [...window.terrain.ground]; + + // Horizontally sorts the ceiling points that have been drawn + window.terrain.ceiling.sort(function (a, b) { + return a.x - b.x; + }); + window.ceiling = [...window.terrain.ceiling]; + + // Updates terrain alignment + window.align_terrain = { + align: false, // no alignment + ceiling_offset: window.ceiling.length > 0 ? window.game.env.ceiling_offset - window.ceiling[0].y : null, + ground_offset: window.ground.length > 0 ? window.ground[0].y : null, // first ground y value + smoothing: window.game.env.TERRAIN_CPPN_SCALE // current smoothing + }; + + let terrainConfig = state.parkourConfig.terrain; + let creepersConfig = state.parkourConfig.creepers; + init_game( + [terrainConfig.dim1, terrainConfig.dim2, terrainConfig.dim3], + terrainConfig.waterLevel, + creepersConfig.width, + creepersConfig.height, + creepersConfig.spacing, + terrainConfig.smoothing, + creepersConfig.type == 'Swingable', + window.ground, + window.ceiling, + window.align_terrain, + window.game.env.zoom, + window.game.env.scroll + ); + } + + // Generates the drawing from the terrain + else { + + // Draws the forbidden red area on the forbidden canvas + window.draw_forbidden_area(); + + // Clears the previous drawing + drawing_canvas.clear(); + window.terrain = { + ground: [], + ceiling: [] + }; + + // Draws the shape of the current ground + if(window.ground.length > 0){ + + for(let i = 0; i < window.ground.length - 1; i++){ + let p = window.ground[i]; + let p2 = window.ground[i + 1]; + let p_pos = convertPosEnvToCanvas(p.x, p.y); + let p2_pos = convertPosEnvToCanvas(p2.x, p2.y); + + drawing_canvas.stroke("#66994D"); + drawing_canvas.strokeWeight(4); + drawing_canvas.line( + p_pos.x, + p_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1], + p2_pos.x, + p2_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1] + ) + + window.terrain.ground.push({x: p.x, y: p.y}); + } + let p = window.ground[window.ground.length - 1]; + window.terrain.ground.push({x: p.x, y: p.y}); + } + + // Draws the shape of the current ceiling + if(window.ceiling.length > 0){ + + for(let i = 0; i < window.ceiling.length - 1; i++){ + let p = window.ceiling[i]; + let p2 = window.ceiling[i + 1]; + let p_pos = convertPosEnvToCanvas(p.x, p.y); + let p2_pos = convertPosEnvToCanvas(p2.x, p2.y); + + drawing_canvas.stroke("#808080"); + drawing_canvas.strokeWeight(4); + drawing_canvas.line( + p_pos.x, + p_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1], + p2_pos.x, + p2_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1] + ) + + window.terrain.ceiling.push({x: p.x, y: p.y}); + } + let p = window.ceiling[window.ceiling.length - 1]; + window.terrain.ceiling.push({x: p.x, y: p.y}); + } + + // Empties the ground and ceiling lists of points to create an empty environment with just the startpad. + window.ground = []; + window.ceiling = []; + + // Initializes the environment + let terrainConfig = state.parkourConfig.terrain; + let creepersConfig = state.parkourConfig.creepers; + init_game( + [terrainConfig.dim1, terrainConfig.dim2, terrainConfig.dim3], + terrainConfig.waterLevel, + creepersConfig.width, + creepersConfig.height, + creepersConfig.spacing, + terrainConfig.smoothing, + creepersConfig.type == 'Swingable', + window.ground, + window.ceiling, + window.align_terrain, + window.game.env.zoom, + window.game.env.scroll + ); + + // Displays the drawing and forbidden canvas on top of the main canvas + image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); + } + return state; + }, + + /** + * Re-draws the terrain shapes on the drawing canvas. + * @param state {Object} - UI state + * @param payload + * @return {Object} - UI state + */ + refreshDrawing(state, payload){ + + // Draws the forbidden red area on the forbidden canvas + window.draw_forbidden_area(); + + drawing_canvas.clear(); + + // Horizontally sorts the ground points that have been drawn + window.terrain.ground.sort(function (a, b) { + return a.x - b.x; + }); + + // Horizontally sorts the ceiling points that have been drawn + window.terrain.ceiling.sort(function (a, b) { + return a.x - b.x; + }); + + // Draws the ground ground + for(let i = 0; i < window.terrain.ground.length - 1; i++) { + let p = window.terrain.ground[i]; + let p2 = window.terrain.ground[i + 1]; + let p_pos = convertPosEnvToCanvas(p.x, p.y); + let p2_pos = convertPosEnvToCanvas(p2.x, p2.y); + + drawing_canvas.stroke("#66994D"); + drawing_canvas.strokeWeight(4); + drawing_canvas.line( + p_pos.x, + p_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1], + p2_pos.x, + p2_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1] + ) + } + + // Draws the ceiling + for(let i = 0; i < window.terrain.ceiling.length - 1; i++) { + let p = window.terrain.ceiling[i]; + let p2 = window.terrain.ceiling[i + 1]; + let p_pos = convertPosEnvToCanvas(p.x, p.y); + let p2_pos = convertPosEnvToCanvas(p2.x, p2.y); + + drawing_canvas.stroke("#808080"); + drawing_canvas.strokeWeight(4); + drawing_canvas.line( + p_pos.x, + p_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1], + p2_pos.x, + p2_pos.y + SCROLL_Y_MAX - window.game.env.scroll[1] + ) + } + + return state; + }, + + /** + * Draws or not all the joints of the environment and renders it. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawJoints(state, payload) { + state.advancedOptionsState.drawJoints = payload; + window.draw_joints = payload; + window.game.env.render(); + return state; + }, + + /** + * Draws or not all the lidars of the agents of the environment and renders it. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawLidars(state, payload) { + state.advancedOptionsState.drawLidars = payload; + window.draw_lidars = payload; + window.game.env.render(); + return state; + }, + + /** + * Draws or not all the names of the agents of the environment and renders it. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawNames(state, payload) { + state.advancedOptionsState.drawNames = payload; + window.draw_names = payload; + window.game.env.render(); + return state; + }, + + /** + * Draws or not the observation of the agents of the environment and renders it. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawObservation(state, payload) { + state.advancedOptionsState.drawObservation = payload; + window.draw_observation = payload; + window.game.env.render(); + return state; + }, + + /** + * Draws or not the reward of the agents of the environment and renders it. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + drawReward(state, payload) { + state.advancedOptionsState.drawReward = payload; + window.draw_reward = payload; + window.game.env.render(); + return state; + }, + + /** + * Starts (true) or exits (false) intro tour. + * @param state {Object} - UI state + * @param payload {boolean} + * @return {Object} - UI state + */ + setIntroTour(state, payload){ + state.simulationState.intro_tour = payload; + + // Shows the intro hints when exiting the guide tour + if(!payload){ + window.introTour.addHints(); + } + return state; + }, + + /** + * Sets the language. + * @param state {Object} - UI state + * @param payload {string} + * @return {Object} - UI state + */ + setLanguage(state, payload) { + state.language = payload; + return state; + } +}; \ No newline at end of file diff --git a/js/ui_state/store/state.js b/js/ui_state/store/state.js new file mode 100644 index 0000000000000000000000000000000000000000..5a9c8537f21c3ecfd8db5fc91691271ac73e8187 --- /dev/null +++ b/js/ui_state/store/state.js @@ -0,0 +1,49 @@ +// State of all UI elements +export default { + language: 'EN', // 'FR' + envsSets: { + baseEnvsSet: [], // list of environments of the base set + customEnvsSet: [] // list of environments of the custom set + }, + morphologies: [], // list of available morphologies + currentSeedsIdx: {}, // index of the policy selected for each morphology + agents: [], // list of running agents + simulationState: { + status: 'init', // 'running', 'paused' + intro_tour: false, + agentFollowed: null, + agentSelected: null, + }, + activeTab:'getting_started', // 'getting_started', 'draw_yourself', 'proc_gen', 'advanced_options', 'about' + parkourConfig: { // parkour customization parameters + terrain:{ + dim1: 1.0, + dim2: 0.95, + dim3: 0, + smoothing: 25, + waterLevel: 0 + }, + creepers:{ + width: 0.3, + height: 2.5, + spacing: 1, + type: 'Swingable' // 'Rigid' + } + }, + drawingModeState: { + drawing: false, + drawing_ground: false, + drawing_ceiling: false, + erasing: false, + }, + advancedOptionsState: { + drawJoints: false, + drawLidars: true, + drawNames: true, + drawObservation: false, + drawReward: false, + assets: { + circle: false, + }, + }, +}; \ No newline at end of file diff --git a/js/ui_state/store/store.js b/js/ui_state/store/store.js new file mode 100644 index 0000000000000000000000000000000000000000..5d32659c6241c7669bcae51b9c4a948fd9675f6c --- /dev/null +++ b/js/ui_state/store/store.js @@ -0,0 +1,111 @@ +import PubSub from '../lib/pubsub.js'; + +/** + * @classdesc Class that handles UI state modifications. + */ +export default class Store { + /** + * @constructor + * @param params {{actions: {}, mutations: {}, state: {}}} + */ + constructor(params) { + let self = this; + self.actions = {}; + self.mutations = {}; + self.state = {}; + self.status = 'default state'; + self.events = new PubSub(); // UI modifications manager + if (params.hasOwnProperty('actions')) { + self.actions = params.actions; + } + if (params.hasOwnProperty('mutations')) { + self.mutations = params.mutations; + } + + // Creates a Proxy to handles the state modifications + self.state = new Proxy((params.state || {}), { + + /** + * Function called when a key of the state is changed. Publish an event corresponding to the key that has been changed. + * @param state {Object} + * @param key {string} + * @param value {} + * @return {boolean} + */ + set: function (state, key, value) { + state[key] = value; + console.log(`stateChange: ${key}: ${value}`); + + if(key == 'envsSets'){ + self.events.publish('envsSetChange', self.state); + } + else if(key == 'morphologies'){ + self.events.publish('morphologiesChange', self.state); + } + else if(key == 'agents'){ + self.events.publish('agentsListChange', self.state); + } + else if(key == 'simulationState'){ + self.events.publish('agentsListChange', self.state); + self.events.publish('mainButtonsChange', self.state); + } + else if(key == 'parkourConfig'){ + self.events.publish('parkourConfigChange', self.state); + } + else if(key == 'drawingModeState'){ + self.events.publish('drawingModeChange', self.state); + } + else if(key == 'advancedOptionsState'){ + self.events.publish('advancedOptionsChange', self.state); + } + else if(key == 'language'){ + self.events.publish('globalElementsChange', self.state); + self.events.publish('aboutTabChange', self.state); + } + + if (self.status !== 'mutation') { + console.warn(`You should use a mutation to set ${key}`); + } + return true; + } + }); + } + + /** + * Triggers the action specified by actionKey with the given payload. + * @param actionKey {string} + * @param payload + * @return {boolean} + */ + dispatch(actionKey, payload) { + let self = this; + if (typeof self.actions[actionKey] !== 'function') { + console.error(`Action "${actionKey} doesn't exist.`); + return false; + } + console.groupCollapsed(`ACTION: ${actionKey}`); + self.status = 'action'; + self.actions[actionKey](self, payload); + console.groupEnd(); + return true; + } + + /** + * Triggers the mutation specified by mutationKey with the given payload. + * @param mutationKey + * @param payload + * @return {boolean} + */ + commit(mutationKey, payload) { + let self = this; + if (typeof self.mutations[mutationKey] !== 'function') { + console.log(`Mutation "${mutationKey}" doesn't exist`); + return false; + } + self.status = 'mutation'; + let newState = self.mutations[mutationKey](self.state, payload); + self.state = Object.assign(self.state, newState); + self.status = 'resting'; + return true; + } +} \ No newline at end of file diff --git a/js/utils/custom_user_data.js b/js/utils/custom_user_data.js new file mode 100644 index 0000000000000000000000000000000000000000..57cf75edb3581dcd138e2c16874c5e9b2a528edf --- /dev/null +++ b/js/utils/custom_user_data.js @@ -0,0 +1,82 @@ +let CustomUserDataObjectTypes = { + BODY_OBJECT: 0, + WATER: 1, + TERRAIN: 2, + GRIP_TERRAIN: 3, + MOTOR: 4, + BODY_SENSOR: 5, + SENSOR_GRIP_TERRAIN:6, +}; + +/** + * @classdesc Class used to store data about different objects. + */ +class CustomUserData{ + /** + * @constructor + * @param name {string} + * @param object_type {number} + */ + constructor(name, object_type){ + this.name = name; + this.object_type = object_type; + } +} + +/** + * @classdesc Motor user data class. + */ +class CustomMotorUserData extends CustomUserData{ + /** + * @constructor + * @param name {string} + * @param speed_control {number} + * @param check_contact {boolean} + * @param angle_correction {number} + * @param contact_body {Object} + */ + constructor(name, speed_control, check_contact, angle_correction=0.0, contact_body=null){ + super(name, CustomUserDataObjectTypes.MOTOR); + this.speed_control = speed_control; + this.check_contact = check_contact; + this.angle_correction = angle_correction; + this.contact_body = contact_body; + } +} + +/** + * @classdesc Body user data class. + */ +class CustomBodyUserData extends CustomUserData{ + /** + * @constructor + * @param check_contact {boolean} + * @param is_contact_critical {boolean} + * @param name {string} + * @param object_type {number} + */ + constructor(check_contact, is_contact_critical=false, + name="body_part", object_type=CustomUserDataObjectTypes.BODY_OBJECT){ + super(name, object_type); + this.check_contact = check_contact; + this.is_contact_critical = is_contact_critical; + this.has_contact = false; + } +} + +/** + * @classdesc Sensor user data class. + */ +class CustomBodySensorUserData extends CustomBodyUserData{ + /** + * @constructor + * @param check_contact {boolean} + * @param is_contact_critical {boolean} + * @param name {string} + */ + constructor(check_contact, is_contact_critical=false, name="body_part"){ + super(check_contact, is_contact_critical, name, CustomUserDataObjectTypes.BODY_SENSOR); + this.has_joint = false; + this.ready_to_attach = false; + } +} diff --git a/js/utils/utils.js b/js/utils/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..cf7583ecefffca9595573c6b0245a647b3c08d31 --- /dev/null +++ b/js/utils/utils.js @@ -0,0 +1,37 @@ +/* Utility functions */ + +/** + * Downloads the given object as a JSON file with the given filename. + * @param exportObj {Object} - Object to be downloaded. + * @param exportName {string} - Name of the file. + */ +window.downloadObjectAsJson = (exportObj, exportName) => { + let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); + let downloadAnchorNode = document.createElement('a'); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", exportName + ".json"); + document.body.appendChild(downloadAnchorNode); // required for firefox + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +} + +/** + * Transforms the first character of the given string to upper case. + * @param a {string} + * @returns {string} + */ +window.strUcFirst = (a) => { + return (a+'').charAt(0).toUpperCase()+a.substr(1); +} + +/** + * Draws the forbidden area in the off-screen forbidden canvas. + */ +window.draw_forbidden_area = () => { + forbidden_canvas.clear(); + forbidden_canvas.stroke("#FF0000"); + forbidden_canvas.strokeWeight(3); + forbidden_canvas.fill(255, 50, 0, 75); + let w = convertPosEnvToCanvas((INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP, 0).x; + forbidden_canvas.rect(0, 0, w, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); +} \ No newline at end of file diff --git a/policies.json b/policies.json new file mode 100644 index 0000000000000000000000000000000000000000..6204cdb7b8227c5d0b750e460873527d25bd66e2 --- /dev/null +++ b/policies.json @@ -0,0 +1 @@ +[{"type": "swimmer", "morphologies": [{"morphology": "fish", "seeds": [{"seed": "3", "path": "policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3", "name": "Nemo/adult"}, {"seed": "40", "path": "policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40", "name": "Flipper/baby"}, {"seed": "41", "path": "policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41", "name": "Flipper/teenager"}, {"seed": "42", "path": "policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42", "name": "Flipper/adult"}, {"seed": "7", "path": "policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7", "name": "Dorry/adult"}, {"seed": "9", "path": "policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9", "name": "Oscar/adult"}]}]}, {"type": "walker", "morphologies": [{"morphology": "spider", "seeds": [{"seed": "1", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1", "name": "Lucas/adult"}, {"seed": "12", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12", "name": "Peter/adult"}, {"seed": "130", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130", "name": "Aragog/baby"}, {"seed": "131", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131", "name": "Aragog/adult"}, {"seed": "132", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132", "name": "Aragog/teenager"}, {"seed": "4", "path": "policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4", "name": "Natasha/adult"}]}, {"morphology": "bipedal", "seeds": [{"seed": "1", "path": "policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1", "name": "Joe/adult"}, {"seed": "110", "path": "policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110", "name": "Bob/baby"}, {"seed": "111", "path": "policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111", "name": "Bob/teenager"}, {"seed": "112", "path": "policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112", "name": "Bob/adult"}, {"seed": "2", "path": "policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2", "name": "Alice/adult"}, {"seed": "5", "path": "policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5", "name": "Susan/adult"}]}]}, {"type": "climber", "morphologies": [{"morphology": "chimpanzee", "seeds": [{"seed": "15", "path": "policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15", "name": "Jack/adult"}, {"seed": "2", "path": "policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2", "name": "Caesar/adult"}, {"seed": "4", "path": "policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4", "name": "Tarzan/adult"}, {"seed": "5", "path": "policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5", "name": "Tarzan/teenager"}, {"seed": "6", "path": "policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6", "name": "Tarzan/baby"}, {"seed": "6", "path": "policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6", "name": "Kong/adult"}]}]}] \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/group1-shard1of1.bin b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..7a69db3f1df85932f886c4285b2e5f3372b50f8c --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5091b104773c087e697523885f0f4e0c7c5adaa612873c0975cbcf24b2362ee +size 2347728 diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/model.json b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/model.json new file mode 100644 index 0000000000000000000000000000000000000000..ca452a555dca6f0bfe5038984144bd959cd35fed --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s15/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/group1-shard1of1.bin b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..5bb6676d62ddb7301ca5c808dcd250926a788f0a --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:508d72c6bf0bbc2039dd031a2ee122d740c2b45a11466aa10fc3064b3e1d1111 +size 2347728 diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/model.json b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/model.json new file mode 100644 index 0000000000000000000000000000000000000000..2cef928ad5945d9c4e05401ebc4909f8dbd2e6a3 --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s2/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/group1-shard1of1.bin b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..95dabe8e4bc44d37cb3084bd369928c264c71168 --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9dbf6e3cd4975222410321e347b187c45418f82370eea7b472d8a2bc05bf7e22 +size 2347728 diff --git a/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/model.json b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/model.json new file mode 100644 index 0000000000000000000000000000000000000000..acc39acac798692c1f3f1c0e8e7d27613843f3d8 --- /dev/null +++ b/policy_models/climber/chimpanzee/25-01_test_easy_climbing_parkour_CPPN_input_space_small_max_water_level_0.2_walker_type_climbing_profile_chimpanzee_teacher_Random_s6/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "dtype": {"type": "DT_FLOAT"}, "seed2": {"i": "0"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/group1-shard1of1.bin b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..ad38c313a70c99b44268cea90a6e96eefbe45651 --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424081cd82403e5df2828bef5a83df3559ba7c99f8d22bf8370e733c8e216038 +size 2347728 diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/model.json b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/model.json new file mode 100644 index 0000000000000000000000000000000000000000..3ccca9b7601e88e0df1b462c2f2683663567b55b --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s4/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"dtype": {"type": "DT_FLOAT"}, "seed": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/group1-shard1of1.bin b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..4eec951af5719b10bdbf5de9cebddfb03303b063 --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2623f0360f761805f9c62fb7ebdc28438e0205ba5bcf2b869a961a799c0ffa7a +size 2347728 diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/model.json b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/model.json new file mode 100644 index 0000000000000000000000000000000000000000..32a3c3c184aff6f940b8b9499f071fc4bbdd2435 --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s5/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}, "outputs": {"main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed2": {"i": "0"}, "T": {"type": "DT_INT32"}, "dtype": {"type": "DT_FLOAT"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/group1-shard1of1.bin b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..fbae7f139def6282db52077d5aafa584a89ee31f --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf5f99400415a16b1525f05e7b5047d5d0c482d0803fece87d185eae31934fb0 +size 2347728 diff --git a/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/model.json b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/model.json new file mode 100644 index 0000000000000000000000000000000000000000..5c8516972ad11dc0de97301c19bde061cf8c4125 --- /dev/null +++ b/policy_models/climber/chimpanzee/27-07_benchmark_parkour_ALP-GMM_CPPN_input_space_small_max_water_level_0.1_walker_type_climbing_profile_chimpanzee_s6/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed": {"i": "0"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/group1-shard1of1.bin b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..a4dc8e811284c25993bf22e8c435bd03684b7e8c --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:946fd11edddc57168717246fc04838a3e259ae0adc96cd7f08ab98ac126d2ee8 +size 2200464 diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/model.json b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/model.json new file mode 100644 index 0000000000000000000000000000000000000000..54ddf04201ed9f641130224e00131e619cf0ec51 --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s3/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.3", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "seed": {"i": "0"}, "T": {"type": "DT_INT32"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/group1-shard1of1.bin b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..09620c88f390eaa2820e567eeb6604a88150822b --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:752a08df20636c8155c769492a5e3969172ad657a977083859b8091c3b4248e6 +size 2200464 diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/model.json b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/model.json new file mode 100644 index 0000000000000000000000000000000000000000..6081dedb73778791137e15399204c57bebb3fd27 --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s7/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.3", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}, "outputs": {"main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "dtype": {"type": "DT_FLOAT"}, "seed2": {"i": "0"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/group1-shard1of1.bin b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..5c6222517e1c5ad08c7567ff9520fc8f9bfecb1b --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdd9428a73776a0d8761734740f9c1faff5d89e4ee0740f3bda6ba2ede4b2d2a +size 2200464 diff --git a/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/model.json b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/model.json new file mode 100644 index 0000000000000000000000000000000000000000..66e17b3d25f5cb892b45426260906aa281624133 --- /dev/null +++ b/policy_models/swimmer/fish/04-01_benchmark_parkour_RIAC_walker_type_fish_s9/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.3", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed2": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/group1-shard1of1.bin b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..c676d27b789183f6ff3f67cf09b6e2ca1467c60e --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20c1c85c8015c39f5c7b40863a3fc784ae6f9a585e6d6d22025e370e81a529a1 +size 2200464 diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/model.json b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/model.json new file mode 100644 index 0000000000000000000000000000000000000000..3586e26b9f64afc6fe95b11dd0e7f4acdd6d2bf8 --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s40/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "seed2": {"i": "0"}, "T": {"type": "DT_INT32"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/group1-shard1of1.bin b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..f9f92167303033372f865059e48a19f3d485d935 --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05e1bafaaff280a8946337c38a11ea03e24e05383a1dd777cb88a94ef03b82d1 +size 2200464 diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/model.json b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/model.json new file mode 100644 index 0000000000000000000000000000000000000000..03da15dd5789592804012ec6d6c43a2bfdddf1bb --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s41/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}, "outputs": {"main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/group1-shard1of1.bin b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..2bc799ddb24e1973e1811e251f3475cb6fa1770f --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbce7411d7e43185111b7cf2a9c18181479b8d5857b473336c1f2e6d2d2a3052 +size 2200464 diff --git a/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/model.json b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/model.json new file mode 100644 index 0000000000000000000000000000000000000000..516b3d511f51fd502ff91725096dc57f01870c2d --- /dev/null +++ b/policy_models/swimmer/fish/22-07_benchmark_parkour_ALP-GMM_walker_type_fish_s42/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}, "outputs": {"main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "42"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "38"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "38"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "T": {"type": "DT_INT32"}, "dtype": {"type": "DT_FLOAT"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [42, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [38, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/group1-shard1of1.bin b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..eaabc870ba362224f5397867d8291d5669b8be9d --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74e986561d1ea6dd4552458d0699a8ad07dd8471bd1d4e619915a368196b761a +size 2187664 diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/model.json b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/model.json new file mode 100644 index 0000000000000000000000000000000000000000..501da5cb90ea53ae6728582b102e65a74f0324b9 --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s1/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/group1-shard1of1.bin b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..5b317f3f44430dbae81592d086b7c4021449a2a7 --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:261e7a6c22c694816e3ddd2cae8940389be5c85c26485936ca62d2a2458008ec +size 2187664 diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/model.json b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/model.json new file mode 100644 index 0000000000000000000000000000000000000000..5a7a30c117aa015a542fbb649b2545124ff5f46d --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s2/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}}, "outputs": {"main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"dtype": {"type": "DT_FLOAT"}, "seed2": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/group1-shard1of1.bin b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..8f6bc7f1740d81cc787ef98e73f3c5c3dbb5c35d --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd5654fb3dc8ddca261398e7b3e0b6ce029eb4c9ba0480ee830218b85482c4df +size 2187664 diff --git a/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/model.json b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/model.json new file mode 100644 index 0000000000000000000000000000000000000000..a8c80e035117c90606d8395b0f95202315f034ca --- /dev/null +++ b/policy_models/walker/bipedal/16-02_old_walker_parkour_student_sac_v0.1.1_teacher_ALP-GMM_s5/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}}, "outputs": {"main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/group1-shard1of1.bin b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e0f63b3dbdbcb1a4a23d772eee2368fbf9b5297 --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a50d6daa3de3527ce735383b8b48b13aa7dfaac163a567d8aa8f24160556ff6c +size 2187664 diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/model.json b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/model.json new file mode 100644 index 0000000000000000000000000000000000000000..21e4501b249ae25a50a7a5413163f7f9e51f0c8d --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s110/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"dtype": {"type": "DT_FLOAT"}, "seed": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/group1-shard1of1.bin b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..6f5b17ca4e7f0e2afd4d55bc7dce5f96b0d0f2f4 --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d2aa23e307b23e3d92a596da94f6edb26e20f376e65960aef9740e04fb58821 +size 2187664 diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/model.json b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/model.json new file mode 100644 index 0000000000000000000000000000000000000000..49f71f481ef3997be6f25af8c21df4096ebfd740 --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s111/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}}, "outputs": {"main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "seed": {"i": "0"}, "seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/group1-shard1of1.bin b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..2c9a86a85fa9af529e9f2449b2a5c7846d630f9c --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39dfa43bbc06e128620b429840290100c3e7527c5ba6dfcbb73da07641268cf3 +size 2187664 diff --git a/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/model.json b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/model.json new file mode 100644 index 0000000000000000000000000000000000000000..97616a5e61706a814b5bda8e253731656eaaec87 --- /dev/null +++ b/policy_models/walker/bipedal/22-07_benchmark_parkour_ALP-GMM_walker_type_old_classic_bipedal_s112/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "4"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "4"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "4"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "40"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "36"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "36"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "seed": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 4], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [4], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [40, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [36, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..d93cf532cae6af2a6ddd2f0b1f7d1e38118c9871 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df9190914aa1afd63bb4c48996346c539f8d2aa81181786f03017382f4794683 +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/model.json new file mode 100644 index 0000000000000000000000000000000000000000..be93691c1a1da5ec49ffa4fb2dd4ae97b36b732f --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s1/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..1420bd0e3d16aae4650041b75d6613e656a60105 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64d0bb2fa061ccc34e2fef9383322a034f08fc8ef977ff0b9d467386df7b4303 +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/model.json new file mode 100644 index 0000000000000000000000000000000000000000..4780d85d9730ca7f99921ab509c36544c42326b3 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s12/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..359c8ed5304c3d4b4f423582153f0c02a743269e --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5e0ee5b9f6b49f415432c76b6ae64fe5a1e7909f147723278cac8fbda91ab9c +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/model.json new file mode 100644 index 0000000000000000000000000000000000000000..8fed8d8aaf2b6398e45e0842e86d42212a5a3297 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s130/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"out_type": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..3c77815f5131025cd31a10e14dc12c6f0cb1eeb9 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87355e4103996b0fbcc57f2769f09f55d8f62c72b447fe5ed9b090f5b1743803 +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/model.json new file mode 100644 index 0000000000000000000000000000000000000000..d0b8fb958b5276b1d3f8880373ce1b7abffd98aa --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s131/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}, "outputs": {"main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"T": {"type": "DT_INT32"}, "seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..5b4951766b1fb312fa462fe3e1d076e9036e2061 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1def67200aa4a45feb4d52ddf27c14348f093e4337825a9a6b9de23efbfd0155 +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/model.json new file mode 100644 index 0000000000000000000000000000000000000000..08ba84725f74892bc1c53e7391e5e41d3f48ab83 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s132/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}}, "outputs": {"main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"N": {"i": "2"}, "T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/group1-shard1of1.bin b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/group1-shard1of1.bin new file mode 100644 index 0000000000000000000000000000000000000000..9a06f717fc748d6163dec53cd667387577d285b2 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/group1-shard1of1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37504457f1d0708063ff3a8d328bf60ed43449305aee5b6ac4feaf1a032a655f +size 2347728 diff --git a/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/model.json b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/model.json new file mode 100644 index 0000000000000000000000000000000000000000..41d868e8a9c220564fb2e29e461f9392c0ed93e1 --- /dev/null +++ b/policy_models/walker/spider/22-07_benchmark_parkour_ALP-GMM_walker_type_spider_s4/model.json @@ -0,0 +1 @@ +{"format": "graph-model", "generatedBy": "1.15.5", "convertedBy": "TensorFlow.js Converter v3.12.0", "signature": {"inputs": {"x": {"name": "Placeholder_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "a": {"name": "Placeholder_2:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}, "outputs": {"main/mul_1:0": {"name": "main/mul_1:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/mul:0": {"name": "main/mul:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}, {"size": "12"}]}}, "main/q2/Squeeze:0": {"name": "main/q2/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/q1/Squeeze:0": {"name": "main/q1/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}, "main/v/Squeeze:0": {"name": "main/v/Squeeze:0", "dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "-1"}]}}}}, "modelTopology": {"node": [{"name": "main/pi/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1/x", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/pi/mul/x", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/pi/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/pi/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense_3/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "12"}]}}}}}, {"name": "main/pi/dense_3/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "12"}]}}}}}, {"name": "main/pi/add/y", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {}}}}}, {"name": "main/q1/concat/axis", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}, "dtype": {"type": "DT_INT32"}}}, {"name": "main/q1/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q1/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q1/dense_1/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}}}, {"name": "main/q1/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_2", "op": "Placeholder", "attr": {"dtype": {"type": "DT_FLOAT"}, "shape": {"shape": {"dim": [{"size": "-1"}, {"size": "12"}]}}}}, {"name": "main/q2/concat/axis", "op": "Const", "attr": {"dtype": {"type": "DT_INT32"}, "value": {"tensor": {"dtype": "DT_INT32", "tensorShape": {}}}}}, {"name": "main/q2/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "66"}, {"size": "400"}]}}}}}, {"name": "main/q2/dense/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_1/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}}}, {"name": "main/q2/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/q2/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}}}, {"name": "Placeholder_1", "op": "Placeholder", "attr": {"shape": {"shape": {"dim": [{"size": "-1"}, {"size": "54"}]}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_1/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}]}}}}}, {"name": "main/v/dense/kernel", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "54"}, {"size": "400"}]}}}}}, {"name": "main/v/dense_2/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "300"}, {"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense/bias", "op": "Const", "attr": {"dtype": {"type": "DT_FLOAT"}, "value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}]}}}}}, {"name": "main/v/dense_1/kernel", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "400"}, {"size": "300"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/v/dense_2/bias", "op": "Const", "attr": {"value": {"tensor": {"dtype": "DT_FLOAT", "tensorShape": {"dim": [{"size": "1"}]}}}, "dtype": {"type": "DT_FLOAT"}}}, {"name": "main/pi/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/pi/dense/kernel", "main/pi/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/q1/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q1/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "N": {"i": "2"}, "Tidx": {"type": "DT_INT32"}}}, {"name": "main/q2/concat", "op": "ConcatV2", "input": ["Placeholder_1", "Placeholder_2", "main/q2/concat/axis"], "attr": {"T": {"type": "DT_FLOAT"}, "Tidx": {"type": "DT_INT32"}, "N": {"i": "2"}}}, {"name": "main/v/dense/Relu", "op": "_FusedMatMul", "input": ["Placeholder_1", "main/v/dense/kernel", "main/v/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "epsilon": {"f": 0.0}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/pi/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/pi/dense/Relu", "main/pi/dense_1/kernel", "main/pi/dense_1/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/q1/dense/Relu", "op": "_FusedMatMul", "input": ["main/q1/concat", "main/q1/dense/kernel", "main/q1/dense/bias"], "device": "/device:CPU:0", "attr": {"fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "transpose_b": {"b": false}}}, {"name": "main/q2/dense/Relu", "op": "_FusedMatMul", "input": ["main/q2/concat", "main/q2/dense/kernel", "main/q2/dense/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "num_args": {"i": "1"}, "T": {"type": "DT_FLOAT"}, "epsilon": {"f": 0.0}, "transpose_a": {"b": false}}}, {"name": "main/v/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/v/dense/Relu", "main/v/dense_1/kernel", "main/v/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}}}, {"name": "main/pi/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_2/kernel", "main/pi/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "num_args": {"i": "1"}, "transpose_a": {"b": false}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "epsilon": {"f": 0.0}}}, {"name": "main/pi/dense_3/BiasAdd", "op": "_FusedMatMul", "input": ["main/pi/dense_1/Relu", "main/pi/dense_3/kernel", "main/pi/dense_3/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "transpose_a": {"b": false}, "epsilon": {"f": 0.0}, "num_args": {"i": "1"}}}, {"name": "main/q1/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q1/dense/Relu", "main/q1/dense_1/kernel", "main/q1/dense_1/bias"], "device": "/device:CPU:0", "attr": {"T": {"type": "DT_FLOAT"}, "transpose_b": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}}}, {"name": "main/q2/dense_1/Relu", "op": "_FusedMatMul", "input": ["main/q2/dense/Relu", "main/q2/dense_1/kernel", "main/q2/dense_1/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "transpose_a": {"b": false}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA==", "UmVsdQ=="]}}, "transpose_b": {"b": false}, "num_args": {"i": "1"}}}, {"name": "main/v/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/v/dense_1/Relu", "main/v/dense_2/kernel", "main/v/dense_2/bias"], "device": "/device:CPU:0", "attr": {"epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_a": {"b": false}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}, "num_args": {"i": "1"}}}, {"name": "main/pi/Tanh", "op": "Tanh", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Shape", "op": "Shape", "input": ["main/pi/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "out_type": {"type": "DT_INT32"}}}, {"name": "main/pi/dense_3/Tanh", "op": "Tanh", "input": ["main/pi/dense_3/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q1/dense_1/Relu", "main/q1/dense_2/kernel", "main/q1/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_a": {"b": false}, "num_args": {"i": "1"}, "epsilon": {"f": 0.0}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "transpose_b": {"b": false}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/dense_2/BiasAdd", "op": "_FusedMatMul", "input": ["main/q2/dense_1/Relu", "main/q2/dense_2/kernel", "main/q2/dense_2/bias"], "device": "/device:CPU:0", "attr": {"transpose_b": {"b": false}, "epsilon": {"f": 0.0}, "T": {"type": "DT_FLOAT"}, "fused_ops": {"list": {"s": ["Qmlhc0FkZA=="]}}, "num_args": {"i": "1"}, "transpose_a": {"b": false}}}, {"name": "main/v/Squeeze", "op": "Squeeze", "input": ["main/v/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/mul", "op": "Identity", "input": ["main/pi/Tanh"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/random_normal/RandomStandardNormal", "op": "RandomStandardNormal", "input": ["main/pi/Shape"], "attr": {"seed": {"i": "0"}, "dtype": {"type": "DT_FLOAT"}, "T": {"type": "DT_INT32"}, "seed2": {"i": "0"}}}, {"name": "main/pi/add", "op": "AddV2", "input": ["main/pi/dense_3/Tanh", "main/pi/add/y"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/q1/Squeeze", "op": "Squeeze", "input": ["main/q1/dense_2/BiasAdd"], "attr": {"squeeze_dims": {"list": {"i": ["1"]}}, "T": {"type": "DT_FLOAT"}}}, {"name": "main/q2/Squeeze", "op": "Squeeze", "input": ["main/q2/dense_2/BiasAdd"], "attr": {"T": {"type": "DT_FLOAT"}, "squeeze_dims": {"list": {"i": ["1"]}}}}, {"name": "main/pi/mul", "op": "Mul", "input": ["main/pi/mul/x", "main/pi/add"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_1", "op": "AddV2", "input": ["main/pi/add_1/x", "main/pi/mul"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Exp", "op": "Exp", "input": ["main/pi/add_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/mul_1", "op": "Mul", "input": ["main/pi/random_normal/RandomStandardNormal", "main/pi/Exp"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/add_2", "op": "AddV2", "input": ["main/pi/dense_2/BiasAdd", "main/pi/mul_1"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/pi/Tanh_1", "op": "Tanh", "input": ["main/pi/add_2"], "attr": {"T": {"type": "DT_FLOAT"}}}, {"name": "main/mul_1", "op": "Identity", "input": ["main/pi/Tanh_1"], "attr": {"T": {"type": "DT_FLOAT"}}}], "library": {}, "versions": {"producer": 808}}, "weightsManifest": [{"paths": ["group1-shard1of1.bin"], "weights": [{"name": "main/pi/dense_2/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_2/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add_1/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/mul/x", "shape": [], "dtype": "float32"}, {"name": "main/pi/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/pi/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/pi/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/pi/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/pi/dense_3/kernel", "shape": [300, 12], "dtype": "float32"}, {"name": "main/pi/dense_3/bias", "shape": [12], "dtype": "float32"}, {"name": "main/pi/add/y", "shape": [], "dtype": "float32"}, {"name": "main/q1/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q1/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q1/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q1/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q1/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q1/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q1/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/q2/concat/axis", "shape": [], "dtype": "int32"}, {"name": "main/q2/dense/kernel", "shape": [66, 400], "dtype": "float32"}, {"name": "main/q2/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/q2/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/q2/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/q2/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/q2/dense_2/bias", "shape": [1], "dtype": "float32"}, {"name": "main/v/dense_1/bias", "shape": [300], "dtype": "float32"}, {"name": "main/v/dense/kernel", "shape": [54, 400], "dtype": "float32"}, {"name": "main/v/dense_2/kernel", "shape": [300, 1], "dtype": "float32"}, {"name": "main/v/dense/bias", "shape": [400], "dtype": "float32"}, {"name": "main/v/dense_1/kernel", "shape": [400, 300], "dtype": "float32"}, {"name": "main/v/dense_2/bias", "shape": [1], "dtype": "float32"}]}]} \ No newline at end of file diff --git a/style.css b/style.css deleted file mode 100644 index 114adf441e9032febb46bc056b2a8bb651075f0d..0000000000000000000000000000000000000000 --- a/style.css +++ /dev/null @@ -1,28 +0,0 @@ -body { - padding: 2rem; - font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif; -} - -h1 { - font-size: 16px; - margin-top: 0; -} - -p { - color: rgb(107, 114, 128); - font-size: 15px; - margin-bottom: 10px; - margin-top: 5px; -} - -.card { - max-width: 620px; - margin: 0 auto; - padding: 16px; - border: 1px solid lightgray; - border-radius: 16px; -} - -.card p:last-child { - margin-bottom: 0; -} diff --git a/ui.js b/ui.js new file mode 100644 index 0000000000000000000000000000000000000000..6caab644fd9543f9eb24f15fd8188d613866cd2a --- /dev/null +++ b/ui.js @@ -0,0 +1,573 @@ +import store from './js/ui_state/store/index.js'; +import MorphologiesList from './js/ui_state/components/morphologies_list.js'; +import AgentsList from './js/ui_state/components/agents_list.js'; +import MainButtons from './js/ui_state/components/main_buttons.js'; +import ParkourConfig from './js/ui_state/components/parkour_config.js'; +import DrawingMode from "./js/ui_state/components/drawing_mode.js"; +import AdvancedOptions from "./js/ui_state/components/advanced_options.js"; +import EnvsSet from "./js/ui_state/components/envs_set.js"; +import GlobalElements from "./js/ui_state/components/global_elements.js"; +import AboutTab from "./js/ui_state/components/about_tab.js"; + +/** + * Opens the given modal. + * @param modal {HTMLDivElement} + */ +window.openModal = (modal) => { + modal.style.backgroundColor = 'rgba(0,0,0,0.5)'; + modal.style.display = "block"; + modal.classList.add('show'); +} + +/** + * Closes the given modal and clears the text fields. + * @param modal {HTMLDivElement} + */ +window.closeModal = (modal) => { + modal.classList.remove('show'); + modal.style.display = 'none'; + modal.querySelectorAll('.text-field').forEach((span, index) => { + span.value = ""; + }); +} + +// Save env modal setup +const saveEnvModal = document.querySelector('#saveEnvModal'); +saveEnvModal.querySelectorAll('.btn').forEach((span, index) => { + span.addEventListener('click', () => { + + // If the confirm button is clicked + if(span.getAttribute('id') == "save-confirm-btn"){ + + // Gets the name and description values + let name = saveEnvModal.querySelector('#env-name').value; + if(name == ""){ + name = "Custom Environment " + store.state.envsSets.customEnvsSet.length; + } + let description = saveEnvModal.querySelector('#env-description').value; + + // Saves the current position of the agents + for(let i = 0; i < store.state.agents.length; i++){ + store.dispatch('setAgentInitPos', {index: i, init_pos: window.game.env.agents[i].agent_body.reference_head_object.GetPosition().Clone()}); + } + + // Adjusts the zoom and scroll to capture the thumbnail + let previous_zoom = window.game.env.zoom; + let previous_scroll = [...window.game.env.scroll]; + window.game.env.set_zoom(THUMBNAIL_ZOOM); + window.game.env.set_scroll(null, THUMBNAIL_SCROLL_X, 0); + window.game.env.render(); + + // Creates the state of the current env + let env = { + terrain: { + ground: [...window.ground], + ceiling: [...window.ceiling], + parkourConfig: Object.assign({}, store.state.parkourConfig.terrain), + creepersConfig: Object.assign({}, store.state.parkourConfig.creepers) + }, + agents: [...store.state.agents], + description: { + name: name, + text: description + }, + // Captures the canvas to create the thumbnail of the env + image: window.canvas.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream") + }; + + // Adds the env to the custom set + store.dispatch('addEnv',{set: 'custom', env: env}); + + // Sets back the zoom and scroll to the previous values + window.game.env.set_zoom(previous_zoom); + window.game.env.set_scroll(null, previous_scroll[0], previous_scroll[1]); + window.game.env.render(); + } + + closeModal(saveEnvModal); + }); +}); + +// Main buttons setup +const runButton = document.querySelector("#runButton"); +runButton.addEventListener('click', () => { + store.dispatch('toggleRun', {}); +}); +const resetButton = document.querySelector("#resetButton"); +resetButton.addEventListener('click', () => { + store.dispatch('resetSimulation', {}); +}); +const saveEnvButton = document.querySelector('#saveEnvButton'); +saveEnvButton.addEventListener('click', () => { + openModal(saveEnvModal); +}); +const mainButtonsInstance = new MainButtons(); +mainButtonsInstance.render(); + +// Morphologies list setup +const morphologiesListInstance = new MorphologiesList(); +morphologiesListInstance.render(); + +// Agents list setup +const agentListInstance = new AgentsList(); +agentListInstance.render(); + +// Environments set setup +const envsSetInstance = new EnvsSet(); +envsSetInstance.render(); + +// Parkour config parameters setup +const dim1SliderElement = document.querySelector("#dim1Slider") +dim1SliderElement.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "dim1", + value: parseFloat(dim1SliderElement.value) + }); +}); +const dim2SliderElement = document.querySelector("#dim2Slider") +dim2SliderElement.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "dim2", + value: parseFloat(dim2SliderElement.value) + }); +}); +const dim3SliderElement = document.querySelector("#dim3Slider") +dim3SliderElement.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "dim3", + value: parseFloat(dim3SliderElement.value) + }); +}); +const smoothingSliderElement = document.querySelector("#smoothingSlider") +smoothingSliderElement.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "smoothing", + value: parseFloat(smoothingSliderElement.value) + }); +}); +const waterSliderElement = document.querySelector("#waterSlider") +waterSliderElement.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "waterLevel", + value: parseFloat(waterSliderElement.value) + }); +}); +const creepersWidthSlider = document.querySelector("#creepersWidthSlider"); +creepersWidthSlider.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "width", + value: parseFloat(creepersWidthSlider.value) + }); +}); +const creepersHeightSlider = document.querySelector("#creepersHeightSlider"); +creepersHeightSlider.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "height", + value: parseFloat(creepersHeightSlider.value) + }); +}); +const creepersSpacingSlider = document.querySelector("#creepersSpacingSlider"); +creepersSpacingSlider.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "spacing", + value: parseFloat(creepersSpacingSlider.value) + }); +}); +const creepersTypeSelect = document.querySelector("#creepersType"); +creepersTypeSelect.addEventListener('input', () => { + store.dispatch('changeParkourConfig', { + name: "type", + value: creepersTypeSelect.value + }); +}); +const parkourConfigInstance = new ParkourConfig(); +parkourConfigInstance.render(); + +// Tabs buttons setup +const gettingStartedBtn = document.querySelector('#getting-started-btn'); +gettingStartedBtn.addEventListener('click', () => { + store.dispatch('switchTab', 'getting_started'); +}) +const parkourCustomTab = document.querySelector('#parkour-custom-btn'); +parkourCustomTab.addEventListener('click', () => { + // Shows the "Draw Yourself!" subtab when opening the "Parkour Customization" tab + if(store.state.activeTab != 'draw_yourself' && store.state.activeTab != 'proc_gen'){ + let drawTabBtn = document.querySelector('#draw-tab-btn'); + let drawYourselfTab = new bootstrap.Tab(drawTabBtn); + drawYourselfTab.show(); + store.dispatch('switchTab', 'draw_yourself'); + } +}); +const drawYourselfBtn = document.querySelector('#draw-tab-btn'); +drawYourselfBtn.addEventListener('click', () => { + store.dispatch('switchTab', 'draw_yourself'); +}); +const procGenBtn = document.querySelector('#proc-gen-tab-btn'); +procGenBtn.addEventListener('click', () => { + store.dispatch('switchTab', 'proc_gen'); +}); +const advancedOptionsBtn = document.querySelector('#advanced-options-btn'); +advancedOptionsBtn.addEventListener('click', () => { + store.dispatch('switchTab', 'advanced_options'); +}); +const aboutBtn = document.querySelector('#about-btn'); +aboutBtn.addEventListener('click', () => { + store.dispatch('switchTab', 'about'); +}); + +// Drawing Mode buttons setup +const drawGroundButton = document.querySelector('#drawGroundButton'); +drawGroundButton.addEventListener('click', () => { + store.dispatch('drawGround', !store.state.drawingModeState.drawing_ground); +}); +const drawCeilingButton = document.querySelector('#drawCeilingButton'); +drawCeilingButton.addEventListener('click', () => { + store.dispatch('drawCeiling', !store.state.drawingModeState.drawing_ceiling); +}); +const eraseButton = document.querySelector('#eraseButton'); +eraseButton.addEventListener('click', () => { + store.dispatch('erase', !store.state.drawingModeState.erasing); +}); +const clearButton = document.querySelector('#clearButton'); +clearButton.addEventListener('click', () => { + store.dispatch('clear', {}); +}); +const generateTerrainButton = document.querySelector('#generateTerrainButton'); +generateTerrainButton.addEventListener('click', () => { + store.dispatch('generateTerrain', store.state.drawingModeState.drawing); +}); +const drawingModeInstance = new DrawingMode(); +drawingModeInstance.render(); + +// Advanced Options setup +const drawJointsSwitch = document.querySelector("#drawJointsSwitch"); +drawJointsSwitch.addEventListener('input', () => { + store.dispatch('toggleSwitch', {name: 'drawJoints', value: drawJointsSwitch.checked} ); +}); +const drawLidarsSwitch = document.querySelector("#drawLidarsSwitch"); +window.draw_lidars = true; +drawLidarsSwitch.addEventListener('input', () => { + store.dispatch('toggleSwitch', {name: 'drawLidars', value: drawLidarsSwitch.checked}); +}); +const drawNamesSwitch = document.querySelector("#drawNamesSwitch"); +window.draw_names = true; +drawNamesSwitch.addEventListener('input', () => { + store.dispatch('toggleSwitch', {name: 'drawNames', value: drawNamesSwitch.checked}); +}); +const drawObservationSwitch = document.querySelector("#drawObservationSwitch"); +drawObservationSwitch.addEventListener('input', () => { + store.dispatch('toggleSwitch', {name: 'drawObservation', value: drawObservationSwitch.checked}); +}); +const drawRewardSwitch = document.querySelector("#drawRewardSwitch"); +drawRewardSwitch.addEventListener('input', () => { + store.dispatch('toggleSwitch', {name: 'drawReward', value: drawRewardSwitch.checked}); +}); +const circleAssetButton = document.querySelector('#circleAssetButton'); +circleAssetButton.addEventListener('click', () => { + store.dispatch('drawAsset', {name: 'circle', value: !store.state.advancedOptionsState.assets.circle}); +}); +const advancedOptionsInstance = new AdvancedOptions(); +advancedOptionsInstance.render(); + +// Language set up +const langSelect = document.querySelector("#langSelect"); +langSelect.addEventListener('input', () => { + store.dispatch('setLanguage', langSelect.value); +}); + +// About tab set up +const aboutTabInstance = new AboutTab(); +aboutTabInstance.render(); + +// Global elements set up +const globalElementsInstance = new GlobalElements(); +globalElementsInstance.render(); + +/* + * Fetches the available morphologies and policies from the JSON file + */ +fetch('./policies.json') + .then(resp => resp.text().then(body => { + window.agent_policies = JSON.parse(body); + return window.agent_policies; + })) + .then(types => { + types.forEach(type => { + type["morphologies"].forEach(morphology => { + + // Adds the morphology with its compatible policies to the list of morphologies + store.dispatch('addMorphology', { + morphology: morphology["morphology"], + seeds: morphology["seeds"].map((seed, index) => { + seed["idx"] = index; + return seed; + }) + }); + }); + }); + }); + +/* + * Fetches the base environments from the JSON file. + * The JSON file must contain a list of the names of all the files contained in the 'base_envs_set' folder. + */ +fetch('./base_envs_set.json') + .then(resp => resp.text().then(body => { + return JSON.parse(body); + })) + .then(data => data['filenames'].forEach(filename => { + + // Fetches each JSON env file and parses them to get the corresponding environment + fetch('./base_envs_set/' + filename) + .then(resp => resp.text().then(body => { + let env = JSON.parse(body); + + // Adds the environment contained in the JSON file to the base set + store.dispatch('addEnv',{set: 'base', env: env}); + })) + })); + +/* Utility functions that require access to 'store' */ + +/** + * Wrapper for init_game() with default parameters. + */ +window.init_default = () => { + store.dispatch('init_default', {}); +} + +/** + * Indicates whether the drawing is active. + * @returns {boolean} + */ +window.is_drawing = () => { + return store.state.drawingModeState.drawing; +} + +/** + * Indicates whether the drawing_ground is active. + * @returns {boolean} + */ +window.is_drawing_ground = () => { + return store.state.drawingModeState.drawing_ground; +} + +/** + * Indicates whether the drawing_ceiling is active. + * @returns {boolean} + */ +window.is_drawing_ceiling = () => { + return store.state.drawingModeState.drawing_ceiling; +} + +/** + * Indicates whether the erasing is active. + * @returns {boolean} + */ +window.is_erasing = () => { + return store.state.drawingModeState.erasing; +} + +/** + * Indicates whether the drawing_circle is active. + * @returns {boolean} + */ +window.is_drawing_circle = () => { + return store.state.advancedOptionsState.assets.circle; +} + +/** + * Generates the terrain from the drawing (true) or vice-versa (false). + * @param payload {boolean} + */ +window.generateTerrain = (payload) => { + store.dispatch('generateTerrain', payload); +} + +/** + * Re-draws the drawing canvas. + */ +window.refresh_drawing = () => { + store.dispatch('refreshDrawing', {}); +} + +/** + * Loads the default environment (Flat Parkour). + */ +window.loadDefaultEnv = () => { + let defaultEnv = store.state.envsSets.baseEnvsSet.find(env => env.description["EN"].name.split(" ")[0] == "Flat"); + store.dispatch('loadEnv', defaultEnv != null ? defaultEnv : store.state.envsSets.baseEnvsSet[0]); +} + +/** + * Handles mouse clicks outside the canvas. + */ +window.deselectDrawingButtons = () => { + store.dispatch('deselectDrawingButtons', {}); +} + +/** + * Handles agent selection according to the given index. + * @param index {number} - Index of the agent to select in the list of agents + */ +window.set_agent_selected = (index) => { + store.dispatch('selectAgent', {index: index}); +} + +/** + * Handles agent following according to the given index. + * @param index {number} - Index of the agent to select in the list of agents + */ +window.set_agent_followed = (index) => { + store.dispatch('followAgent', {index: index}); +} + +/** + * Handles agent deletion. + * @param agent {Object} - Agent to delete + */ +window.delete_agent = (agent) => { + store.dispatch('deleteAgent', {index: window.game.env.agents.indexOf(agent)}); +} + +/** + * Returns the current language. + * @return {string} + */ +window.get_language = () => { + return store.state.language; +} + +/** + * Sets up and starts language selection with IntroJs. + */ +window.langIntroSetUp = () => { + window.langIntro = introJs(); + + // Called when langIntro is exited: sets up and starts the guide tour + window.langIntro.onexit(function (){ + window.introTourSetUp(); + }); + + window.langIntro.setOptions({ + exitOnOverlayClick: false, + showBullets: false, + doneLabel: "Ok", + steps: [ + { + title: "Choose a language:", + intro: `` + }, + ] + }); + + // Starts the language selection intro + window.langIntro.start(); + + // Sets the language on select input + const langSelectIntro = document.querySelector('#langSelectIntro'); + langSelectIntro.addEventListener('input', () => { + store.dispatch('setLanguage', langSelectIntro.value); + }); +} + +/** + * Sets up guide tour with IntroJs. + */ +window.introTourSetUp = () => { + + store.dispatch('setIntroTour', true); + + // Guide tour and hints manager + window.introTour = introJs(); + + // Called when the tour is exited: enables save env button and show the hints + window.introTour.onexit(function (){ + store.dispatch('setIntroTour', false); + }); + + // Shows hints when a hint is closed so that they are always available + window.introTour.onhintclose(function (){ + window.introTour.showHints(); + }); + + let tour_dict = window.lang_dict[store.state.language]['introTour']; + + // Sets up the intro options + window.introTour.setOptions({ + + hidePrev: true, + exitOnOverlayClick: false, + nextLabel: tour_dict['nextLabel'], + prevLabel: tour_dict['prevLabel'], + doneLabel: tour_dict['doneLabel'], + + // Steps of the guide tour + steps: [ + { + title: tour_dict['welcomeTitle'], + intro: tour_dict['welcomeText'], + disableInteraction: true, + }, + { + title: tour_dict['viewportTitle'], + intro: tour_dict['viewportText'], + element: document.querySelector('#canvas_container'), + disableInteraction: false, + position: "bottom" + }, + { + title: tour_dict['runTitle'], + intro: tour_dict['runText'], + element: document.querySelector('#canvas-and-main-buttons'), + disableInteraction: false + }, + { + title: tour_dict['baseEnvsTitle'], + intro: tour_dict['baseEnvsText'], + element: document.querySelector('#baseEnvsSet'), + disableInteraction: true, + }, + { + title: tour_dict['morphologiesTitle'], + intro: tour_dict['morphologiesText'], + element: document.querySelector('#agents-selection'), + disableInteraction: true, + }, + { + title: tour_dict['agentsListTitle'], + intro: tour_dict['agentsListText'], + element: document.querySelector('#agents_list_container'), + disableInteraction: true, + }, + { + title: tour_dict['customEnvsTitle'], + intro: tour_dict['customEnvsText'], + element: document.querySelector('#customSetSection'), + disableInteraction: true, + }, + { + title: tour_dict['furtherTitle'], + intro: tour_dict['furtherText'], + element: document.querySelector('#tabs-buttons'), + disableInteraction: true, + } + ], + + // Hints buttons + hintButtonLabel: window.lang_dict[store.state.language]['introHints']['buttonLabel'], + hints: [ + { + hint: window.lang_dict[store.state.language]['introHints']['tips'], + element: document.querySelector('#canvas_container'), + hintPosition: 'top-right', + } + ] + }); + + // Starts the guide tour + window.introTour.start(); +} \ No newline at end of file