0

I am trying to make a child class of LeafSystem whose output is sinusoidal and its derivative. I wrote the code and try to plot it but signal logger doesn't log correctly.

#include "drake/systems/framework/leaf_system.h"
#include "drake/systems/analysis/simulator.h"
#include "drake/systems/framework/diagram.h"
#include "drake/systems/framework/diagram_builder.h"
#include "drake/systems/primitives/signal_logger.h"
#include "drake/common/proto/call_python.h"

class Sinusoid : public drake::systems::LeafSystem<double>
{
public:
    Sinusoid (double tstart, double freq, double amp, double offset) :
        m_freq(freq), m_amp(amp), m_offset(offset), m_tstart(tstart) {
    this->DeclareVectorOutputPort(
            drake::systems::BasicVector<double>(2), &Sinusoid::output);
        }

private:
    void output(const drake::systems::Context<double>& c,             drake::systems::BasicVector<double>* output) const {
      double t(c.get_time());
      double tknot(t - m_tstart);
      if (t > m_tstart) {
          output->SetAtIndex(0, std::sin(tknot*m_freq +     m_offset)*m_amp);
          output->SetAtIndex(1, std::cos(tknot*m_freq +     m_offset)*m_amp*m_freq);
      } else {
          output->SetAtIndex(0, 0.0);
          output->SetAtIndex(1, 0.0);
      }
    }
    double m_freq{0.0}, m_amp{0.0}, m_offset{0.0}, m_tstart{0.0};
};

int main(int argc, char *argv[])
{
    // Add System and Connect
    drake::systems::DiagramBuilder<double> builder;
    auto system  = builder.AddSystem<Sinusoid>(1.0, 2.*M_PI*1., 3., 0.);
    auto logger = LogOutput(system->get_output_port(0), &builder);
    auto diagram = builder.Build();

    // Construct Simulator
    drake::systems::Simulator<double> simulator(*diagram);

    // Run simulation
    simulator.StepTo(100);

    // Plot with Python
    auto sample_time = logger->sample_times();
    auto sample_data = logger->data();
    std::cout << sample_time.size() << std::endl;
    for (int i = 0; i < sample_time.size(); ++i) {
        std::cout << sample_time(i) << " : " << sample_data(i, 0) << "      " << sample_data(i, 1) << std::endl;
        }

    std::cout << "END" << std::endl;
    return 0;
}

The output of the code is 2 0 : 0 0 0 : 0 0 END Whatever number I used in StepTo function, signal logger only cate 2 data whose sampled times are both 0.

4

1 回答 1

0

代码看起来不错。请注意,TrajectorySource几乎完全做到了这一点(并且使用 SingleOutputVectorSource 作为基类,您也可以考虑使用它)。唯一的问题是你没有任何东西告诉模拟器有理由评估输出端口。记录器块将为每个发布事件拉取,但您还没有告诉模拟器发布。

解决方法是调用

simulator.set_publish_every_timestep(true)

http://drake.mit.edu/doxygen_cxx/classdrake_1_1systems_1_1_simulator.html#aef1dc6aeb821503379ab1dd8c6044562

如果您想进一步控制积分器的时间步长,您可以设置积分器的参数(例如 simalator.get_integerator),然后调用set_fixed_step_mode

于 2018-06-11T10:45:37.310 回答