@@ -34,10 +34,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3434
3535#include < ocs2_core/PreComputation.h>
3636#include < ocs2_core/integration/TrapezoidalIntegration.h>
37+ #include < ocs2_core/misc/LinearInterpolation.h>
3738#include < ocs2_oc/approximate_model/LinearQuadraticApproximator.h>
3839
3940namespace ocs2 {
4041
42+ namespace {
43+ template <typename DataType>
44+ void copySegment (const LinearInterpolation::index_alpha_t & indexAlpha0, const LinearInterpolation::index_alpha_t & indexAlpha1,
45+ const std::vector<DataType>& inputTrajectory, std::vector<DataType>& outputTrajectory) {
46+ outputTrajectory.clear ();
47+ outputTrajectory.resize (2 + indexAlpha1.first - indexAlpha0.first );
48+
49+ if (!outputTrajectory.empty ()) {
50+ outputTrajectory.front () = LinearInterpolation::interpolate (indexAlpha0, inputTrajectory);
51+ if (indexAlpha1.first >= indexAlpha0.first ) {
52+ std::copy (inputTrajectory.begin () + indexAlpha0.first + 1 , inputTrajectory.begin () + indexAlpha1.first + 1 ,
53+ outputTrajectory.begin () + 1 );
54+ }
55+ outputTrajectory.back () = LinearInterpolation::interpolate (indexAlpha1, inputTrajectory);
56+ }
57+ }
58+ } // unnamed namespace
59+
4160/* *****************************************************************************************************/
4261/* *****************************************************************************************************/
4362/* *****************************************************************************************************/
@@ -165,6 +184,74 @@ scalar_t rolloutTrajectory(RolloutBase& rollout, scalar_t initTime, const vector
165184 return (finalTime - initTime) / static_cast <scalar_t >(primalSolution.timeTrajectory_ .size ());
166185}
167186
187+ /* *****************************************************************************************************/
188+ /* *****************************************************************************************************/
189+ /* *****************************************************************************************************/
190+ void extractPrimalSolution (const std::pair<scalar_t , scalar_t >& timePeriod, const PrimalSolution& inputPrimalSolution,
191+ PrimalSolution& outputPrimalSolution) {
192+ // no controller
193+ if (outputPrimalSolution.controllerPtr_ != nullptr ) {
194+ outputPrimalSolution.controllerPtr_ ->clear ();
195+ }
196+ // for none StateTriggeredRollout initialize modeSchedule
197+ outputPrimalSolution.modeSchedule_ = inputPrimalSolution.modeSchedule_ ;
198+
199+ // create alias
200+ auto & timeTrajectory = outputPrimalSolution.timeTrajectory_ ;
201+ auto & stateTrajectory = outputPrimalSolution.stateTrajectory_ ;
202+ auto & inputTrajectory = outputPrimalSolution.inputTrajectory_ ;
203+ auto & postEventIndices = outputPrimalSolution.postEventIndices_ ;
204+
205+ /*
206+ * Find the indexAlpha pair for interpolation. The interpolation function uses the std::lower_bound while ignoring the initial
207+ * time event, we should use std::upper_bound. Therefore at the first step, we check if for the case where std::upper_bound
208+ * would have give a different solution (index_alpha_t::second = 0) and correct the pair. Then, in the second step, we check
209+ * whether the index_alpha_t::first is a pre-event index. If yes, we move index_alpha_t::first to the post-event index.
210+ */
211+ const auto indexAlpha0 = [&]() {
212+ const auto lowerBoundIndexAlpha = LinearInterpolation::timeSegment (timePeriod.first , inputPrimalSolution.timeTrajectory_ );
213+
214+ const auto upperBoundIndexAlpha = numerics::almost_eq (lowerBoundIndexAlpha.second , 0.0 )
215+ ? LinearInterpolation::index_alpha_t {lowerBoundIndexAlpha.first + 1 , 1.0 }
216+ : lowerBoundIndexAlpha;
217+ const auto it = std::find (inputPrimalSolution.postEventIndices_ .cbegin (), inputPrimalSolution.postEventIndices_ .cend (),
218+ upperBoundIndexAlpha.first + 1 );
219+ if (it == inputPrimalSolution.postEventIndices_ .cend ()) {
220+ return upperBoundIndexAlpha;
221+ } else {
222+ return LinearInterpolation::index_alpha_t {upperBoundIndexAlpha.first + 1 , 1.0 };
223+ }
224+ }();
225+ const auto indexAlpha1 = LinearInterpolation::timeSegment (timePeriod.second , inputPrimalSolution.timeTrajectory_ );
226+
227+ // time
228+ copySegment (indexAlpha0, indexAlpha1, inputPrimalSolution.timeTrajectory_ , timeTrajectory);
229+
230+ // state
231+ copySegment (indexAlpha0, indexAlpha1, inputPrimalSolution.stateTrajectory_ , stateTrajectory);
232+
233+ // input
234+ copySegment (indexAlpha0, indexAlpha1, inputPrimalSolution.inputTrajectory_ , inputTrajectory);
235+
236+ // If the pre-event index is within the range we accept the event
237+ postEventIndices.clear ();
238+ for (const auto & postIndex : inputPrimalSolution.postEventIndices_ ) {
239+ if (postIndex > static_cast <size_t >(indexAlpha0.first ) && inputPrimalSolution.timeTrajectory_ [postIndex - 1 ] <= timePeriod.second ) {
240+ postEventIndices.push_back (postIndex - static_cast <size_t >(indexAlpha0.first ));
241+ }
242+ }
243+
244+ // If there is an event at final time, it misses its pair (due to indexAlpha1 and copySegment)
245+ if (!postEventIndices.empty () && postEventIndices.back () == timeTrajectory.size ()) {
246+ constexpr auto eps = numeric_traits::weakEpsilon<scalar_t >();
247+ const auto indexAlpha2 = LinearInterpolation::timeSegment (timePeriod.second + eps, inputPrimalSolution.timeTrajectory_ );
248+
249+ timeTrajectory.push_back (std::min (timePeriod.second + eps, timePeriod.second ));
250+ stateTrajectory.push_back (LinearInterpolation::interpolate (indexAlpha2, inputPrimalSolution.stateTrajectory_ ));
251+ inputTrajectory.push_back (LinearInterpolation::interpolate (indexAlpha2, inputPrimalSolution.inputTrajectory_ ));
252+ }
253+ }
254+
168255/* *****************************************************************************************************/
169256/* *****************************************************************************************************/
170257/* *****************************************************************************************************/
0 commit comments