43 if (environment.getController())
45 environment.getController()->getAvailableSignals(signal_target);
49 signal_target.registerMeasurement(ns +
"control_input", environment.getController()->getControlInputDimension(), {},
true);
53 if (environment.getPlant())
55 environment.getPlant()->getAvailableSignals(signal_target);
57 signal_target.registerMeasurement(ns +
"plant_output", environment.getPlant()->getOutputDimension());
60 if (environment.getObserver())
62 environment.getObserver()->getAvailableSignals(signal_target);
64 signal_target.registerMeasurement(ns +
"observed_states", environment.getObserver()->getStateDimension());
69 signal_target.registerMeasurement(ns +
"comp_states", environment.getObserver()->getStateDimension());
74 signal_target.registerMeasurement(ns +
"reference/x",
_xreference->getDimension());
78 signal_target.registerMeasurement(ns +
"reference/u",
_ureference->getDimension());
86 if (
_dt <= 0 && !environment.getController()->supportsAsynchronousControl())
88 PRINT_ERROR(
"ClosedLoopControlTask::performTask(): dt <= 0 selected, but current controller does not support asynchronous control.");
97 ControllerInterface* controller = environment.getController().get();
98 PlantInterface* plant = environment.getPlant().get();
99 ObserverInterface* observer = environment.getObserver().get();
101 using ControlVector = Eigen::VectorXd;
102 using StateVector = Eigen::VectorXd;
103 using OutputVector = Eigen::VectorXd;
107 u_sequence->add(0, ControlVector::Zero(plant->getOutputDimension()));
109 OutputVector
y(plant->getOutputDimension());
110 StateVector
x(controller->getStateDimension());
115 if (!
verify(environment, msg))
return;
123 if (!plant->initialize())
138 Time compensator_meas_start;
139 Duration cpu_time(0);
140 Duration cpu_time_cache(0);
147 std::vector<std::pair<double, Eigen::VectorXd>> useq_predict;
153 while (t <= tf &&
ok())
155 Duration last_dt = (t == Time(0)) ? Duration(0) : dt;
164 signal_target->sendMeasurement(ns +
"reference/x", t.toSec(), xref);
165 signal_target->sendMeasurement(ns +
"reference/u", t.toSec(), uref);
170 if (!plant->output(
y, t, signal_target, ns))
PRINT_ERROR(
"ClosedLoopControl::performTask(): error while retreiving plant output.");
171 if (signal_target) signal_target->sendMeasurement(ns +
"plant_output", t.toSec(),
y);
178 if (!observer->observe(
y,
x, last_dt, t, signal_target, ns))
PRINT_ERROR(
"ClosedLoopControl::performTask(): observer error.");
179 if (signal_target) signal_target->sendMeasurement(ns +
"observed_states", t.toSec(),
x);
199 if (!controller->step(
x, *
_xreference, *
_ureference, last_dt, t, u_sequence, x_sequence, signal_target,
nullptr,
nullptr,
nullptr, ns))
201 PRINT_ERROR(
"ClosedLoopControl::performTask(): controller error.");
203 u_sequence->add(t.toSec(), Eigen::VectorXd::Zero(controller->getControlInputDimension()));
209 if (controller->getControlDuration() >=
_min_dt)
211 if (controller->getControlDuration() <=
_max_dt)
213 dt.fromSec(controller->getControlDuration());
214 rate.updateCycleTime(dt);
219 "ClosedLoopControl::performTask(): asychnronous control mode: controller returned dt>_max_dt. Setting dt=dt_max. This "
220 "warning is printed once.");
227 "ClosedLoopControl::performTask(): asychnronous control mode: controller returned dt<_min_dt. Setting dt=dt_min. This warning is "
235 plant->control(u_sequence, x_sequence, dt, t, signal_target, ns);
243 cpu_time =
Time::now() - compensator_meas_start;
244 cpu_time_cache = cpu_time;
253 if (
_use_wall_time) t.fromSec(t_measure_x.toSec() + deadtime + cpu_time_cache.toSec());
254 controller->sendSignals(t.toSec(), *signal_target, ns);
255 if (u_sequence && !u_sequence->isEmpty()) signal_target->sendMeasurement(ns +
"control_input", t.toSec(), u_sequence->getValuesMap(0));
260 PRINT_WARNING(
"ClosedLoopControlTask(): rate exceeded (" << rate.lastCycleTime().toSec() <<
"s/" << dt <<
"s).");
272 if (msg) msg->clear();
278 if (msg) *msg +=
"State reference trajectory not specified for ClosedLoopControlTask\n";
285 if (msg) *msg +=
"Control reference trajectory not specified for ClosedLoopControlTask\n";
289 std::string environment_msg;
290 ret_val = ret_val && environment.verify(&environment_msg);
291 if (msg) *msg += environment_msg;
292 if (ret_val ==
false)
return false;
295 if (environment.getController()->getStateDimension() !=
_xreference->getDimension())
299 *msg +=
"State reference trajectory dimension (" + std::to_string(
_xreference->getDimension()) +
300 ") does not match controller state dimension (" + std::to_string(environment.getController()->getStateDimension()) +
").\n";
302 if (environment.getController()->getControlInputDimension() !=
_ureference->getDimension())
306 *msg +=
"Control reference trajectory dimension (" + std::to_string(
_ureference->getDimension()) +
307 ") does not match controller control input dimension (" +
308 std::to_string(environment.getController()->getControlInputDimension()) +
").\n";
311 if (environment.getPlant()->requiresFutureControls() && !environment.getController()->providesFutureControls())
314 if (msg) *msg +=
"Controller does not support control sequences, that are required by the plant";
317 if (environment.getPlant()->requiresFutureStates() && !environment.getController()->providesFutureStates())
320 if (msg) *msg +=
"Controller does not support state sequences, that are required by the plant";
332 #ifdef MESSAGE_SUPPORT
333 void ClosedLoopControlTask::toMessage(corbo::messages::ClosedLoopControlTask& message)
const
351 void ClosedLoopControlTask::fromMessage(
const corbo::messages::ClosedLoopControlTask& message, std::stringstream* issues)
362 if (message.has_xreference())
366 if (util::get_oneof_field_type(message.xreference(),
"reference", type,
false))
372 xreference->fromMessage(message.xreference(), issues);
380 if (message.has_ureference())
384 if (util::get_oneof_field_type(message.ureference(),
"reference", type,
false))
390 ureference->fromMessage(message.ureference(), issues);
401 _compensator.fromMessage(message.compensator(), issues);
405 if (message.has_computation_delay_filter() && !message.computation_delay_filter().has_no_filter())
409 if (util::get_oneof_field_type(message.computation_delay_filter(),
"filter", type,
false))
415 filter->fromMessage(message.computation_delay_filter(), issues);