Programming examples
Main author: Simon Rohou
The following examples illustrate basic operations on sliced tubes.
Example 1: building and evaluating a scalar tube
The following example builds a scalar tube over a sampled temporal domain and assigns different values on successive temporal intervals.
td = create_tdomain([0,3], 1., False)
x = SlicedTube(td, Interval()) # [-∞,∞] by default for any time
x.set([1,5], [0,1])
x.set([2,8], [1,2])
x.set([6,9], [2,3])
y0 = x([0,3])
y1 = x(1.5)
y2 = x(1.)
auto td = create_tdomain({0,3}, 1., false);
SlicedTube x(td, Interval()); // [-∞,∞] by default for any time
x.set({1,5}, {0,1});
x.set({2,8}, {1,2});
x.set({6,9}, {2,3});
auto y0 = x({0,3});
auto y1 = x(1.5);
auto y2 = x(1.);
Example 2: refining a temporal domain from a tube update
Local assignments refine the shared temporal partition when necessary.
td = create_tdomain([0,1], 0.1, False)
x = SlicedTube(td, IntervalVector(3))
before = td.nb_tslices()
x.set(IntervalVector.constant(3,[2,3]), -42.)
after = td.nb_tslices() # the partition was extended and refined
auto td = create_tdomain({0,1}, 0.1, false);
SlicedTube x(td, IntervalVector(3));
auto before = td->nb_tslices();
x.set(IntervalVector::constant(3,{2,3}), -42.);
auto after = td->nb_tslices(); // the partition was extended and refined
The same partition is updated for all tubes sharing the temporal domain.
Example 3: tube from an analytic function
For \(f(t)=10\cos(t)+t\), a SlicedTube encloses the function over each time slice rather than evaluating it only at isolated timestamps.
td = create_tdomain([0,5], 0.1, True)
t = ScalarVar()
f = AnalyticFunction([t], 10*cos(t) + t)
x = SlicedTube(td, f) # encloses f(t) over each time slice
auto td = create_tdomain({0,5}, 0.1, true);
ScalarVar t;
AnalyticFunction f({t}, 10*cos(t)+t);
SlicedTube x(td, f); // encloses f(t) over each time slice
Example 4: derivative-aware slice reasoning
The following pattern uses a derivative tube and CtcDeriv to sharpen a scalar slice. The slice can then build a polygonal enclosure used for refined evaluation or inversion.
td = create_tdomain([6.4,6.5])
x = SlicedTube(td, Interval(0.759,1.205))
v = SlicedTube(td, Interval(-0.216,-0.115))
x.set(Interval(0.781,1.205), 6.4)
x.set(Interval(0.759,1.194), 6.5)
CtcDeriv().contract(x,v)
sx = x.first_slice()
sv = v.first_slice()
polygon = sx.polygon_slice(sv)
auto td = create_tdomain({6.4,6.5});
SlicedTube x(td, Interval(0.759,1.205));
SlicedTube v(td, Interval(-0.216,-0.115));
x.set(Interval(0.781,1.205), 6.4);
x.set(Interval(0.759,1.194), 6.5);
CtcDeriv ctc;
ctc.contract(x,v);
auto sx = x.first_slice();
auto sv = v.first_slice();
auto polygon = sx->polygon_slice(*sv);
The derivative constraint can narrow the tube before evaluating individual slices.
Example 5: integration and primitive tubes
The integration API supports point and interval queries and can also build a primitive tube.
td = create_tdomain([0,2], 0.5, True)
x = SlicedTube(td, Interval(1,2))
integral_at_one = x.integral(Interval(1))
integral_over_range = x.integral(Interval(0.5,1.5))
p = x.primitive(Interval(0))
auto td = create_tdomain({0,2}, 0.5, true);
SlicedTube x(td, Interval(1,2));
auto integral_at_one = x.integral(Interval(1));
auto integral_over_range = x.integral(Interval(0.5,1.5));
auto p = x.primitive(Interval(0));
Example 6: Cartesian product of tubes
When several sliced tubes share the same temporal domain, you can build a vector-valued tube by stacking their codomains slice by slice.
td = create_tdomain([0,1], 0.5, False)
x1 = SlicedTube(td, Interval(0,1))
x2 = SlicedTube(td, IntervalVector([[1,2],[-1,1]]))
x = tube_cart_prod(x1, x2) # vector tube of dimension 3
auto td = create_tdomain({0,1}, 0.5, false);
SlicedTube x1(td, Interval(0,1));
SlicedTube x2(td, IntervalVector({{1,2},{-1,1}}));
auto x = tube_cart_prod(x1,x2); // vector tube of dimension 3
All inputs must share the same temporal-domain object.
For the analogous operation on SampledTraj objects, see Operations on trajectories (traj_cart_prod).