Using ChFunctions in Chrono (demo_CH_functions.cpp)

Tutorial that teaches how to use the ChFunction inherited classes to build math functions of y=f(x) type. The ChFunction objects are 'building blocks' whose main usage is to describe motion laws, such as trajectories in automation and robotics, etc.

  • create and use ChFunction objects, from available classes.
  • define a custom function by inheriting from ChFunction class.
  • use the ChFunction_Sequence to build a sequence of basic functions
  • No GUI: only text output.
// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Alessandro Tasora, Radu Serban
// =============================================================================
//
// Demo code for using the ChFunction objects for specifying functions y=f(t)
//
// =============================================================================
#include "chrono/core/ChGlobal.h"
#include "chrono/motion_functions/ChFunction.h"
#include "chrono_thirdparty/filesystem/path.h"
// Use the namespace of Chrono
using namespace chrono;
int main(int argc, char* argv[]) {
GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
// Create (if needed) output directory
const std::string out_dir = GetChronoOutputPath() + "DEMO_FUNCTIONS";
if (!filesystem::create_directory(filesystem::path(out_dir))) {
std::cout << "Error creating directory " << out_dir << std::endl;
return 1;
}
//
// EXAMPLE 1: create a ramp ChFunction, set properties, evaluate it.
//
GetLog() << "==== Test 1...\n\n";
f_ramp.Set_ang(0.1); // set angular coefficient;
f_ramp.Set_y0(0.4); // set y value for x=0;
// Evaluate y=f(x) function at a given x value, using Get_y() :
double y_ramp = f_ramp.Get_y(10);
// Evaluate derivative df(x)/dx at a given x value, using Get_y_dx() :
double ydx_ramp = f_ramp.Get_y_dx(10);
GetLog() << " ChFunction_Ramp at x=0: y=" << y_ramp << " dy/dx=" << ydx_ramp << "\n\n";
//
// EXAMPLE 2: save values of a sine ChFunction into a file
//
GetLog() << "==== Test 2...\n\n";
f_sine.Set_amp(2); // set amplitude;
f_sine.Set_freq(1.5); // set frequency;
std::string sinefile = out_dir + "/f_sine_out.dat";
ChStreamOutAsciiFile file_f_sine(sinefile.c_str());
// Evaluate y=f(x) function along 100 x points, and its derivatives,
// and save to file (later it can be loaded, for example, in Matlab using the 'load()' command)
for (int i = 0; i < 100; i++) {
double x = (double)i / 50.0;
double y = f_sine.Get_y(x);
double ydx = f_sine.Get_y_dx(x);
double ydxdx = f_sine.Get_y_dxdx(x);
file_f_sine << x << " " << y << " " << ydx << " " << ydxdx << "\n";
}
//
// EXAMPLE 3: use a custom function (see class at the beginning of this file)
//
GetLog() << "==== Test 3...\n\n";
// The following class will be used as an example of how
// how you can create custom functions based on the ChFunction interface.
// There is at least one mandatory member function to implement: Get_y().
// [Note that the base class implements a default computation of derivatives
// Get_ydx() and Get_ydxdx() by using a numerical differentiation, however
// if you know the analytical expression of derivatives, you can override
// the base Get_ydx() and Get_ydxdx() too, for higher precision.]
class ChFunction_MyTest : public ChFunction {
public:
virtual ChFunction_MyTest* Clone() const override { return new ChFunction_MyTest(); }
virtual double Get_y(double x) const override { return cos(x); } // just for test: simple cosine
};
ChFunction_MyTest f_test;
std::string testfile = out_dir + "/f_test_out.dat";
ChStreamOutAsciiFile file_f_test(testfile.c_str());
// Evaluate y=f(x) function along 100 x points, and its derivatives,
// and save to file (later it can be loaded, for example, in Matlab using the 'load()' command)
for (int i = 0; i < 100; i++) {
double x = (double)i / 50.0;
double y = f_test.Get_y(x);
double ydx = f_test.Get_y_dx(x);
double ydxdx = f_test.Get_y_dxdx(x);
file_f_test << x << " " << y << " " << ydx << " " << ydxdx << "\n";
}
//
// EXAMPLE 4: mount some functions in a sequence using ChFunction_Sequence
//
GetLog() << "==== Test 4...\n\n";
ChFunction_Sequence f_sequence;
auto f_constacc1 = chrono_types::make_shared<ChFunction_ConstAcc>();
f_constacc1->Set_end(0.5); // length of ramp
f_constacc1->Set_h(0.3); // height of ramp
f_sequence.InsertFunct(f_constacc1, 0.5, 1, false, false, false, 0);
auto f_const = chrono_types::make_shared<ChFunction_Const>();
f_sequence.InsertFunct(f_const, 0.4, 1, true, false, false, -1);
auto f_constacc2 = chrono_types::make_shared<ChFunction_ConstAcc>();
f_constacc2->Set_end(0.6); // length of ramp
f_constacc2->Set_av(0.3); // acceleration ends after 30% length
f_constacc2->Set_aw(0.7); // deceleration starts after 70% length
f_constacc2->Set_h(-0.2); // height of ramp
f_sequence.InsertFunct(f_constacc2, 0.6, 1, true, false, false, -1);
f_sequence.Setup();
std::string seqfile = out_dir + "/f_sequence_out.dat";
ChStreamOutAsciiFile file_f_sequence(seqfile.c_str());
// Evaluate y=f(x) function along 100 x points, and its derivatives,
// and save to file (later it can be loaded, for example, in Matlab using the 'load()' command)
for (int i = 0; i < 100; i++) {
double x = (double)i / 50.0;
double y = f_sequence.Get_y(x);
double ydx = f_sequence.Get_y_dx(x);
double ydxdx = f_sequence.Get_y_dxdx(x);
file_f_sequence << x << " " << y << " " << ydx << " " << ydxdx << "\n";
}
//
// EXAMPLE 5: a repeating sequence
//
GetLog() << "==== Test 5...\n\n";
auto f_part1 = chrono_types::make_shared<ChFunction_Ramp>();
f_part1->Set_ang(.50);
auto f_part2 = chrono_types::make_shared<ChFunction_Const>();
f_part2->Set_yconst(1.0);
auto f_part3 = chrono_types::make_shared<ChFunction_Ramp>();
f_part3->Set_ang(-.50);
auto f_seq = chrono_types::make_shared<ChFunction_Sequence>();
f_seq->InsertFunct(f_part1, 1.0, 1, true);
f_seq->InsertFunct(f_part2, 1.0, 1., true);
f_seq->InsertFunct(f_part3, 1.0, 1., true);
auto f_rep_seq = chrono_types::make_shared<ChFunction_Repeat>();
f_rep_seq->Set_fa(f_seq);
f_rep_seq->Set_window_length(3.0);
f_rep_seq->Set_window_start(0.0);
f_rep_seq->Set_window_phase(3.0);
std::string repeatfile = out_dir + "/f_repeat_out.dat";
ChStreamOutAsciiFile file_f_repeat(repeatfile.c_str());
for (int i = 0; i < 1000; i++) {
double x = (double)i / 50.0;
double y = f_rep_seq->Get_y(x);
double ydx = f_rep_seq->Get_y_dx(x);
double ydxdx = f_rep_seq->Get_y_dxdx(x);
file_f_repeat << x << " " << y << " " << ydx << " " << ydxdx << "\n";
}
return 0;
}
Sine function y = sin (phase + w*x ) where w=2*PI*freq.
Definition: ChFunction_Sine.h:27
Interface base class for scalar functions of the type: y= f(x)
Definition: ChFunction_Base.h:45
void Set_y0(double m_y0)
The value for x=0;.
Definition: ChFunction_Ramp.h:48
bool InsertFunct(std::shared_ptr< ChFunction > myfx, double duration, double weight=1, bool c0=false, bool c1=false, bool c2=false, int position=-1)
Insert function after the fx with defined "position" index in list.
Definition: ChFunction_Sequence.cpp:108
void Setup()
Scans all the seq.of functions and setup the timings and continuity offsets, to satisfy all constrain...
Definition: ChFunction_Sequence.cpp:203
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
Linear function (like a straight ramp): y = y0 + x * speed
Definition: ChFunction_Ramp.h:27
virtual double Get_y(double x) const override
Return the y value of the function, at position x.
Definition: ChFunction_Ramp.h:43
virtual double Get_y(double x) const override
Return the y value of the function, at position x.
Definition: ChFunction_Sine.cpp:29
const std::string & GetChronoOutputPath()
Obtain the path to the output directory for Chrono demos.
Definition: ChGlobal.cpp:110
virtual double Get_y_dxdx(double x) const override
Return the ddy/dxdx double derivative of the function, at position x.
Definition: ChFunction_Sine.cpp:37
void Set_ang(double m_ang)
The angular coefficient.
Definition: ChFunction_Ramp.h:52
virtual double Get_y_dx(double x) const override
Return the dy/dx derivative of the function, at position x.
Definition: ChFunction_Ramp.h:44
virtual double Get_y_dx(double x) const override
Return the dy/dx derivative of the function, at position x.
Definition: ChFunction_Sine.cpp:33
virtual double Get_y_dx(double x) const override
Return the dy/dx derivative of the function, at position x.
Definition: ChFunction_Sequence.cpp:263
Main namespace for the Chrono package.
Definition: ChBarrelShape.cpp:17
This is a specialized class for ASCII output on system's file,.
Definition: ChStream.h:789
virtual double Get_y(double x) const override
Return the y value of the function, at position x.
Definition: ChFunction_Sequence.cpp:251
virtual double Get_y_dxdx(double x) const override
Return the ddy/dxdx double derivative of the function, at position x.
Definition: ChFunction_Sequence.cpp:275
Sequence function: y = sequence_of_functions(f1(y), f2(y), f3(y)) All other function types can be ins...
Definition: ChFunction_Sequence.h:68