symphony.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include <cassert>
  2. #include <chrono>
  3. #include "simple/motion/movement.hpp"
  4. #include "simple/motion/symphony.hpp"
  5. using namespace std::literals;
  6. using duration = std::chrono::duration<float>;
  7. using simple::support::way;
  8. using simple::motion::symphony;
  9. template <typename T> class show_type;
  10. void SharpTurn()
  11. {
  12. // TODO: use rational, can't rely on float
  13. using movement = simple::motion::movement<duration,float,float>;
  14. std::array<float,2> block{0,0};
  15. auto sharp_turn = symphony(std::vector<movement>{
  16. movement{1250ms, 0,1},
  17. movement{1250ms, 0,1}
  18. });
  19. auto range = sharp_turn.move(block, 500ms).updated;
  20. assert( block[0] == way(0.f,1.f, 0.5f / 1.25f) );
  21. assert( block[1] == 0.f );
  22. assert( range.end() - range.begin() == 1 );
  23. range = sharp_turn.move(block, 500ms).updated;
  24. assert( block[0] == way(0.f,1.f, 1.f / 1.25f) );
  25. assert( block[1] == 0.f );
  26. assert( range.end() - range.begin() == 1 );
  27. range = sharp_turn.move(block, 500ms).updated;
  28. assert( block[0] == way(0.f,1.f, 1.f) );
  29. assert( block[1] == way(0.f,1.f, 0.25f / 1.25f) );
  30. assert( range.end() - range.begin() == 2 );
  31. range = sharp_turn.move(block, 500ms).updated;
  32. assert( block[0] == way(0.f,1.f, 1.f) );
  33. assert( block[1] == way(0.f,1.f, 0.75f / 1.25f) );
  34. assert( range.end() - range.begin() == 1 );
  35. }
  36. void Advance()
  37. {
  38. using movement = simple::motion::movement<std::chrono::milliseconds,float,float>;
  39. auto sequence = symphony(std::vector{
  40. movement{10ms, 0,1},
  41. movement{10ms, 0,1},
  42. movement{10ms, 0,1},
  43. movement{10ms, 0,1}
  44. });
  45. const auto begin = sequence.range().begin();
  46. auto result = sequence.advance(10ms);
  47. assert( not result.done );
  48. assert( result.updated.lower() == begin+0 );
  49. assert( result.updated.upper() == begin+1 );
  50. assert( result.remaining == 0ms );
  51. result = sequence.advance(10ms);
  52. assert( not result.done );
  53. assert( result.updated.lower() == begin+1 );
  54. assert( result.updated.upper() == begin+2 );
  55. assert( result.remaining == 0ms );
  56. result = sequence.advance(10ms);
  57. assert( not result.done );
  58. assert( result.updated.lower() == begin+2 );
  59. assert( result.updated.upper() == begin+3 );
  60. assert( result.remaining == 0ms );
  61. result = sequence.advance(10ms);
  62. assert( result.done );
  63. assert( result.updated.lower() == begin+3 );
  64. assert( result.updated.upper() == begin+4 );
  65. assert( result.remaining == 0ms );
  66. sequence.reset();
  67. result = sequence.advance(15ms);
  68. assert( not result.done );
  69. assert( result.updated.lower() == begin+0 );
  70. assert( result.updated.upper() == begin+2 );
  71. assert( result.remaining == 0ms );
  72. result = sequence.advance(15ms);
  73. assert( not result.done );
  74. assert( result.updated.lower() == begin+1 );
  75. assert( result.updated.upper() == begin+3 );
  76. assert( result.remaining == 0ms );
  77. result = sequence.advance(15ms);
  78. assert( result.done );
  79. assert( result.updated.lower() == begin+3 );
  80. assert( result.updated.upper() == begin+4 );
  81. assert( result.remaining == 5ms );
  82. }
  83. void MoveWithSmallerTarget()
  84. {
  85. using movement = simple::motion::movement<duration,float,float>;
  86. std::array<float,2> block{0,0};
  87. auto s = symphony(std::vector<movement>{
  88. movement{1250ms, 0,1},
  89. movement{1250ms, 0,1},
  90. movement{1250ms, 0,2},
  91. movement{1250ms, 0,2},
  92. movement{1250ms, 0,3},
  93. movement{1250ms, 0,3},
  94. movement{1250ms, 0,4},
  95. movement{1250ms, 0,4}
  96. });
  97. auto range = s.move(block, 500ms).updated;
  98. assert( block[0] == way(0.f,1.f, 0.5f / 1.25f) );
  99. assert( block[1] == 0.f );
  100. assert( range.end() - range.begin() == 1 );
  101. range = s.move(block, 500ms).updated;
  102. assert( block[0] == way(0.f,1.f, 1.f / 1.25f) );
  103. assert( block[1] == 0.f );
  104. assert( range.end() - range.begin() == 1 );
  105. range = s.move(block, 500ms).updated;
  106. assert( block[0] == way(0.f,1.f, 1.f) );
  107. assert( block[1] == way(0.f,1.f, 0.25f / 1.25f) );
  108. assert( range.end() - range.begin() == 2 );
  109. range = s.move(block, 500ms).updated;
  110. assert( block[0] == way(0.f,1.f, 1.f) );
  111. assert( block[1] == way(0.f,1.f, 0.75f / 1.25f) );
  112. assert( range.end() - range.begin() == 1 );
  113. range = s.move(block, 500ms).updated;
  114. assert( block[0] == way(0.f,1.f, 1.f) );
  115. assert( block[1] == way(0.f,1.f, 1.f) );
  116. assert( range.end() - range.begin() == 1 );
  117. // and again
  118. range = s.move(block, 500ms).updated;
  119. assert( block[0] == way(0.f,1.f, 1.f) ); // <- this block is not set
  120. assert( block[1] == way(0.f,2.f, 0.5f / 1.25f) ); // <- only the last block is set
  121. assert( range.end() - range.begin() == 1 );
  122. range = s.move(block, 500ms).updated;
  123. assert( block[0] == way(0.f,1.f, 1.f) );
  124. assert( block[1] == way(0.f,2.f, 1.f / 1.25f) );
  125. assert( range.end() - range.begin() == 1 );
  126. range = s.move(block, 500ms).updated;
  127. assert( block[0] == way(0.f,2.f, 1.f) ); // <- untill we get an update of size 2, then first block gets set to the earlier update, in general last N blocks are set by last N updates
  128. assert( block[1] == way(0.f,2.f, 0.25f / 1.25f) );
  129. assert( range.end() - range.begin() == 2 );
  130. range = s.move(block, 500ms).updated;
  131. assert( block[0] == way(0.f,2.f, 1.f) );
  132. assert( block[1] == way(0.f,2.f, 0.75f / 1.25f) );
  133. assert( range.end() - range.begin() == 1 );
  134. range = s.move(block, 500ms).updated;
  135. assert( block[0] == way(0.f,2.f, 1.f) );
  136. assert( block[1] == way(0.f,2.f, 1.f) );
  137. assert( range.end() - range.begin() == 1 );
  138. // once more for good measure
  139. range = s.move(block, 500ms).updated;
  140. assert( block[0] == way(0.f,2.f, 1.f) );
  141. assert( block[1] == way(0.f,3.f, 0.5f / 1.25f) );
  142. assert( range.end() - range.begin() == 1 );
  143. range = s.move(block, 500ms).updated;
  144. assert( block[0] == way(0.f,2.f, 1.f) );
  145. assert( block[1] == way(0.f,3.f, 1.f / 1.25f) );
  146. assert( range.end() - range.begin() == 1 );
  147. range = s.move(block, 500ms).updated;
  148. assert( block[0] == way(0.f,3.f, 1.f) ); // <- untill we get an update of size 2, then first block gets set to the earlier update, in general last N blocks are set by last N updates
  149. assert( block[1] == way(0.f,3.f, 0.25f / 1.25f) );
  150. assert( range.end() - range.begin() == 2 );
  151. range = s.move(block, 500ms).updated;
  152. assert( block[0] == way(0.f,3.f, 1.f) );
  153. assert( block[1] == way(0.f,3.f, 0.75f / 1.25f) );
  154. assert( range.end() - range.begin() == 1 );
  155. range = s.move(block, 500ms).updated;
  156. assert( block[0] == way(0.f,3.f, 1.f) );
  157. assert( block[1] == way(0.f,3.f, 1.f) );
  158. assert( range.end() - range.begin() == 1 );
  159. }
  160. struct set_order
  161. {
  162. static int order;
  163. int o = 0;
  164. set_order& operator=(float) { o = order++; return *this; }
  165. };
  166. int set_order::order = 0;
  167. void MoveUpdateOrder()
  168. {
  169. using movement = simple::motion::movement<duration,float,float>;
  170. std::array<set_order,3> block{};
  171. auto s = symphony(std::vector<movement>{
  172. movement{1250ms, 0,1},
  173. movement{1250ms, 0,1},
  174. movement{1250ms, 0,1},
  175. movement{1250ms, 0,1},
  176. movement{1250ms, 0,1},
  177. movement{1250ms, 0,1}
  178. });
  179. auto range = s.move(block, 3s).updated;
  180. assert( block[0].o == 0 );
  181. assert( block[1].o == 1 );
  182. assert( block[2].o == 2 );
  183. assert( range.end() - range.begin() == 3 );
  184. range = s.move(block, 3s).updated;
  185. assert( block[0].o == 3 );
  186. assert( block[1].o == 4 );
  187. assert( block[2].o == 5 );
  188. assert( range.end() - range.begin() == 3 );
  189. range = s.move(block, 3s).updated;
  190. assert( block[0].o == 3 ); // <- not set
  191. assert( block[1].o == 6 );
  192. assert( block[2].o == 7 );
  193. assert( range.end() - range.begin() == 2 );
  194. }
  195. void MoreUpdatesThanValues()
  196. {
  197. using movement = simple::motion::movement<duration,float,float>;
  198. std::array<float,2> block{0,0};
  199. auto s = symphony(std::vector<movement>{
  200. movement{1250ms, 0,1}, // <- ignored
  201. movement{1250ms, 0,1}, // <- sets block[0]
  202. movement{1250ms, 0,2}, // <- sets block[1]
  203. });
  204. auto range = s.move(block, 3s).updated;
  205. assert( block[0] == way(0.f,1.f, 1.f) );
  206. assert( block[1] == way(0.f,2.f, 0.5f / 1.25f) );
  207. assert( range.end() - range.begin() == 3 );
  208. }
  209. int main()
  210. {
  211. SharpTurn();
  212. Advance();
  213. MoveWithSmallerTarget();
  214. MoveUpdateOrder();
  215. MoreUpdatesThanValues();
  216. return 0;
  217. }