Положение
Я понял, что пишу много LeafSystem
классов, которые очень легко манипулируют входными данными и выплевывают их в качестве выходных данных. Все они не имеют состояния, и единственное их отличие - функция преобразования.
Примером этого является класс, который просто переупорядочивает входные данные, или класс, который просто удаляет ненужные входные данные.
Следовательно, я подумал написать класс LeafSystem
, который использует эту «функцию преобразования» в качестве аргумента, чтобы пропустить головную боль необходимости создавать новый класс каждый раз, когда я хочу обработать входные данные немного другим способом.
Идея - это конструктор, который принимает std::function
формы вместе с размером входного и выходного вектора.
std::function<void(const Eigen::VectorBlock<const drake::VectorX<T>>&, Eigen::VectorBlock<drake::VectorX<T>>& )>;
«Функция преобразования» может быть реализована в этом функторе.
Пример использования: если бы я хотел преобразовать данные состояния 3D (x, y, z, roll, pitch, yaw) в данные состояния 2D (x, y, yaw), я мог бы просто написать функтор, такой как
void 3Dto2D(const Eigen::VectorBlock<const drake::VectorX<T>>& input, Eigen::VectorBlock<drake::VectorX<T>>& output)
{
output[0] = input[0]; //x
output[1] = input[1]; //y
output[2] = input[5]; //yaw
output[3] = input[6]; //x_dot
output[4] = input[7]; //y_dot
output[5] = input[11]; //yaw_dot
}
И передать этот функтор в этот «StateConverter».
Проблема
Проблема, с которой я сталкиваюсь, касается конструктора копий с преобразованием в скаляр. Как мне реализовать это, когда у класса есть специфичные для типа объекты-члены?
Основная часть этого класса выглядит следующим образом (для полноты)
using ConversionFunc = std::function<void(const Eigen::VectorBlock<const drake::VectorX<T>>&, Eigen::VectorBlock<drake::VectorX<T>>& )>;;
// Some black magic to handle alias explicit template instantiation
template <typename T>
StateConverter<T>::StateConverter(ConversionFunc func, const unsigned int input_size, const unsigned int output_size) :
systems::LeafSystem<T>(systems::SystemTypeTag<StateConverter>{}),
input_idx(this->DeclareVectorInputPort("input_port", systems::BasicVector<T>(input_size)).get_index()),
output_idx(this->DeclareVectorOutputPort("output_port", systems::BasicVector<T>(output_size), &StateConverter::convert).get_index())
{
convert_func = func;
}
template <typename T>
void StateConverter<T>::convert(const drake::systems::Context<T>& context, systems::BasicVector<T>* output) const
{
const auto state = this->EvalVectorInput(context, input_idx)->get_value();
auto mutable_output = output->get_mutable_value();
convert_func(state, mutable_output);
}