Drake 产生正弦信号系统的子类

Drake 产生正弦信号系统的子类,drake,Drake,我试图创建一个子类LeafSystem,它的输出是正弦曲线及其导数。 我编写了代码并试图绘制它,但信号记录器没有正确记录 #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

我试图创建一个子类
LeafSystem
,它的输出是正弦曲线及其导数。 我编写了代码并试图绘制它,但信号记录器没有正确记录

#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;
}
#包括“drake/systems/framework/leaf_system.h”
#包括“drake/systems/analysis/simulator.h”
#包括“drake/systems/framework/diagram.h”
#包括“drake/systems/framework/diagram_builder.h”
#包括“drake/systems/primitives/signal_logger.h”
#包括“drake/common/proto/call_python.h”
类正弦:公共德雷克::系统::叶系统
{
公众:
正弦波(双启动、双频率、双放大器、双偏移):
m_freq(freq)、m_amp(amp)、m_offset(offset)、m_tstart(tstart){
此->DeclareVectorOutputPort(
drake::systems::BasicVector(2),&Sinusoid::output);
}
私人:
无效输出(常量drake::systems::Context&c,drake::systems::BasicVector*输出)常量{
双t(c.get_time());
双结(t-m_tstart);
如果(t>m_tstart){
输出->设置索引(0,标准::sin(tknot*m_freq+m_offset)*m_amp);
输出->设置索引(1,标准::cos(tknot*m_freq+m_offset)*m_amp*m_freq);
}否则{
输出->设置索引(0,0.0);
输出->设置索引(1,0.0);
}
}
双m_-freq{0.0},m_-amp{0.0},m_-offset{0.0},m_-tstart{0.0};
};
int main(int argc,char*argv[])
{
//添加系统并连接
drake::systems::DiagramBuilder builder;
自动系统=builder.AddSystem(1.0,2.*M_PI*1,3,0.);
自动记录器=注销输出(系统->获取输出端口(0),&builder);
auto diagram=builder.Build();
//构造模拟器
德雷克::系统::模拟器(*图);
//运行模拟
模拟机。步骤至(100);
//用Python绘图
自动采样时间=记录器->采样时间();
自动采样数据=记录器->数据();

STD::CUT

代码看起来很好。注意,这几乎是完全正确的(并且使用单输出源作为基类,您也可以考虑)。。唯一的问题是,您没有任何东西告诉模拟器有理由评估输出端口。对于每个发布事件,logger块都会使用它,但您没有告诉模拟器发布

解决办法是打电话

simulator.set_publish_every_timestep(true)


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

感谢您的即时回答@russ。我在构建模拟器后添加了一行代码,但代码仍然返回相同的结果。这让我感到惊讶,但我已经确认您是正确的。我在这里针对这个特殊的怪癖提出了一个问题:我还添加了一个API帮助程序,因为它应该没有那么难,这里: