From 1111a8fc65948c57b16b1cd1ebda53632aad1aa9 Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 12:55:03 -0800 Subject: [PATCH 01/23] allegro task with non-cube assets built from menagerie --- mjpc/CMakeLists.txt | 2 + mjpc/tasks/CMakeLists.txt | 3 + mjpc/tasks/allegro/allegro.cc | 101 +++++++++ mjpc/tasks/allegro/allegro.h | 37 ++++ mjpc/tasks/allegro/assets/fileback.png | Bin 0 -> 8601 bytes mjpc/tasks/allegro/assets/filedown.png | Bin 0 -> 9816 bytes mjpc/tasks/allegro/assets/filefront.png | Bin 0 -> 10155 bytes mjpc/tasks/allegro/assets/fileleft.png | Bin 0 -> 7959 bytes mjpc/tasks/allegro/assets/fileright.png | Bin 0 -> 1406 bytes mjpc/tasks/allegro/assets/fileup.png | Bin 0 -> 3973 bytes mjpc/tasks/allegro/assets/grayback.png | Bin 0 -> 8356 bytes mjpc/tasks/allegro/assets/graydown.png | Bin 0 -> 9630 bytes mjpc/tasks/allegro/assets/grayfront.png | Bin 0 -> 9535 bytes mjpc/tasks/allegro/assets/grayleft.png | Bin 0 -> 5126 bytes mjpc/tasks/allegro/assets/grayright.png | Bin 0 -> 1237 bytes mjpc/tasks/allegro/assets/grayup.png | Bin 0 -> 2788 bytes mjpc/tasks/allegro/cube.xml | 29 +++ mjpc/tasks/allegro/right_hand.xml | 270 ++++++++++++++++++++++++ mjpc/tasks/allegro/task.xml | 83 ++++++++ 19 files changed, 525 insertions(+) create mode 100644 mjpc/tasks/allegro/allegro.cc create mode 100644 mjpc/tasks/allegro/allegro.h create mode 100644 mjpc/tasks/allegro/assets/fileback.png create mode 100644 mjpc/tasks/allegro/assets/filedown.png create mode 100644 mjpc/tasks/allegro/assets/filefront.png create mode 100644 mjpc/tasks/allegro/assets/fileleft.png create mode 100644 mjpc/tasks/allegro/assets/fileright.png create mode 100644 mjpc/tasks/allegro/assets/fileup.png create mode 100644 mjpc/tasks/allegro/assets/grayback.png create mode 100644 mjpc/tasks/allegro/assets/graydown.png create mode 100644 mjpc/tasks/allegro/assets/grayfront.png create mode 100644 mjpc/tasks/allegro/assets/grayleft.png create mode 100644 mjpc/tasks/allegro/assets/grayright.png create mode 100644 mjpc/tasks/allegro/assets/grayup.png create mode 100644 mjpc/tasks/allegro/cube.xml create mode 100644 mjpc/tasks/allegro/right_hand.xml create mode 100644 mjpc/tasks/allegro/task.xml diff --git a/mjpc/CMakeLists.txt b/mjpc/CMakeLists.txt index caa98350e..40a774e72 100644 --- a/mjpc/CMakeLists.txt +++ b/mjpc/CMakeLists.txt @@ -38,6 +38,8 @@ add_library( tasks/tasks.h tasks/acrobot/acrobot.cc tasks/acrobot/acrobot.h + tasks/allegro/allegro.cc + tasks/allegro/allegro.h tasks/cartpole/cartpole.cc tasks/cartpole/cartpole.h tasks/fingers/fingers.cc diff --git a/mjpc/tasks/CMakeLists.txt b/mjpc/tasks/CMakeLists.txt index 33affe24a..eeefc1891 100644 --- a/mjpc/tasks/CMakeLists.txt +++ b/mjpc/tasks/CMakeLists.txt @@ -17,6 +17,9 @@ add_custom_target( copy_menagerie_resources ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${menagerie_SOURCE_DIR}/wonik_allegro/assets + ${CMAKE_CURRENT_BINARY_DIR}/allegro/assets COMMAND ${CMAKE_COMMAND} -E copy_directory ${menagerie_SOURCE_DIR}/shadow_hand/assets ${CMAKE_CURRENT_BINARY_DIR}/hand/assets diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc new file mode 100644 index 000000000..94718f074 --- /dev/null +++ b/mjpc/tasks/allegro/allegro.cc @@ -0,0 +1,101 @@ +#include "mjpc/tasks/allegro/allegro.h" +#include + +#include +#include +#include + +#include +#include "mjpc/task.h" +#include "mjpc/utilities.h" + +namespace mjpc { +std::string AllegroCube::XmlPath() const { + return GetModelPath("allegro/task.xml"); +} +std::string AllegroCube::Name() const { return "AllegroCube"; } + +// ------- Residuals for cube manipulation task ------ +// Cube position: (3) +// Cube orientation: (3) +// Cube linear velocity: (3) +// Control: u +// ------------------------------------------ +void AllegroCube::ResidualFn::Residual(const mjModel* model, const mjData* data, + double* residual) const { + int counter = 0; + + // ---------- Cube position ---------- + // TODO(vincekurtz): specify goal position in a better way + double* cube_position = SensorByName(model, data, "cube_position"); + std::vector goal_cube_position = {0.3, 0.0, 0.025}; + + mju_sub3(residual + counter, cube_position, goal_cube_position.data()); + counter += 3; + + // ---------- Cube orientation ---------- + double* cube_orientation = SensorByName(model, data, "cube_orientation"); + double* goal_cube_orientation = SensorByName(model, data, "cube_goal_orientation"); + mju_normalize4(goal_cube_orientation); + + mju_subQuat(residual + counter, goal_cube_orientation, cube_orientation); + counter += 3; + + // ---------- Cube linear velocity ---------- + double* cube_linear_velocity = + SensorByName(model, data, "cube_linear_velocity"); + + mju_copy(residual + counter, cube_linear_velocity, 3); + counter += 3; + + // ---------- Control ---------- + mju_copy(residual + counter, data->actuator_force, model->nu); + counter += model->nu; + + // ---------- Residual () ---------- + mju_sub(residual + counter, data->qpos + 7, model->key_qpos + 7, 16); + counter += 16; + + // ---------- Residual () ---------- + mju_copy(residual + counter, data->qvel + 6, 16); + counter += 16; + + // Sanity check + CheckSensorDim(model, counter); +} + +void AllegroCube::TransitionLocked(mjModel* model, mjData* data) { + // Check for contact between the cube and the floor + int cube = mj_name2id(model, mjOBJ_GEOM, "cube"); + int floor = mj_name2id(model, mjOBJ_GEOM, "floor"); + + bool on_floor = false; + for (int i=0; i < data->ncon; i++) { + mjContact* g = data->contact + i; + if ((g->geom1 == cube && g->geom2 == floor) || + (g->geom2 == cube && g->geom1 == floor)) { + on_floor = true; + break; + } + } + + // If the cube is on the floor and not moving, reset it + double* cube_lin_vel = SensorByName(model, data, "cube_linear_velocity"); + if (on_floor && mju_norm3(cube_lin_vel) < 0.001) { + int cube_body = mj_name2id(model, mjOBJ_BODY, "cube"); + if (cube_body != -1) { + int jnt_qposadr = model->jnt_qposadr[model->body_jntadr[cube_body]]; + int jnt_veladr = model->jnt_dofadr[model->body_jntadr[cube_body]]; + mju_copy(data->qpos + jnt_qposadr, model->qpos0 + jnt_qposadr, 7); + mju_zero(data->qvel + jnt_veladr, 6); + } + + // Step the simulation forward + mutex_.unlock(); + mj_forward(model, data); + mutex_.lock(); + } + +} + +} // namespace mjpc diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h new file mode 100644 index 000000000..4b2d71792 --- /dev/null +++ b/mjpc/tasks/allegro/allegro.h @@ -0,0 +1,37 @@ +#ifndef MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ +#define MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ + +#include + +#include +#include "mjpc/task.h" + +namespace mjpc { +class AllegroCube : public Task { + public: + std::string Name() const override; + std::string XmlPath() const override; + + class ResidualFn : public BaseResidualFn { + public: + explicit ResidualFn(const AllegroCube* task) : BaseResidualFn(task) {} + void Residual(const mjModel* model, const mjData* data, + double* residual) const override; + }; + AllegroCube() : residual_(this) {} + + // Reset the cube into the hand if it's on the floor + void TransitionLocked(mjModel* model, mjData* data) override; + + protected: + std::unique_ptr ResidualLocked() const override { + return std::make_unique(this); + } + ResidualFn* InternalResidual() override { return &residual_; } + + private: + ResidualFn residual_; +}; +} // namespace mjpc + +#endif // MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ diff --git a/mjpc/tasks/allegro/assets/fileback.png b/mjpc/tasks/allegro/assets/fileback.png new file mode 100644 index 0000000000000000000000000000000000000000..e03322fcdad34c3e10f97f35a48ceae63e80cf05 GIT binary patch literal 8601 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 CgQnX6 literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/filedown.png b/mjpc/tasks/allegro/assets/filedown.png new file mode 100644 index 0000000000000000000000000000000000000000..ee48edf648e069f61fdce7253d48bf92ce075010 GIT binary patch literal 9816 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 literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/fileleft.png b/mjpc/tasks/allegro/assets/fileleft.png new file mode 100644 index 0000000000000000000000000000000000000000..da6427bf7f676180038c926e009b910d2e98ceed GIT binary patch literal 7959 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 T`t}0X(;%YZd4tk3PIvzc3F1Cn literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/fileright.png b/mjpc/tasks/allegro/assets/fileright.png new file mode 100644 index 0000000000000000000000000000000000000000..6c2cb391ba608f08d92c5ffb75b678529d738891 GIT binary patch literal 1406 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 YBI>?&1-5SF9K43HHhAl&mfzp{F95r0b^rhX literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/grayback.png b/mjpc/tasks/allegro/assets/grayback.png new file mode 100644 index 0000000000000000000000000000000000000000..03ae4bf72984a2dc1c0bdab844b0dec769577a85 GIT binary patch literal 8356 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 literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/graydown.png b/mjpc/tasks/allegro/assets/graydown.png new file mode 100644 index 0000000000000000000000000000000000000000..b8b7b3142a7e0838a40e8ca3e8870f215a6fa44a GIT binary patch literal 9630 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 literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/grayleft.png b/mjpc/tasks/allegro/assets/grayleft.png new file mode 100644 index 0000000000000000000000000000000000000000..2625e739889f732556dc56995a7ac112a8caaa20 GIT binary patch literal 5126 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 Ss>2jgfZ5wPgO8|(Q~nJ=71`bZ literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/grayright.png b/mjpc/tasks/allegro/assets/grayright.png new file mode 100644 index 0000000000000000000000000000000000000000..4516b6016b4abdf02d4f5196587f26ad2113108c GIT binary patch literal 1237 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKL96$kvrB^ZqfD}u*qpu?a!^VE@KZ&eBK2wsn zy9>kr_Wm>bfjrIvkH}&M25w;xW@MN(M*=9wUgGKN%KnU7T7-r5vqtB11_tIYo-U3d z6}R5r-I&W1DB$2|5YC|+u_@!!#@R(q%2OC*1DG0v^**L<*PoG@@V(;J8*dqXcCTrN z-+$rS^Ls{IgQ;T@OQ)cU+XRV0#E48gUT?d+zM;M*j=gOcB~Fv9yS;nw{o1PLxjQK_ zhE4%AhJsi?`HKPN<1~=;r6}TU%o$INJ;RL7b(=xb^P=fwl#kk#XES8+Xhuy0gD9H64!{5 zl*E!$tK_0oAjM#0U}U6gXsBys6k=#-1wxkE1_o9J249RaI#4v^=BH$)RpQprnt#Cr PsDZ)L)z4*}Q$iB}$1`dj literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/assets/grayup.png b/mjpc/tasks/allegro/assets/grayup.png new file mode 100644 index 0000000000000000000000000000000000000000..0b07c030b724dcadcf1d7702028b9ac514d8e5a9 GIT binary patch literal 2788 zcmeHJYd8}O8=k`6=4JJkBARt@D#y*c+Pv&tIZTB}+9C`a((5pkLyfktkP4IILWNM` z6>~^4XKIt8jE(s)hZ1|WIUn}v`}h6${(jf@UDtPA&;8ujeLvUz=eeFAPvSWTTV>FG z5C8yBw!>OE0|0U;60Qjv36D z>tm>poV_%aXNkk!9|W5+o&r^FtmQHt5yU!je;;00&9z3DBghXlzpg=S#o`=5@^V6< zRjO@~mOWPIDG-{e|IUbe zdIwyt;>Ycg$$R9h@nb2}HaV6m7Bhz6;1u<>GXZ~OXxwXr@=tNOt8cX}TcKYv9|{c$ zo6Jj8bQh%2oo3h%kY0OFD~&$raMl^MT+uH@J>NB*9gXQivx47I-u1!=x)E7)B8SkQ zGw*Tqu3w4`Ik9Hk{|-K|FW4jx(`$T;1h&)C>qKC?kfIYC2WQ~QbW2}ll>_k-*A7(i zy3M${FN%e=N}-8J-VXkLd%qY8uS@H4TII*IidBGNvD5JJEan92@vQWa zq^*05_Si48#oQ7p@m&-laRS?QJ8cRxm@dUQkq z=ksTL^;uZ4V{xUZOxNelZ8Df1%6(;@A1~mmn|BpTki%$fgc0kkxRi5_!ohXK0C!~N zeevjknM2s;XD8R=*xyW2&aBf6L_?YNrmLY+N)OH-akKbr^EMq5PE=pSrrL@Lg6!ae zYzV8|MjhhdrzB1zJF6LCx$KO2iyALE%sWqC12de~?9#$}W8|6Pr2$B$HMhQwF40&R zOmk8p{B^{STz+>=-$Dm#ICG_KQ_u06j1!FuY$t}f?}Z%;5T<%f4R$I1nHOoFt z5FG&JC4VjG?}+UOr#Sjn%(#>}W#w)rp{-MTdgNxxQ0&i|31& zwsL|t1CuUa?KMcdaE|aIu5^z|f9?0F_mt^n|5a@Q=IYU<$3&8@TW7c9Z-rW$t5*|x zfXC$a*?S}@c`FG{om~_TqMlP)7>oIyGBpy3(O*k&(>Cd{3M{b&Ke+Dk^OfT{UaKPU z{g+QBZ5X(umA?`9?r;0LyVatpe|Rl0_MAGoqdzToByScRr7uInLp9oiPx1qYg28KM zUCp=O`L z3yC~#3+)l5r6@Hqn&tY^g)>23=vH{ViLc;UpwZ?Q$oiH1*6K}-*VZS&coOq-=kd+b zni2JOn$p7Orf$M~EQ9BMAJR-r|6B*gk@jk}J=3}a9;Lp!^y#>?cC5BTvjj`*4keY% z$RRp3Crd7D7`*`=Oz4)Um^PNo=dRr^xVVctAYFI+fOPUv=If!5Ir{DQ8Ti~9&v-1vLK0Gn!fLwq88xigeH zAR;5ZRnAs@Kkgah;FK`{`nbK$pGZ0E^=f`4cztsXs$3nPg(ucWPp|6=nX$1Gi|AV9 zxtN4(L*tD(B)YE+^i?^a+MPe z_n9j=Uj`qGcsN(y=4tmv5tcA0ZB1j>+Aa_H5mzAN)JfH5c4_RV{>21K`5wxyaNP*S zX^1z8#Nl)b8g9qNR2Ul)8Z$g;Z{oAE2S+)X3Y6(9MnN* z!>w`QzJzch%7;wcA^^+;1~W7@HH5)jOifWg3VF=L1Z83(h50A^OW==S-vCn7zYp9F S{$REh0N7bOSe2jjqW%NO1GrfL literal 0 HcmV?d00001 diff --git a/mjpc/tasks/allegro/cube.xml b/mjpc/tasks/allegro/cube.xml new file mode 100644 index 000000000..e30185c87 --- /dev/null +++ b/mjpc/tasks/allegro/cube.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mjpc/tasks/allegro/right_hand.xml b/mjpc/tasks/allegro/right_hand.xml new file mode 100644 index 000000000..296995fd5 --- /dev/null +++ b/mjpc/tasks/allegro/right_hand.xml @@ -0,0 +1,270 @@ + + + + + diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml new file mode 100644 index 000000000..edcf87a90 --- /dev/null +++ b/mjpc/tasks/allegro/task.xml @@ -0,0 +1,83 @@ + + + + + + From 372385f240c09a940ed2b8e6fefa1f687fa5b30b Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 13:01:11 -0800 Subject: [PATCH 02/23] fixed missing Allegro task --- mjpc/tasks/allegro/allegro.cc | 8 ++++---- mjpc/tasks/allegro/allegro.h | 12 ++++++------ mjpc/tasks/tasks.cc | 2 ++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index 94718f074..142cab646 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -10,10 +10,10 @@ #include "mjpc/utilities.h" namespace mjpc { -std::string AllegroCube::XmlPath() const { +std::string Allegro::XmlPath() const { return GetModelPath("allegro/task.xml"); } -std::string AllegroCube::Name() const { return "AllegroCube"; } +std::string Allegro::Name() const { return "Allegro"; } // ------- Residuals for cube manipulation task ------ // Cube position: (3) @@ -21,7 +21,7 @@ std::string AllegroCube::Name() const { return "AllegroCube"; } // Cube linear velocity: (3) // Control: u // ------------------------------------------ -void AllegroCube::ResidualFn::Residual(const mjModel* model, const mjData* data, +void Allegro::ResidualFn::Residual(const mjModel* model, const mjData* data, double* residual) const { int counter = 0; @@ -64,7 +64,7 @@ void AllegroCube::ResidualFn::Residual(const mjModel* model, const mjData* data, CheckSensorDim(model, counter); } -void AllegroCube::TransitionLocked(mjModel* model, mjData* data) { +void Allegro::TransitionLocked(mjModel* model, mjData* data) { // Check for contact between the cube and the floor int cube = mj_name2id(model, mjOBJ_GEOM, "cube"); int floor = mj_name2id(model, mjOBJ_GEOM, "floor"); diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h index 4b2d71792..1d8cc368e 100644 --- a/mjpc/tasks/allegro/allegro.h +++ b/mjpc/tasks/allegro/allegro.h @@ -1,5 +1,5 @@ -#ifndef MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ -#define MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ +#ifndef MJPC_TASKS_ALLEGRO_ALLEGRO_H_ +#define MJPC_TASKS_ALLEGRO_ALLEGRO_H_ #include @@ -7,18 +7,18 @@ #include "mjpc/task.h" namespace mjpc { -class AllegroCube : public Task { +class Allegro : public Task { public: std::string Name() const override; std::string XmlPath() const override; class ResidualFn : public BaseResidualFn { public: - explicit ResidualFn(const AllegroCube* task) : BaseResidualFn(task) {} + explicit ResidualFn(const Allegro* task) : BaseResidualFn(task) {} void Residual(const mjModel* model, const mjData* data, double* residual) const override; }; - AllegroCube() : residual_(this) {} + Allegro() : residual_(this) {} // Reset the cube into the hand if it's on the floor void TransitionLocked(mjModel* model, mjData* data) override; @@ -34,4 +34,4 @@ class AllegroCube : public Task { }; } // namespace mjpc -#endif // MJPC_TASKS_ALLEGROCUBE_ALLEGROCUBE_H_ +#endif // MJPC_TASKS_ALLEGRO_ALLEGRO_H_ diff --git a/mjpc/tasks/tasks.cc b/mjpc/tasks/tasks.cc index 9b1c773e4..1aea4b9af 100644 --- a/mjpc/tasks/tasks.cc +++ b/mjpc/tasks/tasks.cc @@ -18,6 +18,7 @@ #include #include "mjpc/tasks/acrobot/acrobot.h" +#include "mjpc/tasks/allegro/allegro.h" #include "mjpc/tasks/cartpole/cartpole.h" #include "mjpc/tasks/fingers/fingers.h" #include "mjpc/tasks/hand/hand.h" @@ -38,6 +39,7 @@ namespace mjpc { std::vector> GetTasks() { return { std::make_shared(), + std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), From b841d3e972663b006a2573639574ddd2b47c60ce Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 13:01:37 -0800 Subject: [PATCH 03/23] fixed source paths in setup.py to include pngs --- python/setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 33453fdb8..38437968d 100644 --- a/python/setup.py +++ b/python/setup.py @@ -150,7 +150,11 @@ def finalize_options(self): def run(self): mjpc_tasks_path = Path(__file__).parent.parent / "mjpc" / "tasks" - source_paths = tuple(mjpc_tasks_path.rglob("*.xml")) + source_paths = ( + tuple(mjpc_tasks_path.rglob("*.xml")) + + tuple(mjpc_tasks_path.rglob("*.png")) + + tuple(mjpc_tasks_path.rglob("*.stl")) + ) relative_source_paths = tuple(p.relative_to(mjpc_tasks_path) for p in source_paths) assert self.build_lib is not None build_lib_path = Path(self.build_lib).resolve() From a7d04a6722805e94253502a2239016b41bc8be32 Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 13:03:28 -0800 Subject: [PATCH 04/23] remove stls --- python/setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 38437968d..6fec66aa3 100644 --- a/python/setup.py +++ b/python/setup.py @@ -153,7 +153,6 @@ def run(self): source_paths = ( tuple(mjpc_tasks_path.rglob("*.xml")) + tuple(mjpc_tasks_path.rglob("*.png")) - + tuple(mjpc_tasks_path.rglob("*.stl")) ) relative_source_paths = tuple(p.relative_to(mjpc_tasks_path) for p in source_paths) assert self.build_lib is not None From cc9ee26a67c9e071ebab928d3d628972121a77c2 Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 17:06:00 -0800 Subject: [PATCH 05/23] add license info to files --- mjpc/tasks/allegro/allegro.cc | 14 ++++++++++++++ mjpc/tasks/allegro/allegro.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index 142cab646..fc460eca3 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -1,3 +1,17 @@ +// Copyright 2022 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "mjpc/tasks/allegro/allegro.h" #include diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h index 1d8cc368e..14c10e1e6 100644 --- a/mjpc/tasks/allegro/allegro.h +++ b/mjpc/tasks/allegro/allegro.h @@ -1,3 +1,17 @@ +// Copyright 2022 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef MJPC_TASKS_ALLEGRO_ALLEGRO_H_ #define MJPC_TASKS_ALLEGRO_ALLEGRO_H_ From 432c83cf0f6f491d7fb1df9249f0919d0f93592e Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 17:58:28 -0800 Subject: [PATCH 06/23] style changes with clang-format extension, cpplint --- mjpc/tasks/allegro/allegro.cc | 30 +++++++++++++++--------------- mjpc/tasks/allegro/allegro.h | 24 ++++++++++++------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index fc460eca3..0864791c0 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -13,13 +13,13 @@ // limitations under the License. #include "mjpc/tasks/allegro/allegro.h" -#include + +#include #include #include #include -#include #include "mjpc/task.h" #include "mjpc/utilities.h" @@ -35,28 +35,29 @@ std::string Allegro::Name() const { return "Allegro"; } // Cube linear velocity: (3) // Control: u // ------------------------------------------ -void Allegro::ResidualFn::Residual(const mjModel* model, const mjData* data, - double* residual) const { +void Allegro::ResidualFn::Residual(const mjModel *model, const mjData *data, + double *residual) const { int counter = 0; // ---------- Cube position ---------- // TODO(vincekurtz): specify goal position in a better way - double* cube_position = SensorByName(model, data, "cube_position"); + double *cube_position = SensorByName(model, data, "cube_position"); std::vector goal_cube_position = {0.3, 0.0, 0.025}; mju_sub3(residual + counter, cube_position, goal_cube_position.data()); counter += 3; // ---------- Cube orientation ---------- - double* cube_orientation = SensorByName(model, data, "cube_orientation"); - double* goal_cube_orientation = SensorByName(model, data, "cube_goal_orientation"); + double *cube_orientation = SensorByName(model, data, "cube_orientation"); + double *goal_cube_orientation = + SensorByName(model, data, "cube_goal_orientation"); mju_normalize4(goal_cube_orientation); mju_subQuat(residual + counter, goal_cube_orientation, cube_orientation); counter += 3; // ---------- Cube linear velocity ---------- - double* cube_linear_velocity = + double *cube_linear_velocity = SensorByName(model, data, "cube_linear_velocity"); mju_copy(residual + counter, cube_linear_velocity, 3); @@ -78,14 +79,14 @@ void Allegro::ResidualFn::Residual(const mjModel* model, const mjData* data, CheckSensorDim(model, counter); } -void Allegro::TransitionLocked(mjModel* model, mjData* data) { +void Allegro::TransitionLocked(mjModel *model, mjData *data) { // Check for contact between the cube and the floor int cube = mj_name2id(model, mjOBJ_GEOM, "cube"); int floor = mj_name2id(model, mjOBJ_GEOM, "floor"); - + bool on_floor = false; - for (int i=0; i < data->ncon; i++) { - mjContact* g = data->contact + i; + for (int i = 0; i < data->ncon; i++) { + mjContact *g = data->contact + i; if ((g->geom1 == cube && g->geom2 == floor) || (g->geom2 == cube && g->geom1 == floor)) { on_floor = true; @@ -94,7 +95,7 @@ void Allegro::TransitionLocked(mjModel* model, mjData* data) { } // If the cube is on the floor and not moving, reset it - double* cube_lin_vel = SensorByName(model, data, "cube_linear_velocity"); + double *cube_lin_vel = SensorByName(model, data, "cube_linear_velocity"); if (on_floor && mju_norm3(cube_lin_vel) < 0.001) { int cube_body = mj_name2id(model, mjOBJ_BODY, "cube"); if (cube_body != -1) { @@ -109,7 +110,6 @@ void Allegro::TransitionLocked(mjModel* model, mjData* data) { mj_forward(model, data); mutex_.lock(); } - } -} // namespace mjpc +} // namespace mjpc diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h index 14c10e1e6..b33b9ee04 100644 --- a/mjpc/tasks/allegro/allegro.h +++ b/mjpc/tasks/allegro/allegro.h @@ -17,35 +17,35 @@ #include -#include #include "mjpc/task.h" +#include namespace mjpc { class Allegro : public Task { - public: +public: std::string Name() const override; std::string XmlPath() const override; class ResidualFn : public BaseResidualFn { - public: - explicit ResidualFn(const Allegro* task) : BaseResidualFn(task) {} - void Residual(const mjModel* model, const mjData* data, - double* residual) const override; + public: + explicit ResidualFn(const Allegro *task) : BaseResidualFn(task) {} + void Residual(const mjModel *model, const mjData *data, + double *residual) const override; }; Allegro() : residual_(this) {} // Reset the cube into the hand if it's on the floor - void TransitionLocked(mjModel* model, mjData* data) override; + void TransitionLocked(mjModel *model, mjData *data) override; - protected: +protected: std::unique_ptr ResidualLocked() const override { return std::make_unique(this); } - ResidualFn* InternalResidual() override { return &residual_; } + ResidualFn *InternalResidual() override { return &residual_; } - private: +private: ResidualFn residual_; }; -} // namespace mjpc +} // namespace mjpc -#endif // MJPC_TASKS_ALLEGRO_ALLEGRO_H_ +#endif // MJPC_TASKS_ALLEGRO_ALLEGRO_H_ From 480c0dc178145f43d21a32cf385a6a21172fd1f7 Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 18:01:28 -0800 Subject: [PATCH 07/23] added more descriptive/correct residual comments --- mjpc/tasks/allegro/allegro.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index 0864791c0..a05dd7555 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -33,7 +33,9 @@ std::string Allegro::Name() const { return "Allegro"; } // Cube position: (3) // Cube orientation: (3) // Cube linear velocity: (3) -// Control: u +// Control: (16), there are 16 servos +// Nominal pose: (16) +// Joint velocity: (16) // ------------------------------------------ void Allegro::ResidualFn::Residual(const mjModel *model, const mjData *data, double *residual) const { @@ -67,11 +69,11 @@ void Allegro::ResidualFn::Residual(const mjModel *model, const mjData *data, mju_copy(residual + counter, data->actuator_force, model->nu); counter += model->nu; - // ---------- Residual () ---------- + // ---------- Nominal Pose ---------- mju_sub(residual + counter, data->qpos + 7, model->key_qpos + 7, 16); counter += 16; - // ---------- Residual () ---------- + // ---------- Joint Velocity ---------- mju_copy(residual + counter, data->qvel + 6, 16); counter += 16; From 0b93ab625404ddad7a36392a14906d751e8d0f1e Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 20:46:34 -0800 Subject: [PATCH 08/23] added sensor/site for cube goal position, removed hardcoded goal --- mjpc/tasks/allegro/allegro.cc | 9 ++++----- mjpc/tasks/allegro/right_hand.xml | 1 + mjpc/tasks/allegro/task.xml | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index a05dd7555..64775bb68 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -42,11 +42,10 @@ void Allegro::ResidualFn::Residual(const mjModel *model, const mjData *data, int counter = 0; // ---------- Cube position ---------- - // TODO(vincekurtz): specify goal position in a better way - double *cube_position = SensorByName(model, data, "cube_position"); - std::vector goal_cube_position = {0.3, 0.0, 0.025}; + double* cube_position = SensorByName(model, data, "cube_position"); + double* cube_goal_position = SensorByName(model, data, "cube_goal_position"); - mju_sub3(residual + counter, cube_position, goal_cube_position.data()); + mju_sub3(residual + counter, cube_position, cube_goal_position); counter += 3; // ---------- Cube orientation ---------- @@ -114,4 +113,4 @@ void Allegro::TransitionLocked(mjModel *model, mjData *data) { } } -} // namespace mjpc +} // namespace mjpc diff --git a/mjpc/tasks/allegro/right_hand.xml b/mjpc/tasks/allegro/right_hand.xml index 296995fd5..eeec9d0cc 100644 --- a/mjpc/tasks/allegro/right_hand.xml +++ b/mjpc/tasks/allegro/right_hand.xml @@ -127,6 +127,7 @@ + diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index edcf87a90..96d89c88a 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -71,6 +71,7 @@ + From 09d6a5a40e6cfb73e926c05eba86bb89b0f12608 Mon Sep 17 00:00:00 2001 From: alberthli Date: Thu, 11 Jan 2024 20:47:28 -0800 Subject: [PATCH 09/23] style enforced with the clang-format extension --- mjpc/tasks/allegro/allegro.cc | 4 ++-- mjpc/tasks/allegro/allegro.h | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/mjpc/tasks/allegro/allegro.cc b/mjpc/tasks/allegro/allegro.cc index 64775bb68..383405f25 100644 --- a/mjpc/tasks/allegro/allegro.cc +++ b/mjpc/tasks/allegro/allegro.cc @@ -42,8 +42,8 @@ void Allegro::ResidualFn::Residual(const mjModel *model, const mjData *data, int counter = 0; // ---------- Cube position ---------- - double* cube_position = SensorByName(model, data, "cube_position"); - double* cube_goal_position = SensorByName(model, data, "cube_goal_position"); + double *cube_position = SensorByName(model, data, "cube_position"); + double *cube_goal_position = SensorByName(model, data, "cube_goal_position"); mju_sub3(residual + counter, cube_position, cube_goal_position); counter += 3; diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h index b33b9ee04..251119fba 100644 --- a/mjpc/tasks/allegro/allegro.h +++ b/mjpc/tasks/allegro/allegro.h @@ -15,19 +15,20 @@ #ifndef MJPC_TASKS_ALLEGRO_ALLEGRO_H_ #define MJPC_TASKS_ALLEGRO_ALLEGRO_H_ +#include + #include #include "mjpc/task.h" -#include namespace mjpc { class Allegro : public Task { -public: + public: std::string Name() const override; std::string XmlPath() const override; class ResidualFn : public BaseResidualFn { - public: + public: explicit ResidualFn(const Allegro *task) : BaseResidualFn(task) {} void Residual(const mjModel *model, const mjData *data, double *residual) const override; @@ -37,15 +38,15 @@ class Allegro : public Task { // Reset the cube into the hand if it's on the floor void TransitionLocked(mjModel *model, mjData *data) override; -protected: + protected: std::unique_ptr ResidualLocked() const override { return std::make_unique(this); } ResidualFn *InternalResidual() override { return &residual_; } -private: + private: ResidualFn residual_; }; -} // namespace mjpc +} // namespace mjpc -#endif // MJPC_TASKS_ALLEGRO_ALLEGRO_H_ +#endif // MJPC_TASKS_ALLEGRO_ALLEGRO_H_ From 4b60ae1bdace54f043b6bee09d9c6bde0fcb2447 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Fri, 12 Jan 2024 14:48:32 -0700 Subject: [PATCH 10/23] cube assets, minor fix --- mjpc/tasks/allegro/allegro.h | 4 ++-- mjpc/tasks/allegro/cube.xml | 14 +++++++------- mjpc/tasks/allegro/task.xml | 15 --------------- .../assets => assets/cube}/fileback.png | Bin .../assets => assets/cube}/filedown.png | Bin .../assets => assets/cube}/filefront.png | Bin .../assets => assets/cube}/fileleft.png | Bin .../assets => assets/cube}/fileright.png | Bin .../{allegro/assets => assets/cube}/fileup.png | Bin .../assets => assets/cube}/grayback.png | Bin .../assets => assets/cube}/graydown.png | Bin .../assets => assets/cube}/grayfront.png | Bin .../assets => assets/cube}/grayleft.png | Bin .../assets => assets/cube}/grayright.png | Bin .../{allegro/assets => assets/cube}/grayup.png | Bin mjpc/tasks/hand/assets/fileback.png | Bin 8601 -> 0 bytes mjpc/tasks/hand/assets/filedown.png | Bin 9816 -> 0 bytes mjpc/tasks/hand/assets/filefront.png | Bin 10155 -> 0 bytes mjpc/tasks/hand/assets/fileleft.png | Bin 7959 -> 0 bytes mjpc/tasks/hand/assets/fileright.png | Bin 1406 -> 0 bytes mjpc/tasks/hand/assets/fileup.png | Bin 3973 -> 0 bytes mjpc/tasks/hand/assets/grayback.png | Bin 8356 -> 0 bytes mjpc/tasks/hand/assets/graydown.png | Bin 9630 -> 0 bytes mjpc/tasks/hand/assets/grayfront.png | Bin 9535 -> 0 bytes mjpc/tasks/hand/assets/grayleft.png | Bin 5126 -> 0 bytes mjpc/tasks/hand/assets/grayright.png | Bin 1237 -> 0 bytes mjpc/tasks/hand/assets/grayup.png | Bin 2788 -> 0 bytes mjpc/tasks/hand/cube.xml | 14 +++++++------- 28 files changed, 16 insertions(+), 31 deletions(-) rename mjpc/tasks/{allegro/assets => assets/cube}/fileback.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/filedown.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/filefront.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/fileleft.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/fileright.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/fileup.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/grayback.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/graydown.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/grayfront.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/grayleft.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/grayright.png (100%) rename mjpc/tasks/{allegro/assets => assets/cube}/grayup.png (100%) delete mode 100644 mjpc/tasks/hand/assets/fileback.png delete mode 100644 mjpc/tasks/hand/assets/filedown.png delete mode 100644 mjpc/tasks/hand/assets/filefront.png delete mode 100644 mjpc/tasks/hand/assets/fileleft.png delete mode 100644 mjpc/tasks/hand/assets/fileright.png delete mode 100644 mjpc/tasks/hand/assets/fileup.png delete mode 100644 mjpc/tasks/hand/assets/grayback.png delete mode 100644 mjpc/tasks/hand/assets/graydown.png delete mode 100644 mjpc/tasks/hand/assets/grayfront.png delete mode 100644 mjpc/tasks/hand/assets/grayleft.png delete mode 100644 mjpc/tasks/hand/assets/grayright.png delete mode 100644 mjpc/tasks/hand/assets/grayup.png diff --git a/mjpc/tasks/allegro/allegro.h b/mjpc/tasks/allegro/allegro.h index 251119fba..046b6a63d 100644 --- a/mjpc/tasks/allegro/allegro.h +++ b/mjpc/tasks/allegro/allegro.h @@ -15,10 +15,10 @@ #ifndef MJPC_TASKS_ALLEGRO_ALLEGRO_H_ #define MJPC_TASKS_ALLEGRO_ALLEGRO_H_ -#include - +#include #include +#include #include "mjpc/task.h" namespace mjpc { diff --git a/mjpc/tasks/allegro/cube.xml b/mjpc/tasks/allegro/cube.xml index e30185c87..3088dd635 100644 --- a/mjpc/tasks/allegro/cube.xml +++ b/mjpc/tasks/allegro/cube.xml @@ -1,14 +1,14 @@ + fileup="../assets/cube/fileup.png" fileback="../assets/cube/fileback.png" + filedown="../assets/cube/filedown.png" filefront="../assets/cube/filefront.png" + fileleft="../assets/cube/fileleft.png" fileright="../assets/cube/fileright.png"/> - + diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 96d89c88a..95c37a84b 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -48,21 +48,6 @@ - diff --git a/mjpc/tasks/allegro/assets/fileback.png b/mjpc/tasks/assets/cube/fileback.png similarity index 100% rename from mjpc/tasks/allegro/assets/fileback.png rename to mjpc/tasks/assets/cube/fileback.png diff --git a/mjpc/tasks/allegro/assets/filedown.png b/mjpc/tasks/assets/cube/filedown.png similarity index 100% rename from mjpc/tasks/allegro/assets/filedown.png rename to mjpc/tasks/assets/cube/filedown.png diff --git a/mjpc/tasks/allegro/assets/filefront.png b/mjpc/tasks/assets/cube/filefront.png similarity index 100% rename from mjpc/tasks/allegro/assets/filefront.png rename to mjpc/tasks/assets/cube/filefront.png diff --git a/mjpc/tasks/allegro/assets/fileleft.png b/mjpc/tasks/assets/cube/fileleft.png similarity index 100% rename from mjpc/tasks/allegro/assets/fileleft.png rename to mjpc/tasks/assets/cube/fileleft.png diff --git a/mjpc/tasks/allegro/assets/fileright.png b/mjpc/tasks/assets/cube/fileright.png similarity index 100% rename from mjpc/tasks/allegro/assets/fileright.png rename to mjpc/tasks/assets/cube/fileright.png diff --git a/mjpc/tasks/allegro/assets/fileup.png b/mjpc/tasks/assets/cube/fileup.png similarity index 100% rename from mjpc/tasks/allegro/assets/fileup.png rename to mjpc/tasks/assets/cube/fileup.png diff --git a/mjpc/tasks/allegro/assets/grayback.png b/mjpc/tasks/assets/cube/grayback.png similarity index 100% rename from mjpc/tasks/allegro/assets/grayback.png rename to mjpc/tasks/assets/cube/grayback.png diff --git a/mjpc/tasks/allegro/assets/graydown.png b/mjpc/tasks/assets/cube/graydown.png similarity index 100% rename from mjpc/tasks/allegro/assets/graydown.png rename to mjpc/tasks/assets/cube/graydown.png diff --git a/mjpc/tasks/allegro/assets/grayfront.png b/mjpc/tasks/assets/cube/grayfront.png similarity index 100% rename from mjpc/tasks/allegro/assets/grayfront.png rename to mjpc/tasks/assets/cube/grayfront.png diff --git a/mjpc/tasks/allegro/assets/grayleft.png b/mjpc/tasks/assets/cube/grayleft.png similarity index 100% rename from mjpc/tasks/allegro/assets/grayleft.png rename to mjpc/tasks/assets/cube/grayleft.png diff --git a/mjpc/tasks/allegro/assets/grayright.png b/mjpc/tasks/assets/cube/grayright.png similarity index 100% rename from mjpc/tasks/allegro/assets/grayright.png rename to mjpc/tasks/assets/cube/grayright.png diff --git a/mjpc/tasks/allegro/assets/grayup.png b/mjpc/tasks/assets/cube/grayup.png similarity index 100% rename from mjpc/tasks/allegro/assets/grayup.png rename to mjpc/tasks/assets/cube/grayup.png diff --git a/mjpc/tasks/hand/assets/fileback.png b/mjpc/tasks/hand/assets/fileback.png deleted file mode 100644 index e03322fcdad34c3e10f97f35a48ceae63e80cf05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8601 zcmcI|WmuG5*ES#$3W!Qe45c*Ejii(yCEX#?$k5F#prC+sGe|cK9S)#$OE(Be2@D`H zNWRxx+|Tp<`Tl+1dl1L5_qF$mbFFi&y?3~}ngZb+syi4M7=%iSa+(+zn4i&qcsRgJ zP^;ho1_qIykG7thrnx7?#nt(>t%Ehh&D+HqV(n%78Uw>?b~n|~^;biz+%-HxA1erh zxXpE+zgeuIANG(buUIp0JP&zAS*?*O7jCt3AGy5zEq?C$a`^3ayY8r-ai4(-d*@+- zfgSu%1HsliPXY%%w-qlfVuSCBugPUK~oDH$DwO z{D1{p_&@dnX|bh3bt`Ziqn#DshAD_^??6? zPrkx{sJ?m@lvT~fq)AZ&AW3AsDjle&@!$%IYlu%J9Q#P<2_Xzd&R@{H*kh72c4 zvx`<-EH18`9Z%`9dpfHGLauLXUgM8n-5y2W*_^xmH%Q(4S&KN`pXfuRjUxAaKx$(= zDkV^4PXVuW=P#kaxunem^aRnIdB>1zIDfIu^|H&qJ=+~ovai`vT|wsHD`1ikpWN06 znfWOod-p!YOGWcgTD9q^w_&{xwB|KLx`cB=wuJRDb2`1hrSFicX=9jZV*1M9E<5;{ zsx;&~PPy@EKQ{RyI{lDh;PfEc1o_fQwEIB>#uQ2qUjAm_HEEa;-Vm&?QPNXeWu-m!t|7a8t#GrC4qJ*%%0%bR9@i#Zh5j14tAEV$P% z+|w3w9qlckmN@43JQK6KSK5kb2{!Oj|46Rsk<*gXr9V+m|4*-y;D8iIKE_WwJnXkT zRIgjY;(lK+zRMo{Zp3A*S!?T~u9OMHmGH+?C^CB}M9TNYe@ZVK$*wnicxXF9*075%7~3bKvDq0 zHYC$BRcu>a>G^<(S#su&q?0(`{@#g%-o&D(&jw{|cbZLNwiqkZ;|J?6gx4z{f10dX z*>qIi(QD-MaI;jala@9N%|Wu%;ZO(*r`eQS{?5jU8lO>Fto|Ipc)w`mcW+ob6ZM?G zV25%+U#}yFO2X=t8a8x;cdF2VllZW1PFmRjU%?3ZMW?@=(&}jkg{pYbd#N1)?anY{S=R^Drm6D@cm{ukxu#uh+bqC48A`7 zm%sU)!|fKalP5!w*jt~<+CySdQb>&PhapYIGPtqnR6|_Wr8V90gKsMvw+Rth{fuFH zZksRG_)|EOaT%m8kFa0Zhe~=EMhtKg_ocn1*P-89T$+U-lNinTbJo z;-32CsRqxvG6ZI2?x#ZGBt?Ip)({}vohyE+snO|P6?AiczQ-+0>h0-6rbC&(ww3hz zjKHPZv95e1o_)lrhw0I6oYC1ygA{mfMAbV7N}ebNMB)#;4agl4Pp`iHyxSOcesm-S z0!sbfeKM;BOKEJecjBCSYP1Cz7sO?!VASUMGvM4s@0H5f{h6cM z$%sGH%!8y`n#z#3MY9K;?==;OKYz5)Q7w&Kv=di$J0?#=SdFSy-NU|6)`1pZarJaBEPUl#9sVm)4-mc&N?lo~;_QC;zhttm@g~JglWn%E_sBRJR%%`4QisnN9=g7>D=G(@MV?pw|x$6-7r7s z;wr?LNn&*oC(NAUkMO`DixntX?uq_R;#sE0x^t#O^se_>rz(tjrfRV! z5EQSmI+R#an~v|-=bZ0+M>OL%Y`M}MciiX1-A;HT@Huex$)BcsI~mFNhA9s;7sAC# z)fKEFla_``ndlkiRu$?td>ig&DAEJ;yud9s^+?RgKih_dJ>5t*%zirFjguIYiC}BYKHV4-; zk0r2VsI|n-&hS1n_w#trvn2QZYez?V9;2oHV^yL{t?SV^f5+Z=m~T}DXG*igjNW65 zle+bXU1>dL9fjN{Kiw9p`e!!hJ~uN-L&VNzg=U%O=`Iwm6$Sg*n2I`Am_+CrN2EPzBH?9TYf6&-Pg>ck-IOI zSzjg2v(_m!(expUxny5e$!3Rd<+6YCf<1q)c8kOYQ)rHi-0`-Ogfpj`QstPO*(=wc zD=Y!O)7Jw!%Mq~EmAiJjMM!Ide+Wo^;*sQ!yibxjY)Z*z@>zM;GL!sFv1o>VuJCbD9n@+c3-$!Ln=pXtyhqEFMZ%N z6$!H4qD0^gSA*0xx9)1x42S=Y#<$84#iZ}V%?PEQKChiDzB56r=KIO&GqQfaP@cj5 z@l)|zp&Z@Nw^N9idjEdj3naz-QZ+#<-2(bQ-_)f<|9-Qj%MxVYu(x5H%5{a&qN8nH zk99^TIgXXL#TejG-50GWcHXsCh>uoO7bmhSdHt0tqP`mYv-|FpEk0r1w$Fsb^EZ*l)lct zua742Ks8)i(0Z|znLeRcHZ90a5a*rK&8v3Rset3Y{`vAfnf@E>Reg6jb>x(*+8;iy zxaEmbW0l1wt#+MR$H7?_vinAuPmK}V{)6RTji$tL0EJ3@3HUM?&0is%CV`JbC>(FnUt0y+;JqDsc7O-PMONeLV;ZJd4p6+G z>Bu~O<)>Ul5^_f%Q*k>m!6E%tUj$ZGPUmJ>{ju+G=bgdC11@eXJMUjxoXssvA~Gl8Fw9iX89EryH@+cFl>m{2gf;u%))y#n7lD}Vl zM>=epPj>dD?~7vp5vd2IUOtyQlwPuF9*noe<@9f+FKek8uV~}7~n7Zi^y@^JNqzk(Knaqm>5WF zz^o@$^Xq`gpri-W@H|<{^+4TL|HqV|<;!-thdG{wpVk7bid@n=SaeFmTVD>E|7E!z zWtl$>ldmT_s>D@@@Xu}KjU@dbyLs?%3d(%c$;LA{80+iGf~x+Ldm!x%bQPSdM=%*b{I4SK)W;L@@=)e=ZNrqKYP3Qe*sq%WspQ7q zZ~nL|2YqW}LdU{V7k>3Q-ZtaYV?*A?=SA(FoP8OUlpY7xcW?P}Bu_OJ;(N3U3***@ z`>fxEXQxE54ESB$f{e-1huNNfyZ=ve1Gx3qN=u?=le=4TCNaetvV1Y`1Ffv& z#PKhV!yl41ebOvj;ImJPG$ToHIOnFl8bPJyY|7ypz_#yG-Zo_mMMR!zw{@~zWe+v( zk#}9wZJJW|h>LO^2V%DKZONzAHcbOpO&kjq1v!js^iLL|AP$(pcTv=bVqn~Ti2lRG zNKK~zCUM=ARONAhVNwu0A(YFGRRpFe-Q@M$WSt!yt)1L3WL>Sz-K?!3p0;jpAPP#V z>bk*1aJb6Tf%ew99<8i|!b78rw|hC{dV)A%wQ>UEHP{+WPCav>{1*9aM1` z;4d=p(u+W|HP9v%i3R!|TI1cLtk-yGd2`HzPGhtd9?);j*^e%C*^ zD~ptIajAdpFS(-e#f+`J!@WI6R^M)rKXg6cL$N=inxeUgkw3-xer+?%)gZcFaXBv= z6eQ)rUB5(=F|tK3B?U<<`sn;|rbP0H7y|jc5I@uU!7;;70viv{>Toh*NnyLM9vq-{ z2GT70>r`p6u(7NDdJSqFM6U%NgL||br@HdXw!vk5mhJ2Zs61{TJYwP=dze^QGo_1yLW}yR$?q{RgLjZ=$7Oo(x53~bpWCaA z5p8dDohik~so@(NOAZ6J?*o=MZ;)N^ua~`byMvAG(bm7~DI$6s5T|PB>N{X^{I7(8 z7S1|%rvtR1gNEz@bbQnqSeU^y2lE54o8{ntv7PYA5*qZEoms&aG8jk33L2Yc1p{s< zT71>^^dEh{%2P_v;Dse0=~54H-e76w{vMa#IEX50@XUi_Nq7kyI1hN<7?uO&j)*#T z1cCE)FVE3}Kq_xtecew@u3zT^e17mGr*7SCdrpjg#xtxdfj<)J{@7eFBwgo z#Cy?aqsFeV)tM9_QS_AZ?~<^N+{A4tY&EWSxMQQ=6i!S`tjSvw@PeS6BIca>Wu3{x zw7T+Y^sI*dtbm$bBLhkV?I9ia<;T#VpwF=qKD76JJ!q27sRQj09Fxxaw)7B4Zgy!d zZ%|FLYwCM z)~ytcbx1Dt;^|;^^6G?lYaIb#_-H{Bvzpz&wQl-__p&=EJvHWXh$TYA#IBWH)G`h2 zM?|JEPREvPK*~9F1xF*}Yjjj)42XX7u@>JUY#cuL&VdG0Q5h9+CS3M+eSX8sX6^D| zEux+SZ3lt9Fc($dNsoV&&Fe*C!#c+r5HVw&M-S5~di|qbPDzr(xP2#N01>^5$ClYe zu0XFBAMtQ^a6_Byrk$wM9X^<}A=y0;Ikp9lm*-rqpqk?!xi7md3CEE&s^ zxal@SppePaItOKl${ku=vXR-71 z&=qFsZ=>*a7Y&syrBSshwML*C5Voh=&F}#b8;uV#)B^i+@;v=Vw^90dczCRoKOCb^ z?UpVAOHl`nNnH$}_WsSTYYrgYQqBVtF#+096{oKL>PiDp50w`J$!SNl73iZea4?!~ z`hW1Gltm8tN9iUllJegOtzT@peK-CWuON5<>q*3D4 z<;|Ky@{}*V1n>#>eik9W{aO!%Rw4^nqzZDp=BV5*BK(#!fDh|Or%xvWFg-l16@0~B z`b#x-0O?eyjhlz4XlRfWuaEZ0N4~HNHk8O!(-AVcv2TPG8#~t3Yzcn^k;{V;$%MHB z$%%)Tn``J@Azb@6A8^EZLKfim7TG^RQpzX05?p5qgoFN31#{&C1TPE@TW#>UpH(yg$xDByYzB;La^T`{zBWj5uKmDBZpAd}8VipV*zfz2etBSmx~ z;MYE7wiSC-a)30kWu_fVqM21_Iis4s>eNP_I!Nfnm)&%|+M;$DVq(R0StFK6o_Bv* z$*c09?q30zv9N3@wX2<}C(geDTv^?LQfJ6WL6}2XI%00Mz9OmqDtUbm^x({MfwK$M z3{>vSWX}}P*Y!$F8`4hdvGqlJO0?@Oc8V{kyZ~Ol(09|SsQ?lOGdP#ph)JQqBpv$x z1|9|LCE;q;>sA>b#~F!{y5ACar2%#A=jqzOGAE!!1J1dz?@<;AUUL9o*Zqz;wP-|d zWwLGs67qOpVB7Mrju34UTT{Gybev&1P#Sj?3i9>wu&`KXN~T8ODoKn$Hp3}(JHpEB z(Qs*N$Ln;ym3MI~_CIWnQlp1_PF?VcitumBNCvvdV1w|alZg{O;6iqdI_+vI7f`0w z=4L@81UPGPyXf7ofs%n5yl4R}IhN**@6yGA#evx@;eg(0rH=An*<9QJ;znl^_$<-s zO+7jc=p?@;>Er;FCI=XMemuCW0K`ApxD+NUKOaR0rPus&m@PsizjoboX~25%rrKz$lBa2oO_QYZja{b)Hhjl^7Q2S`y=w|x_81C4I zfATOVVr6rDwM-XefO4No@yco93Qz$?RyH`%Ik;mW#CEbPNe}c*Cj`(|0CzPFSfby` z1^}o6G?xH<$!+xT`n2;m66hk%>y01|<8)y%wtm*?Kv(jCev<|5#_^z|QV=rwjE;wh zP@+?^B?!cSSuMDS0@t0nF9<|!!>*rk`Pp5q!CiLA!RhD6*FfdtaYssk8e-3izrF3t zf&tO^NK-G@4CbD-+>#dBrH@b~`gDo*L3>>1B)nJkZ{S^T{}}`ibix;uM)XFQ=eKey zkVK98^&r~HO^H*Tfi*@z0i!ED)4G8E-3C{lY#CE46l6LzFM|G$=G7Rc&%3%Kp$^YP zkE=p~(^Ra4FAZt44h@hj(RC(BG~-xVxwjs43z(*!Qy&Vp($R5VRf8*yw}~Pz?H;d7 zcDI)$-Jo7amvJVIgmNrRlI^*Ro1-zwEm{u}uGt6#e7ocu{+N(PhR*!ni(uCHE}nNS zz!}O=RJYp@#33Z5`o3XIMw1|T0>mqP&Bx>w(@-`?9eebiMJ3H56@;{h{r@W*0zSKFUuK)Cj{ z0Ni`d2Q8e`Sh=}ViBlJVg8Wf_7jR7giV~;qi72l}1uYuMT9f;a>Pl~%F&SkBPKmMq zg2@HeklY(*!}cF(5ND3dW{e5k6QIf zsxREH_Q2wNRJJIhM&Y6gba}pO>Qe-CH-x}?)$rdq|ue@NRgXp z-S>Y&+C5SXvqLLJJ19HE(kzb5=8^& z^JAuQ7>@2RjX$G7p5S=QiFF+{0;eom+g3a8c_sz}UG7YKkK_qa z4{*X3ul`xAS9wAQ?u^*j9RHWpnZ{JBHQzh|gHCd^=)ig}QuroHZ2>ujU<87eCn%1zi=iW=`N~*|NCtZ+!KqaHU7pdnu_P z2j#ogJRUubpt?tzd>qfGnkoMY!k{EYUzAuNczBh!sG4^vyH60~pw##GPQw&{jXPAu zh88lbH+DXn8IC?;fV2@6Zu3GO-)kHLm*SqJY@$nu)f6IIQq8%g^Itc*6l7;;L4`$Z zC6VESQ(kBco!(qhpveMhju`z7oFQFrY&8)QJwb{tqPK!hly5QI`_`%oKAuS2!e|Np z?}N#IUr@lujsNY@e_l{-o@@TUkN)qkKvE1>x1ChVc9K(alYrMO3?+FrxpEn^fBpw9 CgQnX6 diff --git a/mjpc/tasks/hand/assets/filedown.png b/mjpc/tasks/hand/assets/filedown.png deleted file mode 100644 index ee48edf648e069f61fdce7253d48bf92ce075010..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9816 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 diff --git a/mjpc/tasks/hand/assets/fileleft.png b/mjpc/tasks/hand/assets/fileleft.png deleted file mode 100644 index da6427bf7f676180038c926e009b910d2e98ceed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7959 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 T`t}0X(;%YZd4tk3PIvzc3F1Cn diff --git a/mjpc/tasks/hand/assets/fileright.png b/mjpc/tasks/hand/assets/fileright.png deleted file mode 100644 index 6c2cb391ba608f08d92c5ffb75b678529d738891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1406 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 YBI>?&1-5SF9K43HHhAl&mfzp{F95r0b^rhX diff --git a/mjpc/tasks/hand/assets/grayback.png b/mjpc/tasks/hand/assets/grayback.png deleted file mode 100644 index 03ae4bf72984a2dc1c0bdab844b0dec769577a85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8356 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 diff --git a/mjpc/tasks/hand/assets/graydown.png b/mjpc/tasks/hand/assets/graydown.png deleted file mode 100644 index b8b7b3142a7e0838a40e8ca3e8870f215a6fa44a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9630 zcmdsb2Ut@}wC)B%M{1BFEz&}f5|AoJ0-=gD6;O(lASg`;MOqXIB1l!>fb=S&L_|ao zL5d0%no1L-O7FddBncn8r*RM#;$I_J?qodO{ z(xef`kKM3vhYPyFS_`D|JRc``ej0j+o2Uw@o*``(PYn()?u3)Br-yqlE`945)Y{7S zTdYA})>gi9s*^Sm3)kg?=Cd%F)8XMaPcM>ywS<=Uw;gE*A6{Vld*P z$zx`4i*x*}H&Nn6&EzUS_Oq=e&bPJ_*4Vmi{J*4de@`;7IWE{f(?%8rI(t=Dak2L< zNm`jmv(ein;h0dZyqW<3aIhoetWwPrwdqSlvkR!G{tB8C6JwLR0}nzgEq+6RPJeX% z`gC%7SFJ&3(ZmTVW-4G^i|)csU6fnBvJ74h0(5@CC&#OsSgwxdy=R00W9Oe;_|~0T znwQJm7A1oME_4X#YECLo2aF}N17TZvq}3WrZgPOS1mwgLoviio7ZTHmH_ciwAYkdu zY%IV3@jNvt$gA;$>VOYj+o59**mGZKcK55OPfH`r2J84FpN+n_$3|-x$&-c$`nLBQ z8hEe=X4K>$LCeo1;~{oB((TMti+hd8Q*?ICyo)Nc&MleCE0q|!G(J73t==z>T;DZ#m-d+a#7CWmG~;a1VM%|n;-OBtn9 z*$hWe6Pc44r!sE~A_JZiF812=H-5_r|6Vu3Do>8gj2c^AJqM`yukUYtTU<<^&e2@0 zJU>9KnHs^4K;17c-pMbE7oH#5T5kz&2@m{~oPRAoFEG_I2m-e(7*l~v_69|z9i_B~(bxm^|MH2}S6 zb}VeS=;aHc%`drwmH}7T#d)5w1FsJpSlG+nPfIw`tJlt!YtNJYS@eUYT{|5@R5YsS_#Pg*}9`? zz3fhG{hoS*ToGgFY8?FLb^wwsg>=P?LE(F4mU>}tgJ-3RBwnO$wnw1*kY{^{k0nFQ z!F{+i>(V#J3WPo$Fd5D`(oX6h%Sx?8vA?{Uq|85j%2yBWi!2KaleOW$oGQP*~! zD7IAFSDCZmfvJag_uV`V``{9Net9=$J8n4*spvg`Lx6K>F;4R5;CK{}8TX>?y%CIfDU;Kn=YWEA2g*rVT5IK9_XyB-z!x6@DOD9ZnEXwxz}2witvNrZ0Bn zCo1a3BGQG5LFF9*8kv2}@fib?p|)~T*K)H4zOd6;hGEC{gB}yUkUjPGcm8ZeeOPIx zOzS-2MJ)}!&_doupl$vR1E@*!sVjedU}?bbN1NUoclHF#U6}#V!E0xD4b^@BT%s1& zoT?2KzVMSoE3fAlDX}a)?Kjg?58z^gZ5l*9%}_8!y0LPUSwfP=+&}{zQRK*$k@?C1 zCREIfSUNO_#0TBya$)^l;cz)wj@E$*Nkd{G>6w{mm_203Mk1sV-tzwGe3BK*rmJ~$ znpDK?#yxwc6^kRS0;<&^Oe=@4iuR7cC= z&bMC}X2iRgrD!=VTN*%JANI@Dcr+bpeSnHGtSe$hIV$KfEvgk7r1yGs2ae4p-ex(-vttrO8TZH3U} zTO*lf(IzpK`tTNs2tTLAf^U>GCdaK8CXlH}l!wJ#ttJ&Piw-sNK@!Y55uKa90=De1 zn+U~%E&^$z!oi>zH~<&pVlt1q@c4#jv0!u6tvy4VVgbSh#4u&i<;)6Is_b%ks!2Fq3lKWD$)~Igmm9VqvLy$JfDK7gc zn2=cPYrc8)Ja+kH0`%+;M+aFZD)yzIVM3f87dt+v2K5@lgjkse*3~7La}%**b8#7U zb4BcI-V6wdrC@LXwfIFOw!N@tGMsumB3btO!jvXHC~@N8n6UnC7TsjSDCc zw8>3WOztqUh^0(J(Yi{L~-0D9u%#3i_vhFdfeZvRUtVKmD?XA2t~Az z^ud~mYBi~%5?M<6hv zU>Lyzz-~{hlMKsN9ZfDfU|>MUL>1bnrwFBbdq0!b zSM3`S-r+^dQn7*7*ZfeyLW}L5HwgE_wco~CqP~TlTTedCr22HAybA`q`3!k?PGVs} zk0(Q2u$^HhgmgW#I^8d>$h;If$d1_F4CwcmRp#&EwZ-C&*|Ph3IP{(pzIW!EEzgMx zT6wX0T(4-&&@`*%YTT~K>=6&x3Ju}7`1U}f`_ATv6Gn0uU={mXcHOXnll9KkZ(Z(E zb0d7*$j0g$i9zt4>=|+8H$#3W_KxbWZa02=X;+^SXD;2~P7GULfx}@X@%6anM~m5v zgr;#5Z#+5M3B}~Su0EfCunMr5#wKQ|(%LmLsA3_(r=Bu&q1rw&KiZNk=3!sw>wKL*_fhUnrXZ8y z_ksBCTw`#oUh3@&;?QD-BHnSQ-E%l6p$SEtT-%tU`kmbZO>VP9o_B@BJ z!!3Fys!0d+_dU#)`|}c~{e_kHsA2|v>dge0wopOkpRN;QpK~Iyn@I^+OpqYoWxtG;w;u&ooV*^fa zjd9B{))YP}J&UFvOZPz=U~P;GzEr#Kk3}RJyq%x1Twgz%m5$;;gqS-&?IB%OB}rX? zZ7^RvS(a5;-?eO(h%!q3kf~Ah0JXL7IjD->?v;)BlgExm{une`NcfCU+HpM{OFI(` zT8vZbeOhry=&F$c#zqV(C&h{v9erZv4u>+OrA9U9nb`~K9*ps|R*kV1kv~+Aiu!-) ztKomkXAOz%<3~tJF{r~qJf$3pjUtF=0iWfdAV3`oK5Id7zxjJz?V!F3 z3d4_|jxWX$i*XSNbjP}h=o^}t0RmtirK~@nltdAPoT7r98h}thC}=1sY9N$F6cHNA z6a~aaCDQ|Zpv4F%KVSbW8)W?lOG*`gGN$N%GQI%nG=H$60}G@3N$38FB^CAWY+Na} zf9Ot>ZUV30nUVX*BLKURo}nIC5rqS00ufbdOBJLdU|?BMg}Gp=m8dHW)?n9 zE;gtjzp#)Xzkq;H<-BO@aVGYjv5 z1H1^B01WY8zR0ft4hBk_Xs8YY)Erba98}~MKp1Q%E!B_fcPijJH4TK8j-G*$i5Ub` zu~T}Ah8jXcOACR3xnW>F0O6qJgehv%ahW^PAHD)bTu;hl5Jgoqa$9sQizzwzMldoR z**U98d;t`bJoh*=A5$&#`U6``z1fDe?VZ+)!-YE z_^6xFw_=j-+)YVM`z<{qzo4+Fxa5B6gC~_wtDaRquc>WnZh8IYZEM@R?oXe;^z`=i z4~&kDPkf)8nx2_mSzTM-*xcIQ*`@HJ@ci@oo!Nij#R2l7hCpZ_^b}rH)PWS@91vQV zA|0o;Ilbc*uEU7y3{X^3UPU9LsFKApx07!d(?K!iQSlWDwI9s>bHpP4Tg?6<_CI+I z04y|Apz~-r03Zb*#*WU3SB5!~0h+UU+k|paHkFDy-*k4lX_GpA5$wZ!u*@pqkHvc8l($T z>*c}edMZqd!u~lEo-A(e+L)o=;?;@o9_vC?E9dacWk_jX4qf0}nRvfetfdef&ihb9#^`R|*<+Q41O&{&C-6q4 z){PU}d5)nL!)Fra{Wv}p{C11vOkA^@_Z91Um{eP<@a{=wgv_M$G*M~%h<>vlt)5c< zowctuZhN?-`BA^ClJ6bP3~s%XLF)B*R1Im#%VLHP`Dl;c-Q_sP zy;>QWC&?$H9I}#}JQ-Wd1kW#YL_^J}{zd4o2Q88GJxxiq@}vlvtn%2mxK+(dxQ#B{ zI*08-c)|@b5LiOu-Vx@$MN-~(nDp2-Ch09mlIrj5^mcw(>xgWa@ao3R%^XEzg#p6HAjce%;PD8NmRNv#h<0*zNkod*9n2_n&mxo&q2e(kv2mLW7c{+ z$BTl6JNJ51wiB8(a-zPI0fU5(&m5M)<&xXh6v8++;Q zQTvQilOd%^8S^Z@=O&lp2rS$2Q_aEogH6V$7TJ{me=@)^@N%$Up0S80k-1McLa#5197SeLC4TqOE0~;`9>H^P? z0sfS-`!k!n#W`9j-Cj``>E=&^A-x^^Z_-ub%53{i9S^cC$JJ>Hw>Z@&5sqwE7LLwW zxsCIBG%B&#mw_`VJY~s6t@>0$MTqg*vCLuC661j*<2ynai?6oE?*7~#SS_qGH5BIc zk8*Qw9+7z1k#TCEVCIOVS;CoaPwz32hbvLz6^lrkB&*BUw=GL!v#7^Sk>TC830n?g z;dy2Cg!U_UwW1DVUm%-HM#75u3C{}nwzSbuE5+yLXejUtp&I!|hvlyf6XOSR_OTB8 z5GzfGf)O$>1jY?~xc+M=TpZGB=iYHnu#aCDk^w>?$$$N5=-R0K&Y`C{ySt`S4mwsJ zuL!T?&Fp4R8WW|0!GY_b5d!;p+SpFT&x7&*hCjrifuHdv-(HF2I$f;>A&e)dWUvVr zFX8av>{DqCf9IoJ#b|4(Pj`h+hjxJ+W-c~^;jJm8L#Bl%;AY|G-pwxtq{!aKR*^)_ zw0A32(WGr~?7cM!sR})dW3{#0D!68JGz8 zOa|ui$-wmCnt^>`deV|9QD*hH3>VRTx8XzoavCviz;r)Ma*dEzHkHGOYaJ>C!*(}L zW0$}Fax@u;V>A7{g>V=({tOPBolpIL8^0P|Xdv{XKYPS#kiNkLM)>+`owNQ2*-D2V zPrLdemkQ35txs#dw%xYzYQNEVp!!XQ4H+nYPHf~}+F09)hzi9NvF&;wlL)z&CxT-4 z$ByTe9gh_!vAo3TQo_Z~{J*U`|K;^2z4C9a?f8$L@8uu^{6aaUi!KdKY4^cpZ>{7B z*aYA&X)EN=7Q2}*<=tvIC)u)9R+n!_gN3i_G>id73J$Ga1na@36PuwsSo|Bsx)Zde8+c)YBK1F8| zBp>fTyfDmpaz*{J8`6(0kEWD(3TL#jYOC}p#v(-DVfEO2cWsIG+lNoVfRzD8p+(cX zTBf6du@5y;_T(1_3*lh~ZQherGbuMlhTzkrgHN8}HXhb{W>IJZegiRX;1Qa8)iqrX~gmQFX#O1C{Pdj$GD%a3j|~1GjPXX$3q6Rx!ZfEw~<@H zxKW3s73-XF(=Q~~zb{?K{=Tl+>J#09!%J$C!EK&>9$0yMcI#h3$Rt@eM&+uYInaGOO z^duBow;q^ye=FT|w@|cX@9j=F_xR@>O!8HG8@s}!cAMWO?#!AX>gQ-8qBzsU0%!Ls zCsu+=oi6#ktfj?f(|5+d7&9>MRp}uE_4h<0s7AsicYBc#&LLZU2*=ap)<$!vuOT61 z8F!PbIavBtpQ^=}VV?l8Z(0lQH`(_+Dz`g){i(yGXPTp3aA^bHo1{+(v`xa+|JJ>f z^#4{DS4T<248P`g`DBpPk_P{<_)7ZrhS)j*40e%e+TbGh?H(DpZb&-1R>a+w@NV>W z#@)g%@wX+8Tf03k3dsR?l1;|B;C9j*47#ttAjOXy74O7Ns}_@i5er;g=nUEiS9Z4{ zD+~Aa3^GL+ox|lON^%YkB+*K4e?|noXztoyaBU?6FW}za9kk3%e7*}+;;tQ=Em|*x((87uW;wu@?$m}PeI4u(_$vBu4NYQ6fQOu zMlgDn7>L9brnG-S^NID4Zj5AIw3l9KoH#EOx)TLWaQxg`9^~D)dogN!h?=iFy4lu% zZYg)2dvd(;60b{lX!m@B4*<#e4#sd^F%b01o_%(7gJ`Ea_UCK8OCip!FujS()(O zP`p-2^>dOr=!l~fM{rRbaT=TwyD@zG8rTAQ`h4TXWBfI`Qx=vM=bm+B!3p5HGs+J- ziIL(YX&m^?6z7IqhkU{PE?8Xx|GsKr!ni=>T{^g7$z5C5O&^yK~`kH{zBVFn)-ZH?9O_VmPfVS#^~d0Aa&sCWc{IIXCtLHVo8D1e7+3hM~B=)W0wdb_y0Uj26iymzNEXuwaY0Tblzs)2IH z`k7&TEge05JTQQotO(`Lxo}((M8W<->4J?p?e2;B)uA5307?MCTz`SlV7aEQu6`IS z2v-Skx10jACI8Ac^mM$4(Z%>V`?~vJ-Mzj3*$wP2-Qu7L^zSAoF>pkIgQKOlD>l&47X$osJZX4a*8~KK{Z$9n&EM0>%hBEA z*IgoVXx$RT3;Y5Py3@xOx^Izrg)yjw8aQ%e#tl0Qzx!-+S;1-&N_J2LKRWyA%u{ErS|t z#6>Bq$>S~&UcYvmqKf#13IIUvD9g#{`b=(Qj(J^ItbK$g257|~fV@_VKy9bM9uS09 z6s5AwtYq&p%Tr*%xPqkwscfsyxkABBekbSW?8>>R?>$zOXYi}0lAdE4f@|d{oF^Ju zP(%>~ri(|z8Ae0_e?$P44Nu60cWM4dHk*rM8edb?B3IO+2Fs6b;>Agf-ky z2}Yl_bq+n3BFI$XXFq?#kVBEA%KJDTO>vFVB}6}8Ra;XjoaOEEbs~`)1FjM9xB4uu z@S7~pn`ivmD}|y3jx=7euIguLb)Dt0@6Byr-LBRrJ7)`k=e2Al#Rs3(?s|7G592>? z%2KkGA%{V=wp7IlTV3&=H#aBthYG5~lh%Xp+REHuf({)UuW~~^Fe45c&nt1Ef^eIP zpQ5qPm<+>IgCbv4eZYuJm+K3fgWi6#?t3GR8JPs3AJrv80tW%4;j53+LUnhz%a-fzjSkOU+cRA3km0pxY zC6KNxHF}j%P14>CN@ZYt_99s&LFC?~$BYTSPrVVZ^XcbX_7T+ypYqE&6;tk4dFsE_ zEUGoAyJrB+s ztH@Ymo02ItaWh4Hcqf?E{DLHb9416O6FBiT@GQ-^m`(!+v*i%Y844%UVTfJskbD=A z@8)-!TCzq)4&y%?^W8?Et~qQx?<*O}iu1{9`4%?)yhHG; zrWRdF9=(zNR-p3M4!%3Q@5(EuBOu|ny*jUgiYPc;HV zzN9s@7@rQv!>A+@eb#Wp!b*v7ptBT+UAE{1$V2tuGH9}pMOfH$xrVz6B$p+m&$#oc zLo&+i_G}g{B8+?VR@e_;oM=iK=sJ~VuXSQfH#0LL&~ZB1v6c}IPdXrk=tTzbGcqA+ zyb{Y3pLS7U!r-GXUrR=IJd8;AK1qJh>2r8kDG68Cw^Don3Uy#tPy1Y`-wkC#Y_uzT zIdGFghbG-DK!pbCpo6F#=3+*iTjuTyGs%dCBRs##t&EHjcCV=3%7L$dHzC*2QOrZo|Lxu{1fG_ISHwdyCO@ZOrJMQ8E{1U95Y#Ao|X{Zq=}%^2*|^nq&@Ns zgL*2tFlwxnX&Ohr+e(Jvb4>a2a&i&fGkuGRa{b>(Nf*3`$lmqXDBiVs(1Qrp4an-Y z=A?lt*m9VW(WN37XrK?YUd@)76|0BFKn8wfWSa~4kd|mBJe+SqypKV=VUI|F3|qCK zCkBjqH#2)Ay!eIgibma?nEcAdf)%$q-;u1P*`+1I!M!;vP#<$QgxpgXLbV$3~i1 z;W<7v8?X)3xc_zeNdFL4dF==)3AP)~upgNNZAXJqQ7a)OL%!c=zuX7vHrx{i=vD8L zQY>V|2{-s1l(b6%E2$3yE+9QoKc2{447}f5dFlsDtJiBPorakC#1&mE9Bc-0H)GAc zy(=Ttpq6Gbj#^^TO(^*l(H1Swb0LY_R-P%_KM3-` z2APu8iQA-hFy6}PH*%ac?mT`I-)HELVa9 z=aEVeV9`<6qAohd7!Rlzw>K!Gi=z42Ys0Sk<1la{9N3O7Q~xw;*EZrsw7Yv%nKlgA z4*lp>MZV#Wg7u`lh%J!A14PV`-n1?D74#LA2BgACH=qEWbdl%nSncZf#VOa3%q9X3 zIHKY3bLF~cvj>MB9E;D#NQD;8xR3Wc6S$v7H@4j1e9d5#RFPr^1ws%tCaM+Q5*r61 z$=C1><$J;bAj!4WkK7Kau6Ry%|Op+R3CxUcm(L>VbKmgaK9It84 z$5Z_^az*%hM!1|E46ou;$7|I!_}vIxZmf{Sr*THdWlXxuJh{xVBu01uyMg3a zHcQKUf|5O6Z|RyKfb*dJ{l$>3sW>Il?oh~wZjtoON3zFt_g(cyH@hD}fO}_F`3kK56>F`0}MmA#Ebx(bTaM41Fe3Vu6l*U$f5#(t0`HQNr5ePjzm4TR~ zdlDb#vib;QI#*s+I!whXd4+#7ODjklpY%G(`a$sE9`(Zw;~4?&c1JV4@bNYd@gXk} zu3or1n|%8(MN>e@%D*%V2~}`dN^QLNoN^(Pn#E79>!&cn2v3!*S~o&oHI%x#=S@U6 zQosn#y+B{4kq>vY930Sw3iB6L=|-p#y`0kn%Q(NGMDdCB5=c6AJNQa9m@6%J`QkZh zaZFg8;8_GVSC6MU)Wi_-+f~+tjko878A_#ShnLFU1&v>E_oj~s@U}D7nTC(I&;4L? zl6AC%;1sg9Gex%Ce976)lq-|+0?uve%6CV$@f{`qIKrWp%FP>Lq~u;B6}z!#3*$i` zA(PIhd9PIo`NbsehL1B#nP;={P0}{VzTy7XpOfr~@J|%!g%hQrs(4r$S=!()10TxC zPt}u=x?7zGgjFO^S2N<3W&^jFSk7hzrW#}4fAhMZ&~*{(1lJoqM(;Z^ByQ6TT~F4n z?OY9Y>e@nkJBhJv>-Z_K$4^PC+}pJ5K7P+xsQvaOAY#i_tiHh@%sbJWc6L%>d|Ie_ z1)xL=tJu6r4D9SOdnZm?6UVxl726+U#20x=TCmkhPmKLUuHv!6Y8Js4hR^Vj`PU<5 zhJkxWeF!DIMB3;(czkrDS-KlS**oc3_gbwY{adKR01=TEqEy?h5^m0=f!ZjPg2bzKa-u5At^1ykr3!P-Wxr>gk|I z@MV}hS4#;f;PPsbtbhPjV|U)(Aipt86}P;Ic5d3%_TjAMy~BeA_(|4vrZB$O8{o>A zF?067?8L&4+nsJQs5hHc*d50`C<_+ePV#kmRY;KH&!5X?WV2>BrxB^unr$YIM(&$*+jbFPyiSV~i5i%=37ZOUj;w2XBrE;FgEZZ%2*1ZM;+dZTT0dL^CnmQt%* zxhM9*cQLB2@}(vmw)b}IPp+I13fO`_2u`oN-T*or$pe@REwcgF1AV=3S09abd7J$`X^ zStxSTN+F*kZc#L@RX)SRbnGBt%)@j5{9fFf{u1e<;TP7_scfDq05exe~%5a{+;Eei$54&>VGi459*k|v%vue!}$lD;vZOod6r8vz~<8S zcRiHkH}AhOLyx290Emi$vI6Mnk`h>;rvO<14+jSq2OAF;7Z)ENkAR5$DiI+e5e?Zj z5^{Q4h8y&>baad?yzGoj+{|=z93nTl`S=9|1sT}IBt>BoyaIx-%Rw;k@$rcWiKwq$ zrG`Q2ps@e*f&KuHf_FmU^z#_#agYwJZT+_0^WpX2jJxI*OV}@6@P-qWrvj|wahvE}Z zQc=^;va+#r+~gD#5*85^6PJ~fS5Q<^R?*Sb(>E}@XJm!2wz0KC+Iyfpy}W&V{T_ye zKYAPy8I_d$BqjCfv*&4f`2{at78Vu1dQ(+hQ~S2AzM-|Pz2jqNS9j0n;V&bjW8)K( z^9zgLzAr7Wtgh|s?(HA^JUlu+x#V@p^N-^mG;1^5+>^Jy^y#=u_8~U zm(K9xX%x#C&eAV1R>=)8D9egu4|%_%fd}-n{pD>7{wo7pSnlzjE$3Wf_c?jeY@KfK zwrHp%J_)9{2!1f3Wpe&DD#s%_;>In{+u;tz_WIrr`P5^A8`Md@Ii#UDWfv4{!auqC zlyQ7f`#Etwpglsab?-)qmOMG|uZ0Wk*;8Ds50g&)mIkv_43?}BRJ?=plbbWA?a?n(;|2&_G;ZxA#st~g5{ z>+Rymt8o-0Y#bpIhDM-)YjGNb2CB={T;1c_ug8tXi%-S*-GdbLC?=+kY(8FlF47k~ zDaw#gQt|@1{<)u_1EXBoYPBrcc4%mx4l%OK(Ya-tJ!BSso^FK(r1a6i;c9Se+N65c zjN|+ngdlqZ&r2wPK4MiXh&_AAwBUmF_0uP0a>3({@uP1x1Grqn(veB>`z}vL2R~{* zHNN4+{HTgRylC$hdvKfL5#70%^ysZGx^F4HDPwDW%mk*GA0B;CzNie!Yj93$kWj?e z$>tu(e!i-!B_A+xYWJ_#k{r-yh^&x^#(t|UtLoc%sA#@woYLu&XL*v=nZ+CvWShNR zp1~sas$^e6in+akCg9jRH9H6mg!id%6f)7!YX$Am5gd~Ae0G|k$9;?ne?~YJJ{@wg zq2aOS@TzDo@_wl36ALYPR8n)$I|F@Z)$?Gk-qktRofi}p1~X{D82d8j5r52aOfFHS z;gQZ4(nQ0tEZW+Xrd~^nfMt4J(4W(g0YTNvElPLG*P;O?z78$Y1K$n_IP!AV!6M{e z%7TPE8h{ozN1v6vEf;7XdNR`Mg~AHHwQ5=i<_Qyb&x|Rz@ynCUllfoyGhv_COG=Df zSmxxA;W5rd9ZWV<9)A*ZSG!v!35%+*LOo4&Q-2J7EYFSmDAD)#aW*JGlmwD!>}{D|Rg}2thS|p0Bicgof;Ow)UXj@Ppl zlZU4b%#lTtvmAV?1&gf8Z6vKtKT`}#aI|IU@yd;kl=K3o1g3kA9+N(ZDi{;IEjgAi z$s0A#b1(y+2H1J?s~>u=k5=dHAVM&BUR7@D?OX`8abMM|EgaQcD8-gP?d>=&xiAn< zafY+2!q=b zHy#O-6gv3#^rQ}atq7rf)wX%pzQC~X-5ae2vEf6x=M0*DfGf;=n5bU^OZic$8@@Rt)LTMP5=I<1UqT2|iL4CqEi zLg{|EMJLr~-FRy@n4*UKH?uk(+o#c+8C3@;u}i z%O@`i$31B*F!6|WR_rsKkBaYn$(O1mS#ls~4h_pF{-}E9EtpFuCH#WJG5vK;f($N} zLB3J%@}#WD;h@M8S3lRFU=}Lf{N&sFp1M8k&5mrvmSOuELljcF9u2hcfl;jUxL(B<9+yob#>^(#54JX>0T4 zn+2H{d$n$>nqz~XAG47AGsM|YhevkkmewYF?XOU*__qX7PgNs{T$K_mTATjv7>AjBBux3N0W6MpgjFdH!dE=j1oUtLsbt-QU z7rzDR^=g@As!EDylSy62&amP$($31vDmmGgB>Q?Yx_&OVQ@@X!-BW6ic15O(g>+i4 zPRRJwEn>5vGoLPgw65^!`!@rHZ96eej`GrJ!TD%FV34DnM?$TrP(Kn4eAU=4mY(Nq zMgv)w59r?DSj%mpfOr)NgQqnWu;bvC+XP&(!PnM^L?IPJ((NN+2eI%u3je1B{z%(9TYFlb^1KT~`l!i$@$6M2K|KZchfSt2Zq$B;5&q&s z+Ge&;k9mi>NB0xiZe*iIb$^QJw?~$JQ}yQRTsDhT5EyNQ#uqiSdMs5+u!a?v(TE0d z?Tqb6^hfQ}pn7S#kvx{%ewlSb3g$$}UAn?_syDTY>uIZTQt2~-J}GsIG*^*5u+!m- zW?LG0PpA3Y!SnS`0`Ca6&9e+p#o#stpZg72*&T|0Zxc(Jq&lwH6Z7MGWscu=W}qGv zg{_iBQH4dB=Jm6S;dAoGp-o*MbC`d}tu!%$tgk&w8=)T!JX3gSgk z-1z|9C-9_b(XU=>?9MiQ(Ca!*?LHXW*j#b>Ah7ZN+qL~y>;50y$AF%&n_kobKlW%) z@`fl`7bhoc@PEMnD<@#^fS3vdv0j1@U@Ah~>Q_eMGSvX%;pgXp!F2ig#V=1WE_L#`o_H!d(UhK?B-L57s_N8*w-i<)LZqu4Cck>Szs!ax-3@WE)cK zAPV{?N)DWiF4D>RuaX{Gxz&Ln_}ZUfd2n0}8ygR66bKjgLh3Ao-RysMD?3@(TFY5` zSh*uzQAii(|Gf+l#AjB}g#4dPRIQzDQFeeJAD_SW`sP1*{57Nj67gGi5$~xL*!^p% ze{s}tu|auTxLX7NkiJolky8UfEPwhy*?BryI$Ize|9VLnukT;RkM1wwz=VV~UHL9kRP=v`{EZI?jKDd$%v*8%1yDs(UQyW@W$kWd zXW?vXt>EJBWPt(%gha<5d0%FXZvDG9zfVg*OoT7*g3%B(<@^g%O*;0Tsi!H=zjt444csa diff --git a/mjpc/tasks/hand/assets/grayleft.png b/mjpc/tasks/hand/assets/grayleft.png deleted file mode 100644 index 2625e739889f732556dc56995a7ac112a8caaa20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5126 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 Ss>2jgfZ5wPgO8|(Q~nJ=71`bZ diff --git a/mjpc/tasks/hand/assets/grayright.png b/mjpc/tasks/hand/assets/grayright.png deleted file mode 100644 index 4516b6016b4abdf02d4f5196587f26ad2113108c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1237 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKL96$kvrB^ZqfD}u*qpu?a!^VE@KZ&eBK2wsn zy9>kr_Wm>bfjrIvkH}&M25w;xW@MN(M*=9wUgGKN%KnU7T7-r5vqtB11_tIYo-U3d z6}R5r-I&W1DB$2|5YC|+u_@!!#@R(q%2OC*1DG0v^**L<*PoG@@V(;J8*dqXcCTrN z-+$rS^Ls{IgQ;T@OQ)cU+XRV0#E48gUT?d+zM;M*j=gOcB~Fv9yS;nw{o1PLxjQK_ zhE4%AhJsi?`HKPN<1~=;r6}TU%o$INJ;RL7b(=xb^P=fwl#kk#XES8+Xhuy0gD9H64!{5 zl*E!$tK_0oAjM#0U}U6gXsBys6k=#-1wxkE1_o9J249RaI#4v^=BH$)RpQprnt#Cr PsDZ)L)z4*}Q$iB}$1`dj diff --git a/mjpc/tasks/hand/assets/grayup.png b/mjpc/tasks/hand/assets/grayup.png deleted file mode 100644 index 0b07c030b724dcadcf1d7702028b9ac514d8e5a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2788 zcmeHJYd8}O8=k`6=4JJkBARt@D#y*c+Pv&tIZTB}+9C`a((5pkLyfktkP4IILWNM` z6>~^4XKIt8jE(s)hZ1|WIUn}v`}h6${(jf@UDtPA&;8ujeLvUz=eeFAPvSWTTV>FG z5C8yBw!>OE0|0U;60Qjv36D z>tm>poV_%aXNkk!9|W5+o&r^FtmQHt5yU!je;;00&9z3DBghXlzpg=S#o`=5@^V6< zRjO@~mOWPIDG-{e|IUbe zdIwyt;>Ycg$$R9h@nb2}HaV6m7Bhz6;1u<>GXZ~OXxwXr@=tNOt8cX}TcKYv9|{c$ zo6Jj8bQh%2oo3h%kY0OFD~&$raMl^MT+uH@J>NB*9gXQivx47I-u1!=x)E7)B8SkQ zGw*Tqu3w4`Ik9Hk{|-K|FW4jx(`$T;1h&)C>qKC?kfIYC2WQ~QbW2}ll>_k-*A7(i zy3M${FN%e=N}-8J-VXkLd%qY8uS@H4TII*IidBGNvD5JJEan92@vQWa zq^*05_Si48#oQ7p@m&-laRS?QJ8cRxm@dUQkq z=ksTL^;uZ4V{xUZOxNelZ8Df1%6(;@A1~mmn|BpTki%$fgc0kkxRi5_!ohXK0C!~N zeevjknM2s;XD8R=*xyW2&aBf6L_?YNrmLY+N)OH-akKbr^EMq5PE=pSrrL@Lg6!ae zYzV8|MjhhdrzB1zJF6LCx$KO2iyALE%sWqC12de~?9#$}W8|6Pr2$B$HMhQwF40&R zOmk8p{B^{STz+>=-$Dm#ICG_KQ_u06j1!FuY$t}f?}Z%;5T<%f4R$I1nHOoFt z5FG&JC4VjG?}+UOr#Sjn%(#>}W#w)rp{-MTdgNxxQ0&i|31& zwsL|t1CuUa?KMcdaE|aIu5^z|f9?0F_mt^n|5a@Q=IYU<$3&8@TW7c9Z-rW$t5*|x zfXC$a*?S}@c`FG{om~_TqMlP)7>oIyGBpy3(O*k&(>Cd{3M{b&Ke+Dk^OfT{UaKPU z{g+QBZ5X(umA?`9?r;0LyVatpe|Rl0_MAGoqdzToByScRr7uInLp9oiPx1qYg28KM zUCp=O`L z3yC~#3+)l5r6@Hqn&tY^g)>23=vH{ViLc;UpwZ?Q$oiH1*6K}-*VZS&coOq-=kd+b zni2JOn$p7Orf$M~EQ9BMAJR-r|6B*gk@jk}J=3}a9;Lp!^y#>?cC5BTvjj`*4keY% z$RRp3Crd7D7`*`=Oz4)Um^PNo=dRr^xVVctAYFI+fOPUv=If!5Ir{DQ8Ti~9&v-1vLK0Gn!fLwq88xigeH zAR;5ZRnAs@Kkgah;FK`{`nbK$pGZ0E^=f`4cztsXs$3nPg(ucWPp|6=nX$1Gi|AV9 zxtN4(L*tD(B)YE+^i?^a+MPe z_n9j=Uj`qGcsN(y=4tmv5tcA0ZB1j>+Aa_H5mzAN)JfH5c4_RV{>21K`5wxyaNP*S zX^1z8#Nl)b8g9qNR2Ul)8Z$g;Z{oAE2S+)X3Y6(9MnN* z!>w`QzJzch%7;wcA^^+;1~W7@HH5)jOifWg3VF=L1Z83(h50A^OW==S-vCn7zYp9F S{$REh0N7bOSe2jjqW%NO1GrfL diff --git a/mjpc/tasks/hand/cube.xml b/mjpc/tasks/hand/cube.xml index 64d09d719..408a2da5d 100644 --- a/mjpc/tasks/hand/cube.xml +++ b/mjpc/tasks/hand/cube.xml @@ -1,14 +1,14 @@ + fileup="../assets/cube/fileup.png" fileback="../assets/cube/fileback.png" + filedown="../assets/cube/filedown.png" filefront="../assets/cube/filefront.png" + fileleft="../assets/cube/fileleft.png" fileright="../assets/cube/fileright.png"/> - + From f9311d3ba6305f75b26855b225846b28bebfa5a5 Mon Sep 17 00:00:00 2001 From: alberthli Date: Fri, 12 Jan 2024 14:20:24 -0800 Subject: [PATCH 11/23] added stls to source paths in setup.py --- python/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/setup.py b/python/setup.py index 6fec66aa3..38437968d 100644 --- a/python/setup.py +++ b/python/setup.py @@ -153,6 +153,7 @@ def run(self): source_paths = ( tuple(mjpc_tasks_path.rglob("*.xml")) + tuple(mjpc_tasks_path.rglob("*.png")) + + tuple(mjpc_tasks_path.rglob("*.stl")) ) relative_source_paths = tuple(p.relative_to(mjpc_tasks_path) for p in source_paths) assert self.build_lib is not None From dad6b3207e7b15cd9b07fb17ceac49771c343ab3 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Tue, 16 Jan 2024 19:25:35 -0700 Subject: [PATCH 12/23] home keyframe --- mjpc/tasks/allegro/task.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 95c37a84b..0730b58b2 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -64,6 +64,6 @@ - + From e8131e52deb73cdac19aed3cdcccec495b0f71a1 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Tue, 16 Jan 2024 19:27:00 -0700 Subject: [PATCH 13/23] 10 default rollouts --- mjpc/tasks/allegro/task.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 0730b58b2..27c70c42e 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -13,7 +13,7 @@ - + From f4d5849faf084203e0477e1a4719211d9ebdb7dc Mon Sep 17 00:00:00 2001 From: taylor howell Date: Thu, 18 Jan 2024 10:40:59 -0700 Subject: [PATCH 14/23] update task xml --- mjpc/tasks/allegro/task.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 27c70c42e..34722cff3 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -17,10 +17,10 @@ - - + + From e7a5b8c34392f8ee7a4f57e9a2b6a1b0643ff060 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Fri, 19 Jan 2024 11:33:40 -0700 Subject: [PATCH 15/23] patch --- mjpc/tasks/CMakeLists.txt | 6 + mjpc/tasks/allegro/right_hand.xml | 271 ------------------------ mjpc/tasks/allegro/right_hand.xml.patch | 44 ++++ mjpc/tasks/allegro/task.xml | 2 +- right_hand.xml.patch | 0 5 files changed, 51 insertions(+), 272 deletions(-) delete mode 100644 mjpc/tasks/allegro/right_hand.xml create mode 100644 mjpc/tasks/allegro/right_hand.xml.patch create mode 100644 right_hand.xml.patch diff --git a/mjpc/tasks/CMakeLists.txt b/mjpc/tasks/CMakeLists.txt index eeefc1891..dca9d9bbe 100644 --- a/mjpc/tasks/CMakeLists.txt +++ b/mjpc/tasks/CMakeLists.txt @@ -17,9 +17,15 @@ add_custom_target( copy_menagerie_resources ALL + COMMAND ${CMAKE_COMMAND} -E copy + ${menagerie_SOURCE_DIR}/wonik_allegro/right_hand.xml + ${CMAKE_CURRENT_BINARY_DIR}/allegro/right_hand.xml COMMAND ${CMAKE_COMMAND} -E copy_directory ${menagerie_SOURCE_DIR}/wonik_allegro/assets ${CMAKE_CURRENT_BINARY_DIR}/allegro/assets + COMMAND patch -o ${CMAKE_CURRENT_BINARY_DIR}/allegro/right_hand_modified.xml + ${CMAKE_CURRENT_BINARY_DIR}/allegro/right_hand.xml + <${CMAKE_CURRENT_SOURCE_DIR}/allegro/right_hand.xml.patch COMMAND ${CMAKE_COMMAND} -E copy_directory ${menagerie_SOURCE_DIR}/shadow_hand/assets ${CMAKE_CURRENT_BINARY_DIR}/hand/assets diff --git a/mjpc/tasks/allegro/right_hand.xml b/mjpc/tasks/allegro/right_hand.xml deleted file mode 100644 index eeec9d0cc..000000000 --- a/mjpc/tasks/allegro/right_hand.xml +++ /dev/null @@ -1,271 +0,0 @@ - - - - - diff --git a/mjpc/tasks/allegro/right_hand.xml.patch b/mjpc/tasks/allegro/right_hand.xml.patch new file mode 100644 index 000000000..643e764fc --- /dev/null +++ b/mjpc/tasks/allegro/right_hand.xml.patch @@ -0,0 +1,44 @@ +diff --git a/right_hand_modified.xml b/right_hand_modified.xml +--- a/right_hand_modified.xml ++++ b/right_hand_modified.xml +@@ -6,7 +6,7 @@ + + + +- ++ + + + +@@ -124,8 +124,9 @@ + + + +- ++ + ++ + + + +@@ -148,6 +149,7 @@ + + + ++ + + + +@@ -257,4 +259,12 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ + diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 34722cff3..16ff4c9e7 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -61,7 +61,7 @@ - + diff --git a/right_hand.xml.patch b/right_hand.xml.patch new file mode 100644 index 000000000..e69de29bb From 433a2af84e7ffa4846dde4dec6a7b0353b0b8a33 Mon Sep 17 00:00:00 2001 From: Taylor Howell Date: Sat, 20 Jan 2024 09:40:52 -0800 Subject: [PATCH 16/23] Delete right_hand.xml.patch --- right_hand.xml.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 right_hand.xml.patch diff --git a/right_hand.xml.patch b/right_hand.xml.patch deleted file mode 100644 index e69de29bb..000000000 From 90be9f0313cafaa1a4cbe6f41e33e4401140bad2 Mon Sep 17 00:00:00 2001 From: Taylor Howell Date: Sat, 20 Jan 2024 09:49:21 -0800 Subject: [PATCH 17/23] Update task.xml --- mjpc/tasks/allegro/task.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/mjpc/tasks/allegro/task.xml b/mjpc/tasks/allegro/task.xml index 16ff4c9e7..5f79fc532 100644 --- a/mjpc/tasks/allegro/task.xml +++ b/mjpc/tasks/allegro/task.xml @@ -61,6 +61,7 @@ + From db4b4aa5866657b506c7207b66c8fc482da5c7bb Mon Sep 17 00:00:00 2001 From: taylor howell Date: Tue, 23 Jan 2024 15:51:54 -0700 Subject: [PATCH 18/23] derivative skip --- mjpc/planners/model_derivatives.cc | 207 ++++++++++++++++++++++++----- 1 file changed, 177 insertions(+), 30 deletions(-) diff --git a/mjpc/planners/model_derivatives.cc b/mjpc/planners/model_derivatives.cc index 1ce85e702..613f72af9 100644 --- a/mjpc/planners/model_derivatives.cc +++ b/mjpc/planners/model_derivatives.cc @@ -49,39 +49,186 @@ void ModelDerivatives::Compute(const mjModel* m, int dim_state_derivative, int dim_action, int dim_sensor, int T, double tol, int mode, ThreadPool& pool) { - { - int count_before = pool.GetCount(); - for (int t = 0; t < T; t++) { - pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, - dim_state, dim_state_derivative, dim_action, dim_sensor, - tol, mode, t, T]() { - mjData* d = data[ThreadPool::WorkerId()].get(); - // set state - SetState(m, d, x + t * dim_state); - d->time = h[t]; - - // set action - mju_copy(d->ctrl, u + t * dim_action, dim_action); + int count_before = pool.GetCount(); + // t == 0 + pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, + dim_state, dim_state_derivative, dim_action, dim_sensor, tol, + mode]() { + int t = 0; + mjData* d = data[ThreadPool::WorkerId()].get(); + // set state + SetState(m, d, x + t * dim_state); + d->time = h[t]; + + // set action + mju_copy(d->ctrl, u + t * dim_action, dim_action); + + // derivatives + mjd_transitionFD( + m, d, tol, mode, + DataAt(A, t * (dim_state_derivative * dim_state_derivative)), + DataAt(B, t * (dim_state_derivative * dim_action)), + DataAt(C, t * (dim_sensor * dim_state_derivative)), + DataAt(D, t * (dim_sensor * dim_action))); + }); + + // t == T - 2 + pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, + dim_state, dim_state_derivative, dim_action, dim_sensor, tol, + mode, T]() { + int t = T - 2; + mjData* d = data[ThreadPool::WorkerId()].get(); + // set state + SetState(m, d, x + t * dim_state); + d->time = h[t]; + + // set action + mju_copy(d->ctrl, u + t * dim_action, dim_action); + + // derivatives + mjd_transitionFD( + m, d, tol, mode, + DataAt(A, t * (dim_state_derivative * dim_state_derivative)), + DataAt(B, t * (dim_state_derivative * dim_action)), + DataAt(C, t * (dim_sensor * dim_state_derivative)), + DataAt(D, t * (dim_sensor * dim_action))); + }); + + // t == T - 1 + pool.Schedule([&m, &data, &C = C, &x, &u, &h, + dim_state, dim_state_derivative, dim_action, dim_sensor, tol, + mode, T]() { + int t = T - 1; + mjData* d = data[ThreadPool::WorkerId()].get(); + + // set state + SetState(m, d, x + t * dim_state); + d->time = h[t]; + + // set action + mju_copy(d->ctrl, u + t * dim_action, dim_action); + + // Jacobians + mjd_transitionFD(m, d, tol, mode, nullptr, nullptr, + DataAt(C, t * (dim_sensor * dim_state_derivative)), + nullptr); + }); + + // skip values + std::vector tt; + tt.push_back(0); + + int skip = 3; + for (int t = skip; t < T - skip; t += skip) { + tt.push_back(t); + } + tt.push_back(T - 2); + tt.push_back(T - 1); + int S = tt.size(); + + for (int t = skip; t < T - skip; t += skip) { + pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, + dim_state, dim_state_derivative, dim_action, dim_sensor, + tol, mode, t, T]() { + mjData* d = data[ThreadPool::WorkerId()].get(); + // set state + SetState(m, d, x + t * dim_state); + d->time = h[t]; + + // set action + mju_copy(d->ctrl, u + t * dim_action, dim_action); + + // Jacobians + if (t == T - 1) { // Jacobians - if (t == T - 1) { - // Jacobians - mjd_transitionFD(m, d, tol, mode, nullptr, nullptr, - DataAt(C, t * (dim_sensor * dim_state_derivative)), - nullptr); - } else { - // derivatives - mjd_transitionFD( - m, d, tol, mode, - DataAt(A, t * (dim_state_derivative * dim_state_derivative)), - DataAt(B, t * (dim_state_derivative * dim_action)), - DataAt(C, t * (dim_sensor * dim_state_derivative)), - DataAt(D, t * (dim_sensor * dim_action))); - } - }); - } - pool.WaitCount(count_before + T); + mjd_transitionFD(m, d, tol, mode, nullptr, nullptr, + DataAt(C, t * (dim_sensor * dim_state_derivative)), + nullptr); + } else { + // derivatives + mjd_transitionFD( + m, d, tol, mode, + DataAt(A, t * (dim_state_derivative * dim_state_derivative)), + DataAt(B, t * (dim_state_derivative * dim_action)), + DataAt(C, t * (dim_sensor * dim_state_derivative)), + DataAt(D, t * (dim_sensor * dim_action))); + } + }); + } + pool.WaitCount(count_before + S); + pool.ResetCount(); + + // -- interpolate skipped values -- // + + // find skipped indices + std::vector ss; + for (int t = 0; t < T; t++) { + if(std::find(tt.begin(), tt.end(), t) == tt.end()) { + /* v contains x */ + ss.push_back(t); + } + } + + // convert to double index for FindInterval + std::vector ttd; + for (int i: tt) { + ttd.push_back((double)i); } + + int H = ss.size(); + for (int i: ss) { + pool.Schedule([&A = A, &B = B, &C = C, &D = D, &tt, &ttd, + dim_state_derivative, dim_action, dim_sensor, i]() { + // find interval + int bounds[2]; + FindInterval(bounds, ttd, (double)i, ttd.size()); + + // normalized time + double q = double(i - tt[bounds[0]]) / double(tt[bounds[1]] - tt[bounds[0]]); + if (bounds[0] == bounds[1]) { + q = 0.0; + } + + // A + int nA = dim_state_derivative * dim_state_derivative; + double* Ai = DataAt(A, i * nA); + double* AL = DataAt(A, tt[bounds[0]] * nA); + double* AU = DataAt(A, tt[bounds[1]] * nA); + + mju_scl(Ai, AL, 1.0 - q, nA); + mju_addToScl(Ai, AU, q, nA); + + // B + int nB = dim_state_derivative * dim_action; + double* Bi = DataAt(B, i * nB); + double* BL = DataAt(B, tt[bounds[0]] * nB); + double* BU = DataAt(B, tt[bounds[1]] * nB); + + mju_scl(Bi, BL, 1.0 - q, nB); + mju_addToScl(Bi, BU, q, nB); + + // C + int nC = dim_sensor * dim_state_derivative; + double* Ci = DataAt(C, i * nC); + double* CL = DataAt(C, tt[bounds[0]] * nC); + double* CU = DataAt(C, tt[bounds[1]] * nC); + + mju_scl(Ci, CL, 1.0 - q, nC); + mju_addToScl(Ci, CU, q, nC); + + // D + int nD = dim_sensor * dim_action; + double* Di = DataAt(D, i * nD); + double* DL = DataAt(D, tt[bounds[0]] * nD); + double* DU = DataAt(D, tt[bounds[1]] * nD); + + mju_scl(Di, DL, 1.0 - q, nD); + mju_addToScl(Di, DU, q, nD); + }); + } + + pool.WaitCount(count_before + H); pool.ResetCount(); } From 5c8c3bd7a80635842ededa48fe905c7c3bdd4da9 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Wed, 24 Jan 2024 11:05:50 -0700 Subject: [PATCH 19/23] clean up --- mjpc/planners/gradient/planner.cc | 8 +- mjpc/planners/gradient/planner.h | 1 + mjpc/planners/ilqg/planner.cc | 7 +- mjpc/planners/ilqg/planner.h | 1 + mjpc/planners/model_derivatives.cc | 192 +++++++++-------------------- mjpc/planners/model_derivatives.h | 6 +- mjpc/utilities.cc | 22 ---- mjpc/utilities.h | 23 +++- 8 files changed, 102 insertions(+), 158 deletions(-) diff --git a/mjpc/planners/gradient/planner.cc b/mjpc/planners/gradient/planner.cc index 2ce00d071..35c1d1231 100644 --- a/mjpc/planners/gradient/planner.cc +++ b/mjpc/planners/gradient/planner.cc @@ -147,6 +147,9 @@ void GradientPlanner::Reset(int horizon, expected = 0.0; improvement = 0.0; surprise = 0.0; + + // derivative skip + derivative_skip_ = GetNumberOrDefault(0, model, "derivative_skip"); } // set state @@ -200,10 +203,12 @@ void GradientPlanner::OptimizePolicy(int horizon, ThreadPool& pool) { auto model_derivative_start = std::chrono::steady_clock::now(); // compute model and sensor Jacobians + int skip = derivative_skip_; model_derivative.Compute( model, data_, trajectory[0].states.data(), trajectory[0].actions.data(), trajectory[0].times.data(), dim_state, dim_state_derivative, dim_action, - dim_sensor, horizon, settings.fd_tolerance, settings.fd_mode, pool); + dim_sensor, horizon, settings.fd_tolerance, settings.fd_mode, pool, + skip); // stop timer model_derivative_time += GetDuration(model_derivative_start); @@ -475,6 +480,7 @@ void GradientPlanner::GUI(mjUI& ui) { "Zero\nLinear\nCubic"}, {mjITEM_SLIDERINT, "Spline Pts", 2, &policy.num_spline_points, "0 1"}, // {mjITEM_SLIDERNUM, "Spline Pow. ", 2, ×tep_power, "0 10"}, + {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 64"}, {mjITEM_END}}; // set number of trajectory slider limits diff --git a/mjpc/planners/gradient/planner.h b/mjpc/planners/gradient/planner.h index f2ae52522..403af8538 100644 --- a/mjpc/planners/gradient/planner.h +++ b/mjpc/planners/gradient/planner.h @@ -158,6 +158,7 @@ class GradientPlanner : public Planner { private: mutable std::shared_mutex mtx_; + int derivative_skip_ = 0; }; } // namespace mjpc diff --git a/mjpc/planners/ilqg/planner.cc b/mjpc/planners/ilqg/planner.cc index 708bba6b5..6c3561212 100644 --- a/mjpc/planners/ilqg/planner.cc +++ b/mjpc/planners/ilqg/planner.cc @@ -137,6 +137,9 @@ void iLQGPlanner::Reset(int horizon, const double* initial_repeated_action) { improvement = 0.0; expected = 0.0; surprise = 0.0; + + // derivative skip + derivative_skip_ = GetNumberOrDefault(0, model, "derivative_skip"); } // set state @@ -245,6 +248,7 @@ void iLQGPlanner::GUI(mjUI& ui) { "Zero\nLinear\nCubic"}, {mjITEM_SELECT, "Reg. Type", 2, &settings.regularization_type, "Control\nFeedback\nValue\nNone"}, + {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 64"}, {mjITEM_CHECKINT, "Terminal Print", 2, &settings.verbose, ""}, {mjITEM_END}}; @@ -385,12 +389,13 @@ void iLQGPlanner::Iteration(int horizon, ThreadPool& pool) { auto model_derivative_start = std::chrono::steady_clock::now(); // compute model and sensor Jacobians + int skip = derivative_skip_; model_derivative.Compute( model, data_, candidate_policy[0].trajectory.states.data(), candidate_policy[0].trajectory.actions.data(), candidate_policy[0].trajectory.times.data(), dim_state, dim_state_derivative, dim_action, dim_sensor, horizon, - settings.fd_tolerance, settings.fd_mode, pool); + settings.fd_tolerance, settings.fd_mode, pool, skip); // stop timer double model_derivative_time = GetDuration(model_derivative_start); diff --git a/mjpc/planners/ilqg/planner.h b/mjpc/planners/ilqg/planner.h index b675c1c52..48916a7fa 100644 --- a/mjpc/planners/ilqg/planner.h +++ b/mjpc/planners/ilqg/planner.h @@ -154,6 +154,7 @@ class iLQGPlanner : public Planner { private: int num_trajectory_ = 1; int num_rollouts_gui_ = 1; + int derivative_skip_ = 0; }; } // namespace mjpc diff --git a/mjpc/planners/model_derivatives.cc b/mjpc/planners/model_derivatives.cc index 613f72af9..5ada98562 100644 --- a/mjpc/planners/model_derivatives.cc +++ b/mjpc/planners/model_derivatives.cc @@ -48,89 +48,33 @@ void ModelDerivatives::Compute(const mjModel* m, const double* h, int dim_state, int dim_state_derivative, int dim_action, int dim_sensor, int T, double tol, int mode, - ThreadPool& pool) { - int count_before = pool.GetCount(); + ThreadPool& pool, int skip) { + // reset indices + evaluate_.clear(); + interpolate_.clear(); + + // evaluate indices + int s = skip + 1; + evaluate_.push_back(0); + for (int t = s; t < T - s; t += s) { + evaluate_.push_back(t); + } + evaluate_.push_back(T - 2); + evaluate_.push_back(T - 1); - // t == 0 - pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, - dim_state, dim_state_derivative, dim_action, dim_sensor, tol, - mode]() { - int t = 0; - mjData* d = data[ThreadPool::WorkerId()].get(); - // set state - SetState(m, d, x + t * dim_state); - d->time = h[t]; - - // set action - mju_copy(d->ctrl, u + t * dim_action, dim_action); - - // derivatives - mjd_transitionFD( - m, d, tol, mode, - DataAt(A, t * (dim_state_derivative * dim_state_derivative)), - DataAt(B, t * (dim_state_derivative * dim_action)), - DataAt(C, t * (dim_sensor * dim_state_derivative)), - DataAt(D, t * (dim_sensor * dim_action))); - }); - - // t == T - 2 - pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, - dim_state, dim_state_derivative, dim_action, dim_sensor, tol, - mode, T]() { - int t = T - 2; - mjData* d = data[ThreadPool::WorkerId()].get(); - // set state - SetState(m, d, x + t * dim_state); - d->time = h[t]; - - // set action - mju_copy(d->ctrl, u + t * dim_action, dim_action); - - // derivatives - mjd_transitionFD( - m, d, tol, mode, - DataAt(A, t * (dim_state_derivative * dim_state_derivative)), - DataAt(B, t * (dim_state_derivative * dim_action)), - DataAt(C, t * (dim_sensor * dim_state_derivative)), - DataAt(D, t * (dim_sensor * dim_action))); - }); - - // t == T - 1 - pool.Schedule([&m, &data, &C = C, &x, &u, &h, - dim_state, dim_state_derivative, dim_action, dim_sensor, tol, - mode, T]() { - int t = T - 1; - mjData* d = data[ThreadPool::WorkerId()].get(); - - // set state - SetState(m, d, x + t * dim_state); - d->time = h[t]; - - // set action - mju_copy(d->ctrl, u + t * dim_action, dim_action); - - // Jacobians - mjd_transitionFD(m, d, tol, mode, nullptr, nullptr, - DataAt(C, t * (dim_sensor * dim_state_derivative)), - nullptr); - }); - - // skip values - std::vector tt; - tt.push_back(0); - - int skip = 3; - for (int t = skip; t < T - skip; t += skip) { - tt.push_back(t); + // interpolate indices + for (int t = 0; t < T; t++) { + if (std::find(evaluate_.begin(), evaluate_.end(), t) == evaluate_.end()) { + interpolate_.push_back(t); + } } - tt.push_back(T - 2); - tt.push_back(T - 1); - int S = tt.size(); - for (int t = skip; t < T - skip; t += skip) { + // evaluate derivatives + int count_before = pool.GetCount(); + for (int t : evaluate_) { pool.Schedule([&m, &data, &A = A, &B = B, &C = C, &D = D, &x, &u, &h, - dim_state, dim_state_derivative, dim_action, dim_sensor, - tol, mode, t, T]() { + dim_state, dim_state_derivative, dim_action, dim_sensor, tol, + mode, t, T]() { mjData* d = data[ThreadPool::WorkerId()].get(); // set state SetState(m, d, x + t * dim_state); @@ -143,8 +87,8 @@ void ModelDerivatives::Compute(const mjModel* m, if (t == T - 1) { // Jacobians mjd_transitionFD(m, d, tol, mode, nullptr, nullptr, - DataAt(C, t * (dim_sensor * dim_state_derivative)), - nullptr); + DataAt(C, t * (dim_sensor * dim_state_derivative)), + nullptr); } else { // derivatives mjd_transitionFD( @@ -156,79 +100,65 @@ void ModelDerivatives::Compute(const mjModel* m, } }); } - pool.WaitCount(count_before + S); + pool.WaitCount(count_before + evaluate_.size()); pool.ResetCount(); - // -- interpolate skipped values -- // - - // find skipped indices - std::vector ss; - for (int t = 0; t < T; t++) { - if(std::find(tt.begin(), tt.end(), t) == tt.end()) { - /* v contains x */ - ss.push_back(t); - } - } - - // convert to double index for FindInterval - std::vector ttd; - for (int i: tt) { - ttd.push_back((double)i); - } - - int H = ss.size(); - for (int i: ss) { - pool.Schedule([&A = A, &B = B, &C = C, &D = D, &tt, &ttd, - dim_state_derivative, dim_action, dim_sensor, i]() { + // interpolate derivatives + count_before = pool.GetCount(); + for (int t : interpolate_) { + pool.Schedule([&A = A, &B = B, &C = C, &D = D, &evaluate_ = this->evaluate_, + dim_state_derivative, dim_action, dim_sensor, t]() { // find interval int bounds[2]; - FindInterval(bounds, ttd, (double)i, ttd.size()); + FindInterval(bounds, evaluate_, t, evaluate_.size()); + int e0 = evaluate_[bounds[0]]; + int e1 = evaluate_[bounds[1]]; - // normalized time - double q = double(i - tt[bounds[0]]) / double(tt[bounds[1]] - tt[bounds[0]]); + // normalized input + double tt = double(t - e0) / double(e1 - e0); if (bounds[0] == bounds[1]) { - q = 0.0; + tt = 0.0; } // A int nA = dim_state_derivative * dim_state_derivative; - double* Ai = DataAt(A, i * nA); - double* AL = DataAt(A, tt[bounds[0]] * nA); - double* AU = DataAt(A, tt[bounds[1]] * nA); - - mju_scl(Ai, AL, 1.0 - q, nA); - mju_addToScl(Ai, AU, q, nA); - - // B + double* Ai = DataAt(A, t * nA); + double* AL = DataAt(A, e0 * nA); + double* AU = DataAt(A, e1 * nA); + + mju_scl(Ai, AL, 1.0 - tt, nA); + mju_addToScl(Ai, AU, tt, nA); + + // B int nB = dim_state_derivative * dim_action; - double* Bi = DataAt(B, i * nB); - double* BL = DataAt(B, tt[bounds[0]] * nB); - double* BU = DataAt(B, tt[bounds[1]] * nB); + double* Bi = DataAt(B, t * nB); + double* BL = DataAt(B, e0 * nB); + double* BU = DataAt(B, e1 * nB); - mju_scl(Bi, BL, 1.0 - q, nB); - mju_addToScl(Bi, BU, q, nB); + mju_scl(Bi, BL, 1.0 - tt, nB); + mju_addToScl(Bi, BU, tt, nB); // C int nC = dim_sensor * dim_state_derivative; - double* Ci = DataAt(C, i * nC); - double* CL = DataAt(C, tt[bounds[0]] * nC); - double* CU = DataAt(C, tt[bounds[1]] * nC); + double* Ci = DataAt(C, t * nC); + double* CL = DataAt(C, e0 * nC); + double* CU = DataAt(C, e1 * nC); - mju_scl(Ci, CL, 1.0 - q, nC); - mju_addToScl(Ci, CU, q, nC); + mju_scl(Ci, CL, 1.0 - tt, nC); + mju_addToScl(Ci, CU, tt, nC); // D int nD = dim_sensor * dim_action; - double* Di = DataAt(D, i * nD); - double* DL = DataAt(D, tt[bounds[0]] * nD); - double* DU = DataAt(D, tt[bounds[1]] * nD); + double* Di = DataAt(D, t * nD); + double* DL = DataAt(D, e0 * nD); + double* DU = DataAt(D, e1 * nD); - mju_scl(Di, DL, 1.0 - q, nD); - mju_addToScl(Di, DU, q, nD); + mju_scl(Di, DL, 1.0 - tt, nD); + mju_addToScl(Di, DU, tt, nD); }); } - pool.WaitCount(count_before + H); + pool.WaitCount(count_before + interpolate_.size()); pool.ResetCount(); } diff --git a/mjpc/planners/model_derivatives.h b/mjpc/planners/model_derivatives.h index 1ea295b83..6763ce8be 100644 --- a/mjpc/planners/model_derivatives.h +++ b/mjpc/planners/model_derivatives.h @@ -45,7 +45,7 @@ class ModelDerivatives { void Compute(const mjModel* m, const std::vector& data, const double* x, const double* u, const double* h, int dim_state, int dim_state_derivative, int dim_action, int dim_sensor, int T, - double tol, int mode, ThreadPool& pool); + double tol, int mode, ThreadPool& pool, int skip = 0); // Jacobians std::vector A; // model Jacobians wrt state @@ -56,6 +56,10 @@ class ModelDerivatives { // (T * dim_sensor * dim_state_derivative) std::vector D; // output Jacobians wrt action // (T * dim_sensor * dim_action) + + // indices + std::vector evaluate_; + std::vector interpolate_; }; } // namespace mjpc diff --git a/mjpc/utilities.cc b/mjpc/utilities.cc index 5ca374694..82d9d7c90 100644 --- a/mjpc/utilities.cc +++ b/mjpc/utilities.cc @@ -307,28 +307,6 @@ void PowerSequence(double* t, double t_step, double t1, double t2, double p, } } -// find interval in monotonic sequence containing value -void FindInterval(int* bounds, const std::vector& sequence, - double value, int length) { - // get bounds - auto it = - std::upper_bound(sequence.begin(), sequence.begin() + length, value); - int upper_bound = it - sequence.begin(); - int lower_bound = upper_bound - 1; - - // set bounds - if (lower_bound < 0) { - bounds[0] = 0; - bounds[1] = 0; - } else if (lower_bound > length - 1) { - bounds[0] = length - 1; - bounds[1] = length - 1; - } else { - bounds[0] = mju_max(lower_bound, 0); - bounds[1] = mju_min(upper_bound, length - 1); - } -} - // zero-order interpolation void ZeroInterpolation(double* output, double x, const std::vector& xs, const double* ys, int dim, int length) { diff --git a/mjpc/utilities.h b/mjpc/utilities.h index ad425506a..c0bc9f3e4 100644 --- a/mjpc/utilities.h +++ b/mjpc/utilities.h @@ -124,8 +124,27 @@ void PowerSequence(double* t, double t_step, double t1, double t2, double p, double N); // find interval in monotonic sequence containing value -void FindInterval(int* bounds, const std::vector& sequence, - double value, int length); +template +void FindInterval(int* bounds, const std::vector& sequence, double value, + int length) { + // get bounds + auto it = + std::upper_bound(sequence.begin(), sequence.begin() + length, value); + int upper_bound = it - sequence.begin(); + int lower_bound = upper_bound - 1; + + // set bounds + if (lower_bound < 0) { + bounds[0] = 0; + bounds[1] = 0; + } else if (lower_bound > length - 1) { + bounds[0] = length - 1; + bounds[1] = length - 1; + } else { + bounds[0] = mju_max(lower_bound, 0); + bounds[1] = mju_min(upper_bound, length - 1); + } +} // zero-order interpolation void ZeroInterpolation(double* output, double x, const std::vector& xs, From 5c2fcb1050a10efad55663d1c1c8c47bda7494f4 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Wed, 24 Jan 2024 11:08:30 -0700 Subject: [PATCH 20/23] minor fix --- mjpc/planners/gradient/planner.cc | 3 +-- mjpc/planners/ilqg/planner.cc | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mjpc/planners/gradient/planner.cc b/mjpc/planners/gradient/planner.cc index 35c1d1231..96e5dc2b2 100644 --- a/mjpc/planners/gradient/planner.cc +++ b/mjpc/planners/gradient/planner.cc @@ -203,12 +203,11 @@ void GradientPlanner::OptimizePolicy(int horizon, ThreadPool& pool) { auto model_derivative_start = std::chrono::steady_clock::now(); // compute model and sensor Jacobians - int skip = derivative_skip_; model_derivative.Compute( model, data_, trajectory[0].states.data(), trajectory[0].actions.data(), trajectory[0].times.data(), dim_state, dim_state_derivative, dim_action, dim_sensor, horizon, settings.fd_tolerance, settings.fd_mode, pool, - skip); + derivative_skip_); // stop timer model_derivative_time += GetDuration(model_derivative_start); diff --git a/mjpc/planners/ilqg/planner.cc b/mjpc/planners/ilqg/planner.cc index 6c3561212..3a370ba31 100644 --- a/mjpc/planners/ilqg/planner.cc +++ b/mjpc/planners/ilqg/planner.cc @@ -389,13 +389,12 @@ void iLQGPlanner::Iteration(int horizon, ThreadPool& pool) { auto model_derivative_start = std::chrono::steady_clock::now(); // compute model and sensor Jacobians - int skip = derivative_skip_; model_derivative.Compute( model, data_, candidate_policy[0].trajectory.states.data(), candidate_policy[0].trajectory.actions.data(), candidate_policy[0].trajectory.times.data(), dim_state, dim_state_derivative, dim_action, dim_sensor, horizon, - settings.fd_tolerance, settings.fd_mode, pool, skip); + settings.fd_tolerance, settings.fd_mode, pool, derivative_skip_); // stop timer double model_derivative_time = GetDuration(model_derivative_start); From 12b1b9f3bfc528ef8abcb47242da53e4a75d5264 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Thu, 25 Jan 2024 09:28:33 -0700 Subject: [PATCH 21/23] smaller derivative_skip_ gui max --- mjpc/planners/gradient/planner.cc | 2 +- mjpc/planners/ilqg/planner.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mjpc/planners/gradient/planner.cc b/mjpc/planners/gradient/planner.cc index 96e5dc2b2..3226f3fbb 100644 --- a/mjpc/planners/gradient/planner.cc +++ b/mjpc/planners/gradient/planner.cc @@ -479,7 +479,7 @@ void GradientPlanner::GUI(mjUI& ui) { "Zero\nLinear\nCubic"}, {mjITEM_SLIDERINT, "Spline Pts", 2, &policy.num_spline_points, "0 1"}, // {mjITEM_SLIDERNUM, "Spline Pow. ", 2, ×tep_power, "0 10"}, - {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 64"}, + {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 16"}, {mjITEM_END}}; // set number of trajectory slider limits diff --git a/mjpc/planners/ilqg/planner.cc b/mjpc/planners/ilqg/planner.cc index 7dbb69a75..584a2438e 100644 --- a/mjpc/planners/ilqg/planner.cc +++ b/mjpc/planners/ilqg/planner.cc @@ -251,7 +251,7 @@ void iLQGPlanner::GUI(mjUI& ui) { "Zero\nLinear\nCubic"}, {mjITEM_SELECT, "Reg. Type", 2, &settings.regularization_type, "Control\nFeedback\nValue\nNone"}, - {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 64"}, + {mjITEM_SLIDERINT, "Deriv. Skip", 2, &derivative_skip_, "0 16"}, {mjITEM_CHECKINT, "Terminal Print", 2, &settings.verbose, ""}, {mjITEM_END}}; From 79db2bc0cc8e1ca4e96af0859718c265cdd22caf Mon Sep 17 00:00:00 2001 From: taylor howell Date: Fri, 9 Feb 2024 10:13:23 -0700 Subject: [PATCH 22/23] nimrod comments --- mjpc/planners/gradient/planner.cc | 3 ++- mjpc/planners/model_derivatives.cc | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/mjpc/planners/gradient/planner.cc b/mjpc/planners/gradient/planner.cc index 354247121..ba36ea152 100644 --- a/mjpc/planners/gradient/planner.cc +++ b/mjpc/planners/gradient/planner.cc @@ -194,6 +194,7 @@ void GradientPlanner::OptimizePolicy(int horizon, ThreadPool& pool) { // update policy double c_best = c_prev; + int skip = derivative_skip_; for (int i = 0; i < settings.max_rollout; i++) { // ----- model derivatives ----- // // start timer @@ -204,7 +205,7 @@ void GradientPlanner::OptimizePolicy(int horizon, ThreadPool& pool) { model, data_, trajectory[0].states.data(), trajectory[0].actions.data(), trajectory[0].times.data(), dim_state, dim_state_derivative, dim_action, dim_sensor, horizon, settings.fd_tolerance, settings.fd_mode, pool, - derivative_skip_); + skip); // stop timer model_derivative_time += GetDuration(model_derivative_start); diff --git a/mjpc/planners/model_derivatives.cc b/mjpc/planners/model_derivatives.cc index 5ada98562..03f67529a 100644 --- a/mjpc/planners/model_derivatives.cc +++ b/mjpc/planners/model_derivatives.cc @@ -63,9 +63,11 @@ void ModelDerivatives::Compute(const mjModel* m, evaluate_.push_back(T - 1); // interpolate indices - for (int t = 0; t < T; t++) { - if (std::find(evaluate_.begin(), evaluate_.end(), t) == evaluate_.end()) { + for (int t = 0, e = 0; t < T; t++) { + if (e == evaluate_.size() || evaluate_[e] > t) { interpolate_.push_back(t); + } else { + e++; } } @@ -123,8 +125,8 @@ void ModelDerivatives::Compute(const mjModel* m, // A int nA = dim_state_derivative * dim_state_derivative; double* Ai = DataAt(A, t * nA); - double* AL = DataAt(A, e0 * nA); - double* AU = DataAt(A, e1 * nA); + const double* AL = DataAt(A, e0 * nA); + const double* AU = DataAt(A, e1 * nA); mju_scl(Ai, AL, 1.0 - tt, nA); mju_addToScl(Ai, AU, tt, nA); @@ -132,8 +134,8 @@ void ModelDerivatives::Compute(const mjModel* m, // B int nB = dim_state_derivative * dim_action; double* Bi = DataAt(B, t * nB); - double* BL = DataAt(B, e0 * nB); - double* BU = DataAt(B, e1 * nB); + const double* BL = DataAt(B, e0 * nB); + const double* BU = DataAt(B, e1 * nB); mju_scl(Bi, BL, 1.0 - tt, nB); mju_addToScl(Bi, BU, tt, nB); @@ -141,8 +143,8 @@ void ModelDerivatives::Compute(const mjModel* m, // C int nC = dim_sensor * dim_state_derivative; double* Ci = DataAt(C, t * nC); - double* CL = DataAt(C, e0 * nC); - double* CU = DataAt(C, e1 * nC); + const double* CL = DataAt(C, e0 * nC); + const double* CU = DataAt(C, e1 * nC); mju_scl(Ci, CL, 1.0 - tt, nC); mju_addToScl(Ci, CU, tt, nC); @@ -150,8 +152,8 @@ void ModelDerivatives::Compute(const mjModel* m, // D int nD = dim_sensor * dim_action; double* Di = DataAt(D, t * nD); - double* DL = DataAt(D, e0 * nD); - double* DU = DataAt(D, e1 * nD); + const double* DL = DataAt(D, e0 * nD); + const double* DU = DataAt(D, e1 * nD); mju_scl(Di, DL, 1.0 - tt, nD); mju_addToScl(Di, DU, tt, nD); From f22e80c1c279ff5db4a0fcb234727eb4e59c41c8 Mon Sep 17 00:00:00 2001 From: taylor howell Date: Fri, 9 Feb 2024 10:27:58 -0700 Subject: [PATCH 23/23] remove timestep_power --- mjpc/planners/sample_gradient/planner.cc | 3 --- mjpc/planners/sample_gradient/planner.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/mjpc/planners/sample_gradient/planner.cc b/mjpc/planners/sample_gradient/planner.cc index 636223e7d..321a48208 100644 --- a/mjpc/planners/sample_gradient/planner.cc +++ b/mjpc/planners/sample_gradient/planner.cc @@ -47,9 +47,6 @@ void SampleGradientPlanner::Initialize(mjModel* model, const Task& task) { // task this->task = &task; - // rollout parameters - timestep_power = 1.0; - // exploration noise noise_exploration = GetNumberOrDefault(0.1, model, "sampling_exploration"); diff --git a/mjpc/planners/sample_gradient/planner.h b/mjpc/planners/sample_gradient/planner.h index c70bf7a51..92ca2fda7 100644 --- a/mjpc/planners/sample_gradient/planner.h +++ b/mjpc/planners/sample_gradient/planner.h @@ -122,9 +122,6 @@ class SampleGradientPlanner : public Planner { // order of indices of rolled out trajectories, ordered by total return std::vector trajectory_order; - // rollout parameters - double timestep_power; - // zero-mean Gaussian noise standard deviation double noise_exploration; std::vector noise;