123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #include <cassert>
- #include <chrono>
- #include "simple/motion/movement.hpp"
- #include "simple/motion/symphony.hpp"
- using namespace std::literals;
- using duration = std::chrono::duration<float>;
- using simple::support::way;
- using simple::motion::symphony;
- template <typename T> class show_type;
- void SharpTurn()
- {
- // TODO: use rational, can't rely on float
- using movement = simple::motion::movement<duration,float,float>;
- std::array<float,2> block{0,0};
- auto sharp_turn = symphony(std::vector<movement>{
- movement{1250ms, 0,1},
- movement{1250ms, 0,1}
- });
- auto range = sharp_turn.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 0.5f / 1.25f) );
- assert( block[1] == 0.f );
- assert( range.end() - range.begin() == 1 );
- range = sharp_turn.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f / 1.25f) );
- assert( block[1] == 0.f );
- assert( range.end() - range.begin() == 1 );
- range = sharp_turn.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,1.f, 0.25f / 1.25f) );
- assert( range.end() - range.begin() == 2 );
- range = sharp_turn.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,1.f, 0.75f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- }
- void Advance()
- {
- using movement = simple::motion::movement<std::chrono::milliseconds,float,float>;
- auto sequence = symphony(std::vector{
- movement{10ms, 0,1},
- movement{10ms, 0,1},
- movement{10ms, 0,1},
- movement{10ms, 0,1}
- });
- const auto begin = sequence.range().begin();
- auto result = sequence.advance(10ms);
- assert( not result.done );
- assert( result.updated.lower() == begin+0 );
- assert( result.updated.upper() == begin+1 );
- assert( result.remaining == 0ms );
- result = sequence.advance(10ms);
- assert( not result.done );
- assert( result.updated.lower() == begin+1 );
- assert( result.updated.upper() == begin+2 );
- assert( result.remaining == 0ms );
- result = sequence.advance(10ms);
- assert( not result.done );
- assert( result.updated.lower() == begin+2 );
- assert( result.updated.upper() == begin+3 );
- assert( result.remaining == 0ms );
- result = sequence.advance(10ms);
- assert( result.done );
- assert( result.updated.lower() == begin+3 );
- assert( result.updated.upper() == begin+4 );
- assert( result.remaining == 0ms );
- sequence.reset();
- result = sequence.advance(15ms);
- assert( not result.done );
- assert( result.updated.lower() == begin+0 );
- assert( result.updated.upper() == begin+2 );
- assert( result.remaining == 0ms );
- result = sequence.advance(15ms);
- assert( not result.done );
- assert( result.updated.lower() == begin+1 );
- assert( result.updated.upper() == begin+3 );
- assert( result.remaining == 0ms );
- result = sequence.advance(15ms);
- assert( result.done );
- assert( result.updated.lower() == begin+3 );
- assert( result.updated.upper() == begin+4 );
- assert( result.remaining == 5ms );
- }
- void MoveWithSmallerTarget()
- {
- using movement = simple::motion::movement<duration,float,float>;
- std::array<float,2> block{0,0};
- auto s = symphony(std::vector<movement>{
- movement{1250ms, 0,1},
- movement{1250ms, 0,1},
- movement{1250ms, 0,2},
- movement{1250ms, 0,2},
- movement{1250ms, 0,3},
- movement{1250ms, 0,3},
- movement{1250ms, 0,4},
- movement{1250ms, 0,4}
- });
- auto range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 0.5f / 1.25f) );
- assert( block[1] == 0.f );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f / 1.25f) );
- assert( block[1] == 0.f );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,1.f, 0.25f / 1.25f) );
- assert( range.end() - range.begin() == 2 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,1.f, 0.75f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,1.f, 1.f) );
- assert( range.end() - range.begin() == 1 );
- // and again
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) ); // <- this block is not set
- assert( block[1] == way(0.f,2.f, 0.5f / 1.25f) ); // <- only the last block is set
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,2.f, 1.f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- 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
- assert( block[1] == way(0.f,2.f, 0.25f / 1.25f) );
- assert( range.end() - range.begin() == 2 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,2.f, 1.f) );
- assert( block[1] == way(0.f,2.f, 0.75f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,2.f, 1.f) );
- assert( block[1] == way(0.f,2.f, 1.f) );
- assert( range.end() - range.begin() == 1 );
- // once more for good measure
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,2.f, 1.f) );
- assert( block[1] == way(0.f,3.f, 0.5f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,2.f, 1.f) );
- assert( block[1] == way(0.f,3.f, 1.f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- 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
- assert( block[1] == way(0.f,3.f, 0.25f / 1.25f) );
- assert( range.end() - range.begin() == 2 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,3.f, 1.f) );
- assert( block[1] == way(0.f,3.f, 0.75f / 1.25f) );
- assert( range.end() - range.begin() == 1 );
- range = s.move(block, 500ms).updated;
- assert( block[0] == way(0.f,3.f, 1.f) );
- assert( block[1] == way(0.f,3.f, 1.f) );
- assert( range.end() - range.begin() == 1 );
- }
- struct set_order
- {
- static int order;
- int o = 0;
- set_order& operator=(float) { o = order++; return *this; }
- };
- int set_order::order = 0;
- void MoveUpdateOrder()
- {
- using movement = simple::motion::movement<duration,float,float>;
- std::array<set_order,3> block{};
- auto s = symphony(std::vector<movement>{
- movement{1250ms, 0,1},
- movement{1250ms, 0,1},
- movement{1250ms, 0,1},
- movement{1250ms, 0,1},
- movement{1250ms, 0,1},
- movement{1250ms, 0,1}
- });
- auto range = s.move(block, 3s).updated;
- assert( block[0].o == 0 );
- assert( block[1].o == 1 );
- assert( block[2].o == 2 );
- assert( range.end() - range.begin() == 3 );
- range = s.move(block, 3s).updated;
- assert( block[0].o == 3 );
- assert( block[1].o == 4 );
- assert( block[2].o == 5 );
- assert( range.end() - range.begin() == 3 );
- range = s.move(block, 3s).updated;
- assert( block[0].o == 3 ); // <- not set
- assert( block[1].o == 6 );
- assert( block[2].o == 7 );
- assert( range.end() - range.begin() == 2 );
- }
- void MoreUpdatesThanValues()
- {
- using movement = simple::motion::movement<duration,float,float>;
- std::array<float,2> block{0,0};
- auto s = symphony(std::vector<movement>{
- movement{1250ms, 0,1}, // <- ignored
- movement{1250ms, 0,1}, // <- sets block[0]
- movement{1250ms, 0,2}, // <- sets block[1]
- });
- auto range = s.move(block, 3s).updated;
- assert( block[0] == way(0.f,1.f, 1.f) );
- assert( block[1] == way(0.f,2.f, 0.5f / 1.25f) );
- assert( range.end() - range.begin() == 3 );
- }
- int main()
- {
- SharpTurn();
- Advance();
- MoveWithSmallerTarget();
- MoveUpdateOrder();
- MoreUpdatesThanValues();
- return 0;
- }
|