1 //#************************************************************** 2 //# 3 //# filename: control.h 4 //# 5 //# author: Gerstmayr Johannes, Rafael Ludwig 6 //# 7 //# generated: 9 October 2008 8 //# description: Elements for control, transmission elements, etc. 9 //# 10 //# remarks: 11 //# 12 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian 13 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the 14 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved. 15 //# 16 //# This file is part of HotInt. 17 //# HotInt is free software: you can redistribute it and/or modify it under the terms of 18 //# the HOTINT license. See folder 'licenses' for more details. 19 //# 20 //# bug reports are welcome!!! 21 //# WWW: www.hotint.org 22 //# email: bug_reports@hotint.org or support@hotint.org 23 //#*************************************************************************************** 24 25 #ifndef CONTROL__H 26 #define CONTROL__H 27 28 #include "TcpIpRoutines.h" 29 30 const int IOInputTypeElement = 1; 31 const int IOInputTypeSensor = 2; 32 33 //$ RE 2012-11-15: autogeneration functions and variables added 34 35 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 36 //**begin(ued)** 37 // name: InputOutputElement (Constraint) 38 // short description: Superclass for continuous input-output elements 39 // available formulations: Continuous state-space elements 40 // type: SISO (single input-single output); MIMO (multi input-multi output) 41 // development status: complete, auto-generation functions not complete 42 // long description: Superclass providing basic functions for CONTINUOUS input-output elements ==> only subclasses are useful for simulation (e.g. for controller circuits) 43 // class variables: 44 // -inputs: sensor number i: if (input_type==1==IOInputTypeElement) --> global number of InputOutputElement; if (input_type==2==IOInputTypeSensor) --> global sensor number 45 // -input_types: 1==InputOutputElement, 2==Sensor 46 // -input_localnum: output number of sensor: if (input_type==1) --> output number of InputOutputElement 47 // -n_output: number of ouputs 48 // -n_state: number of state variables (integrators) 49 // -ref_pos: reference position of InputOutputSymbol 50 // -draw_dim: drawing parameters 51 // -rotation: rotation, 1==90�, 2==180�, 3==270�, 4=360� 52 // -colbackground: background color of control objects 53 // -colforeground: foreground color of control objects 54 // -input_nodes: nodal positions of connections of inputs 55 // -input_nodes_num: input number for according input_nodes 56 //**end(ued)** 57 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 58 59 class InputOutputElement: public Constraint //$EDC$[beginclass,classname=InputOutputElement,parentclassname=Constraint,texdescription=" 60 //The InputOutputElement is the superclass for continuous input-output elements (e.g.: gain, transfer functions, etc.). 61 //Specialized subclasses of the InputOutputElement can be used in the model. Subclasses of these port-block elements can be connected by 62 //their inputs and outputs. The values of the outputs can be measured by sensors. 63 //"] 64 { 65 public: 66 InputOutputElement(MBS * mbsi)67 InputOutputElement(MBS* mbsi):Constraint(mbsi), inputs(0), input_types(0), input_localnum(0) 68 { 69 mbs = mbsi; //is set in ::Contraint::Element(mbsi) 70 InitConstructor(); 71 }; 72 73 //To be overwritten in derived class: GetCopy()74 virtual Element* GetCopy() 75 { 76 Element* ec = new InputOutputElement(*this); 77 return ec; 78 } 79 //To be overwritten in derived class: 80 virtual void CopyFrom(const Element& e); 81 82 virtual void InitConstructor(); 83 GetElementSpec()84 virtual const char* GetElementSpec() const {return "InputOutputElement";} 85 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()86 virtual int GetExpectedNumberOfInputs(){return -1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 87 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 88 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 89 virtual int GetAvailableSpecialValues(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); 90 virtual int ReadSingleElementData(ReadWriteElementDataVariableType& RWdata); 91 92 //----------------------------------------------------- 93 //b: auto-generated functions 94 virtual void GetElementDataAuto(ElementDataContainer& edc); 95 virtual int SetElementDataAuto(ElementDataContainer& edc); 96 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 97 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 98 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 99 //e: auto-generated functions 100 //----------------------------------------------------- 101 EvalF(Vector & f,double t)102 virtual void EvalF(Vector& f, double t) 103 { 104 //to be overwritten in specific class! 105 106 }; EvalG(Vector & f,double t)107 virtual void EvalG(Vector& f, double t) {}; 108 AddElementCqTLambda(double t,int locelemind,Vector & f)109 virtual void AddElementCqTLambda(double t, int locelemind, Vector& f) {}; 110 ComputationFinished()111 virtual void ComputationFinished() {}; //function is called when computation is finished (e.g. in order to free memory, write results, close connections, etc.) 112 IS()113 virtual int IS() const {return 0;}; ES()114 virtual int ES() const {return n_state;}; Dim()115 virtual int Dim() const {return 2;} //drawing is 2D 116 117 //get a reference position of the body in 3d GetRefPos2DD()118 virtual Vector2D GetRefPos2DD() const 119 { 120 return Vector2D(ref_pos.X(), ref_pos.Y()); 121 } 122 123 //get a reference position of the body in 3d GetRefPosD()124 virtual Vector3D GetRefPosD() const 125 { 126 return Vector3D(GetRefPos2DD().X(), GetRefPos2DD().Y(), 0.); 127 } 128 SetDrawBackgroundColor(const Vector3D & coli)129 virtual void SetDrawBackgroundColor(const Vector3D& coli){colbackground = coli;} GetDrawBackgroundColor()130 virtual const Vector3D& GetDrawBackgroundColor(){return colbackground;} 131 SetDrawForegroundColor(const Vector3D & coli)132 virtual void SetDrawForegroundColor(const Vector3D& coli){colforeground = coli;} GetDrawForegroundColor()133 virtual const Vector3D& GetDrawForegroundColor(){return colforeground;} 134 135 virtual void AddInput(int ioelem_num, int input_type, int localnumI=1) 136 { 137 inputs.Add(ioelem_num); 138 input_types.Add(input_type); 139 input_localnum.Add(localnumI); 140 141 if (input_type == IOInputTypeElement) //input is other input-output element 142 { 143 AddElement(ioelem_num); //add Dependency to this element! 144 } 145 else if (input_type == IOInputTypeSensor) //input is sensor 146 { 147 AddSensor(ioelem_num); 148 } 149 } 150 151 // attention: all input_portnum must have correct connection to input element AddInput(int ioelem_num,int input_type,int localnumI,int input_portnum)152 virtual void AddInput(int ioelem_num, int input_type, int localnumI, int input_portnum) 153 { 154 inputs(input_portnum) = ioelem_num; 155 input_types(input_portnum) = input_type; 156 input_localnum(input_portnum) = localnumI; 157 158 if (input_type == IOInputTypeElement) //input is other input-output element 159 { 160 AddElement(ioelem_num); //add Dependency to this element! 161 } 162 else if (input_type == IOInputTypeSensor) //input is sensor 163 { 164 AddSensor(ioelem_num); 165 } 166 } 167 GetInputNum(int i)168 virtual int GetInputNum(int i) const {return inputs(i);} GetInputLocalNum(int i)169 virtual int GetInputLocalNum(int i) const {return input_localnum(i);} GetInputType(int i)170 virtual int GetInputType(int i) const {return input_types(i);} GetNInputs()171 virtual int GetNInputs() const {return inputs.Length();} //$EDC$[funcaccess,readonly,EDCvarname="number_of_inputs",EDCfolder="IOBlock",tooltiptext="number of inputs"] GetNOutputs()172 virtual int GetNOutputs() const {return n_output;} //$EDC$[funcaccess,readonly,EDCvarname="number_of_outputs",EDCfolder="IOBlock",tooltiptext="number of outputs"] GetNStates()173 virtual int GetNStates() const {return n_state;} //$EDC$[funcaccess,readonly,EDCvarname="number_of_states",EDCfolder="IOBlock",tooltiptext="number of states"] 174 SetNOutputs(int i)175 virtual void SetNOutputs(int i) {n_output = i;} 176 177 virtual void SetOutputName(int output_nr, mystr& name); 178 virtual char* GetOutputName(int output_nr); 179 SetNStates(int i)180 virtual void SetNStates(int i) {n_state = i;} 181 SetRefPos2D(Vector2D rp)182 virtual void SetRefPos2D(Vector2D rp) {ref_pos = rp;} SetDrawDim(const Vector3D & drawdim)183 virtual void SetDrawDim(const Vector3D& drawdim) {draw_dim = drawdim;} SetRotation(double rot)184 virtual void SetRotation(double rot) {rotation = rot;}; //1=90�, 2=180�, ... GetRotation()185 virtual double GetRotation() const {return rotation;} 186 187 virtual double GetInput(double t, int i=1) const 188 { 189 if(input_types.Length() < i || inputs.Length() < i) 190 { 191 mbs->UO(UO_LVL_err).InstantMessageText(mystr("Error: input ") + mystr(i) + mystr(" of element with number ") + mystr(GetOwnNum()) + mystr(" not found. Input is set to zero!!!\n")); 192 return 0.; 193 } 194 //if(inputs(i) < 1 || inputs(i) > mbs->NE()) 195 if(inputs(i) < 1 || (inputs(i) > mbs->NE() && input_types(i) == IOInputTypeElement) || (inputs(i) > mbs->NSensors() && input_types(i) == IOInputTypeSensor)) // $ MSax 2013-07-29: bugfix 196 { 197 mbs->UO(UO_LVL_err).InstantMessageText(mystr("Error: element with number ") + mystr(inputs(i)) + mystr(" not found --> input of element with number ") + mystr(GetOwnNum()) + mystr(" is set to zero!!!\n")); 198 return 0.; 199 } 200 201 if (input_types(i) == IOInputTypeElement) //InputOutputElement 202 { 203 const InputOutputElement& ioe = (const InputOutputElement&)GetMBS()->GetElement(inputs(i)); 204 //const InputOutputElement* ioe = (InputOutputElement*)GetMBS()->GetElementPtr(inputs(i)); 205 return ioe.GetOutput(t, input_localnum(i)); 206 } 207 else if (input_types(i) == IOInputTypeSensor) 208 { 209 //$ YV 2012-06: the sensors may produce just one scalar value 210 const Sensor & s = GetMBS()->GetSensor(inputs(i)); 211 //$ YV 2012-06: here we use an explicit conversion to avoid difficulties with the ``const'' modifier 212 return ((Sensor &)s).GetCurrentValueWithSensorProcessing(t); 213 } 214 else 215 { 216 //should not happen: 217 mbs->UO().InstantMessageText("Unknown input_type --> input of element " + elementname + " was set to zero!"); 218 return 0; 219 } 220 } 221 222 virtual double GetOutput(double t, int i=1) const {return 0;} //to be overwritten in specific class! 223 224 225 virtual void GetDirectFeedThroughElements(TArray<int>& elnums) const; //return all elements which are depending on this element by direct feed through IsDirectFeedThrough()226 virtual int IsDirectFeedThrough() const {return 0;} 227 SetInitialValues(const Vector & xi)228 virtual void SetInitialValues(const Vector& xi) {x_init = xi;} 229 GetElementBox()230 virtual Box3D GetElementBox() const 231 { 232 if (GetMBS()->GetIOption(144)) 233 { 234 // orientation 235 double phi = rotation*MY_PI*0.5; 236 Matrix3D rot = RotMatrix3(phi); 237 238 Vector2D rp = GetRefPos2D(); // reference position 239 Vector3D rp3 = ToP3D(rp); // reference position 3D 240 241 // rectangle 242 double b = draw_dim.X(); 243 double h = draw_dim.Y(); 244 Vector3D p1(-0.75*b,-0.75*h,0.); 245 Vector3D p2( 0.75*b,-0.75*h,0.); 246 Vector3D p3( 0.75*b, 0.75*h,0.); 247 Vector3D p4(-0.75*b, 0.75*h,0.); 248 249 // rotate and translate rectangle 250 p1 = rp3+rot*p1; 251 p2 = rp3+rot*p2; 252 p3 = rp3+rot*p3; 253 p4 = rp3+rot*p4; 254 255 // box 256 double dimZ = sqrt(b*h); 257 Box3D box; 258 box.Add(Vector3D( p1.X(), p1.Y(),-dimZ)); 259 box.Add(Vector3D( p2.X(), p2.Y(),-dimZ)); 260 box.Add(Vector3D( p3.X(), p3.Y(),-dimZ)); 261 box.Add(Vector3D( p4.X(), p4.Y(),-dimZ)); 262 box.Add(Vector3D( p1.X(), p1.Y(), dimZ)); 263 box.Add(Vector3D( p2.X(), p2.Y(), dimZ)); 264 box.Add(Vector3D( p3.X(), p3.Y(), dimZ)); 265 box.Add(Vector3D( p4.X(), p4.Y(), dimZ)); 266 box.Increase(dimZ); 267 return box; 268 } 269 else 270 { 271 Box3D b; 272 return b; 273 } 274 } 275 GetElementBoxD()276 virtual Box3D GetElementBoxD() const 277 { 278 if (GetMBS()->GetIOption(144)) 279 { 280 // orientation 281 double phi = rotation*MY_PI*0.5; 282 Matrix3D rot = RotMatrix3(phi); 283 284 Vector2D rp = GetRefPos2DD(); // reference position 285 Vector3D rp3 = ToP3D(rp); // reference position 3D 286 287 // rectangle 288 double b = draw_dim.X(); 289 double h = draw_dim.Y(); 290 Vector3D p1(-0.75*b,-0.75*h,0.); 291 Vector3D p2( 0.75*b,-0.75*h,0.); 292 Vector3D p3( 0.75*b, 0.75*h,0.); 293 Vector3D p4(-0.75*b, 0.75*h,0.); 294 295 // rotate and translate rectangle 296 p1 = rp3+rot*p1; 297 p2 = rp3+rot*p2; 298 p3 = rp3+rot*p3; 299 p4 = rp3+rot*p4; 300 301 // box 302 double dimZ = sqrt(b*h); 303 Box3D box; 304 box.Add(Vector3D( p1.X(), p1.Y(),-dimZ)); 305 box.Add(Vector3D( p2.X(), p2.Y(),-dimZ)); 306 box.Add(Vector3D( p3.X(), p3.Y(),-dimZ)); 307 box.Add(Vector3D( p4.X(), p4.Y(),-dimZ)); 308 box.Add(Vector3D( p1.X(), p1.Y(), dimZ)); 309 box.Add(Vector3D( p2.X(), p2.Y(), dimZ)); 310 box.Add(Vector3D( p3.X(), p3.Y(), dimZ)); 311 box.Add(Vector3D( p4.X(), p4.Y(), dimZ)); 312 box.Increase(dimZ); 313 return box; 314 } 315 else 316 { 317 Box3D b; 318 return b; 319 } 320 } 321 322 virtual void DrawElement(); 323 virtual void DrawElement2D(); 324 virtual void DrawBlockSymbol(); 325 326 virtual const char* SymbolText() const; 327 AddInputNode(int input_num,const Vector2D & node)328 virtual void AddInputNode(int input_num, const Vector2D& node) // Adds a construction Node to an input ( at "outer" position ) 329 { 330 input_nodes.Add(node); 331 input_nodes_num.Add(input_num); 332 } 333 ConNodePos(int i)334 virtual Vector2D ConNodePos(int i) { return input_nodes(i); } 335 // list operation: insert a construction node into the list ( both lists, at position i ) InsertConNode(int list_idx,int input_nr,Vector2D & node)336 virtual void InsertConNode(int list_idx, int input_nr, Vector2D& node) 337 { 338 // insert at array position defined by list_idx 339 input_nodes.Insert(list_idx, node); 340 input_nodes_num.Insert(list_idx, input_nr); 341 } 342 // list operation: delete the construction node from both arays DeleteConNode(int list_idx)343 virtual void DeleteConNode(int list_idx) // 344 { 345 input_nodes.Erase(list_idx); 346 input_nodes_num.Erase(list_idx); 347 } MoveConNode2D(int list_idx,double delta_x,double delta_y)348 virtual void MoveConNode2D(int list_idx, double delta_x, double delta_y) 349 { 350 Vector2D& p = input_nodes.Elem(list_idx); 351 p.X() += delta_x; 352 p.Y() += delta_y; 353 354 } MoveElement(double delta_x,double delta_y,double delta_z)355 virtual void MoveElement(double delta_x, double delta_y, double delta_z) 356 { 357 //Vector2D& refpos = ref_pos // IOElement has only 2D refpos 358 ref_pos.X() += delta_x; 359 ref_pos.Y() += delta_y; 360 // refpos.Z() += delta_z; 361 362 } 363 364 365 virtual Vector2D GetInputPosD(int i) const; //return absolute position of input #i GetInputPos3DD(int i)366 virtual Vector3D GetInputPos3DD(int i) const {assert(0 && "Only used for 3D-Elements!"); return Vector3D(0.);}; //return absolute position of input #i 367 368 virtual Vector2D GetOutputPosD(int i) const; //return absolute position of input #i GetOutputPos3DD(int i)369 virtual Vector3D GetOutputPos3DD(int i) const {assert(0 && "Only used for 3D-Elements!"); return Vector3D(0.);}; //return absolute position of input #i 370 ToP3D(const Vector2D & p)371 virtual Vector3D ToP3D(const Vector2D& p) const 372 { 373 return Vector3D(p.X(),p.Y(),0.); 374 } 375 376 // functions to catch the input - implemented in derived class RespondToKey(int key)377 virtual int RespondToKey(int key) {return false;} 378 379 protected: 380 381 //system inputs 382 TArray<int> inputs; //$EDC$[varaccess,EDCvarname="input_element_numbers",EDCfolder="IOBlock",variable_length_vector,tooltiptext="vector of element(s) or sensor number(s) connected to input, only valid element numbers permitted!"] // sensor number i: if (input_type==1==IOInputTypeElement) --> global number of IOutputElement 383 //if (input_type==2==IOInputTypeSensor) --> global sensor number 384 TArray<int> input_types; //$EDC$[varaccess,EDCvarname="input_element_types",EDCfolder="IOBlock",variable_length_vector,tooltiptext="vector with types of connected inputs; 1=IOElement, 2=Sensor"] // 1==Input-OutputElement, 2==Sensor 385 TArray<int> input_localnum; //$EDC$[varaccess,EDCvarname="input_local_number",EDCfolder="IOBlock",variable_length_vector,tooltiptext="vector with i-th number of output of previous IOelement connected to this element"] // output number of sensor: if (input_type==1) --> output number of IOutputElement 386 387 int n_output; //number of system outputs, use dedicated function [S|G]etNOutputs() 388 int n_state; // number of state variables, use dedicated function GetNInputs() 389 390 //drawing properties: 391 Vector2D ref_pos; //$EDC$[varaccess,EDCvarname="position",EDCfolder="Graphics",tooltiptext="reference drawing position"] 392 Vector3D draw_dim; //$EDC$[varaccess,EDCvarname="draw_size",EDCfolder="Graphics",tooltiptext="draw size"] 393 double rotation; //$EDC$[varaccess,EDCvarname="rotation",EDCfolder="Graphics",tooltiptext="rotation: 1==90�, 2==180�, 3==270�, 4=360�"] 394 Vector3D colbackground; //$EDC$[varaccess,EDCvarname="background_color",EDCfolder="Graphics",tooltiptext="background color; -1=transparent"] 395 Vector3D colforeground; //$EDC$[varaccess,EDCvarname="foreground_color",EDCfolder="Graphics",tooltiptext="foreground color"] 396 397 // further drawing information: 398 TArray<Vector2D> input_nodes; //!EDC$[varaccess,readonly_varaccess,EDCfolder="Graphics",EDCvarname="input_nodes",variable_length_vector,tooltiptext="position of drawing nodes of connection line to corresponding to the input with number \"input_node_number\""] //nodal positions of connections of inputs 399 TArray<int> input_nodes_num; //$EDC$[varaccess,EDCfolder="Graphics",EDCvarname="input_nodes_num",variable_length_vector,tooltiptext="number of input of drawing position \"input_nodes\""] 400 401 // list containing names of outputs 402 MyStrList output_names; 403 404 //// remove entries from EDC 405 //EDC int use_penalty_formulation; //$EDC$[varaccess,remove,EDCvarname="use_penalty_formulation",EDCfolder="Physics"] 406 //EDC double spring_stiffness; //$EDC$[varaccess,remove,EDCvarname="spring_stiffness",EDCfolder="Physics.Penalty"] 407 //EDC int use_local_coordinate_system; //$EDC$[varaccess,remove,EDCvarname="use_local_coordinate_system",EDCfolder="Geometry"] 408 //EDC Vector3D col; //$EDC$[varaccess,remove,EDCvarname="RGB_color",EDCfolder="Graphics"] 409 410 };//$EDC$[endclass,InputOutputElement] 411 412 const double discrete_time_tol = 1e-10; 413 const double discrete_time_tol_inv = 1e10; 414 415 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 416 // DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS 417 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 418 419 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 420 //**begin(ued)** 421 // name: InputOutputElementDiscrete (InputOutputElement) 422 // short description: Superclass for discontinuous input-output elements 423 // available formulations: Discontinuous state-space elements 424 // type: SISO (single input-single output); MIMO (multi input-multi output) 425 // development status: complete, auto-generation functions not complete 426 // long description: Superclass providing basic functions for DISCONTINUOUS input-output elements ==> only subclasses are useful in simulation e.g. for time discrete controller circuits 427 // discrete system with constant sample time 428 // yk = f(u, y, k) 429 // u = [u_(k-n), u_(k-(n-1)), ..., u_(k-n+m) ] 430 // y = [y_(k-n), y_(k-(n-1)), ..., y_(k-(n-1)), y_(k-1)] 431 // m < n 432 // class variables: 433 // -deltaT: discrete time step 434 // -toff: offset to sample time (Tk = k*dT + off) 435 // -n_disc_states: number of time discrete variables 436 //**end(ued)** 437 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 438 439 class InputOutputElementDiscrete: public InputOutputElement//$EDC$[beginclass,classname=InputOutputElementDiscrete,parentclassname=InputOutputElement] 440 { 441 public: 442 InputOutputElementDiscrete(MBS * mbsi)443 InputOutputElementDiscrete(MBS* mbsi):InputOutputElement(mbsi) 444 { 445 InitConstructor(); 446 }; 447 SetSampleTime(double val)448 virtual void SetSampleTime(double val){ deltaT = val; }; GetSampleTime()449 virtual double GetSampleTime(){return deltaT; }; 450 451 //To be overwritten in derived class: GetCopy()452 virtual Element* GetCopy() 453 { 454 Element* ec = new InputOutputElementDiscrete(*this); 455 return ec; 456 } 457 //To be overwritten in derived class: CopyFrom(const Element & e)458 virtual void CopyFrom(const Element& e) 459 { 460 InputOutputElement::CopyFrom(e); 461 const InputOutputElementDiscrete& ce = (const InputOutputElementDiscrete&)e; 462 463 //k = ce.k; 464 deltaT = ce.deltaT; 465 toff = ce.toff; 466 n_disc_states = ce.n_disc_states; 467 } 468 GetNDiscreteStates()469 virtual int GetNDiscreteStates() const {return n_disc_states;} SetNDiscreteStates(int n_disc_statesI)470 virtual void SetNDiscreteStates(int n_disc_statesI) {n_disc_states = n_disc_statesI;} 471 InitConstructor()472 virtual void InitConstructor() 473 { 474 SetNStates(0); 475 SetNOutputs(1); 476 InputOutputElement::InitConstructor(); 477 elementname = GetElementSpec(); 478 toff = 0; 479 deltaT = 0; 480 //k = 0; 481 482 SetNDiscreteStates(0); 483 Vector datainit(DataS()); 484 datainit.SetAll(0.); 485 SetDataInit(datainit); 486 } 487 //########################### 488 // DISCRETE ELEMENT FUNCTIONS DataS()489 virtual int DataS() const {return 1+GetNDiscreteStates();} // size of data vector, which will is automatically restored if solver-step not valid 490 GetK()491 virtual int GetK() const 492 { 493 return (int)XData(1); 494 } SetK(int k)495 virtual void SetK(int k) {XData(1) = (double)k;} 496 XDiscrete(int i)497 virtual const double& XDiscrete(int i) const {return XData(1+i);} XDiscrete(int i)498 virtual double& XDiscrete(int i) {return XData(1+i);} 499 500 virtual double Roundval(double x) const; 501 502 virtual double GetDiscreteTime() const; 503 virtual double GetNextDiscreteTime() const; 504 505 virtual void StartTimeStep(); // update index "K" here and make shorter step size if it is too big 506 virtual void EndTimeStep(); 507 508 virtual int isDiscreteEvent(double discrete_time) const; 509 510 // to be overwritten in children elements UpdateDiscreteElementState()511 virtual void UpdateDiscreteElementState() {assert(0);}; //*** xk+1 = f(xk,uk), define function in child class UpdateDiscreteElementInput(double t)512 virtual void UpdateDiscreteElementInput(double t) {assert(0);}; //*** read actual uk , define function in child class 513 virtual double GetOutput(double t, int i=1) const { assert(0); return 0; } //*** define function in child class 514 //########################### 515 GetElementSpec()516 virtual const char* GetElementSpec() const {return "IODiscrete";} 517 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute 518 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 519 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 520 521 //----------------------------------------------------- 522 //b: auto-generated functions 523 virtual void GetElementDataAuto(ElementDataContainer& edc); 524 virtual int SetElementDataAuto(ElementDataContainer& edc); 525 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 526 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 527 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 528 //e: auto-generated functions 529 //----------------------------------------------------- 530 IsDirectFeedThrough()531 virtual int IsDirectFeedThrough() const { assert(0); return 0; } //*** define function in child class 532 virtual const char* SymbolText() const; 533 virtual void DrawBlockSymbol(); 534 535 protected: 536 double deltaT, toff; 537 int n_disc_states; // number of discrete variables (without k) 538 };//$EDC$[endclass,InputOutputElementDiscrete] 539 540 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 541 //**begin(ued)** 542 // name: ZTransferFunction (InputOutputElementDiscrete) 543 // short description: Discontinuous Transfer function 544 // available formulations: Discontinuous state-space elements 545 // type: SISO (single input-single output) 546 // development status: complete, auto-generation functions not complete 547 // long description: Discontinuous Transfer function in z-Space 548 // Realization of Z-Transfer Function (Z-transform): 549 // theorical background: 550 // y(z) = G(z)*u(z); G(z) = (num(1)+num(2)*z + ... + num(n)*z^(n+1)) / (den(1) + den(2)*z + ... + den(n)*z^(n+1)); 551 // Z-Space 552 // y_k * z^n o---------0 y_(k+n) 553 // yk = f(u, y, k) 554 // u = [u_(k-n), u_(k-(n-1)), ..., u_(k-n+m) ]^t 555 // y = [y_(k-n), y_(k-(n-1)), ..., y_(k-(n-1)), y_(k-1)]^t 556 // class variables: 557 // -num: numerator of transfer function 558 // -den: denominator of transfer function 559 //**end(ued)** 560 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 561 562 class ZTransferFunction: public InputOutputElementDiscrete//$EDC$[beginclass,classname=ZTransferFunction,parentclassname=InputOutputElementDiscrete,addelementtype=TAEinput_output,addelementtypename=IODiscreteTransferFunction, 563 //texdescription="Discontinuous transfer function in z-space. It is a SISO (single input-single output) control element. Inital state is zero.", 564 //figure="IODiscreteTransferFunction,IODiscreteTransferFunction", 565 //texdescriptionEquations=" 566 //$y(z)=\mathbf{G}(z)u(z)$ \\ \\ 567 //$\mathbf{G}(z)=\frac{\mathbf{num}}{\mathbf{den}}$ \\ \\ 568 //user input: \\ 569 //$\mathbf{num}(z) = num_1 + num_2z + num_3z^2 +...+ num_{n+1}z^n$ \\ 570 //$\mathbf{den}(z) = den_1 + den_2z + den_3z^2 +...+ den_{n+1}z^n$ \\ 571 //Theoretical background: Realization of z-transfer function as time discrete state space model \\ 572 //\begin{eqnarray} 573 // \left[\begin{array}{c} 574 // z_{k+1,1} \medskip \\ 575 // . \medskip \\ 576 // . \medskip \\ 577 // . \medskip \\ 578 // z_{k+1,n} 579 // \end{array} \right] 580 // =\left[ 581 // \begin{array}{ccccc} 582 // 0 & . & . & 0 & -den_1 \medskip \\ 583 // 1 & 0 & . & 0 & -den_2 \medskip \\ 584 // . & . & . & . & . \medskip \\ 585 // 0 & 0 & . & 1 & -den_n 586 // \end{array} \right] . 587 // \left[\begin{array}{c} 588 // z_{k,1} \medskip \\ 589 // . \medskip \\ 590 // . \medskip \\ 591 // . \medskip \\ 592 // z_{k,n} 593 // \end{array} \right] + 594 // \left[\begin{array}{c} 595 // num_1 - num_{n+1}den_1 \medskip \\ 596 // . \medskip \\ 597 // . \medskip \\ 598 // num_n - num_{n+1}den_n 599 // \end{array} \right] u_k 600 //\end{eqnarray} 601 //\begin{equation} 602 // y_k = z_{k,n}+num_{n+1}u_z; 603 //\end{equation}", 604 //example="ZTransferFunction.txt"] 605 606 607 608 //\begin{eqnarray} 609 // \mathbf{B} &=&\left[ 610 // \begin{array}{c} 611 // num(1) - num(n+1)*den(1) \medskip \\ 612 // . \medskip \\ 613 // . \medskip \\ 614 // num(n) - num(n+1)*den(n) 615 // \end{array} 616 // \right] \quad 617 // \end{array} 618 619 //$y(z)=\mathbf{G}(z)u(z); \mathbf{G}(z) = \frac{num(1)+num(2)z+...+num(n)z^{n+1}}{den(1)+den(2)+...+den(n)z^{n+1}}$ \\ \\ 620 //z-space \\ 621 //$y_k*z^n$ $\circ---\circ$ $y_{(k+n)}$ \\ 622 //$y_k = f\left(u,y,k\right)$ \\ 623 //$u = \left[u_{(k-n)}, u_{(k-(n-1))},...,u_{(k-n+m)}\right]^T$ \\ 624 //$y = \left[y_{(k-n)}, y_{(k-(n-1))},...,y_{(k-(n-1))},y_{(k-1)}\right]^T$ 625 { 626 public: 627 ZTransferFunction(MBS * mbsi)628 ZTransferFunction(MBS* mbsi):InputOutputElementDiscrete(mbsi) 629 { 630 InitConstructor(); 631 }; 632 SetZTransferFunction(const Vector & numI,const Vector & denI,const Vector & initVector)633 virtual void SetZTransferFunction(const Vector& numI, const Vector& denI, const Vector& initVector) 634 { 635 //------------------------------------------------------------------- 636 // G(z) = p_num(z)/p_den(z) 637 // p_num(z) = num(1) + num(2) * z + num(3) * z^2 + ... + num(n) * z^m 638 // p_den(z) = den(1) + den(2) * z + den(3) * z^2 + ... + den(n) * z^n 639 // m<=n 640 //------------------------------------------------------------------- 641 //check if sizes are consistent! 642 assert(num.Length() == den.Length()); 643 644 //inputs must be added separately 645 num = numI; 646 den = denI; 647 double fact = den(den.Length()); 648 assert(fact != 0); 649 650 num *= (1./fact); 651 den *= (1./fact); 652 653 SetNOutputs(1); 654 SetNStates(0); 655 int dimIODiscrete = DataS(); // dimension of root element 656 SetNDiscreteStates(initVector.Length()); 657 658 Vector init; 659 init.SetLen(0); // new init vector inclusive base element variables 660 init = init.Append(GetDataInit()); 661 init = init.Append(initVector); 662 init = init.Append(0.); // u0=0.0 663 664 SetDataInit(init); 665 666 //UO() << "init=" << init << "\n"; 667 } 668 SetZTransferFunctionWithDescentPolynoms(const Vector & numI,const Vector & denI)669 virtual void SetZTransferFunctionWithDescentPolynoms(const Vector& numI, const Vector& denI) 670 { 671 //------------------------------------------------------------------- 672 // G(z) = p_num(z)/p_den(z) 673 // p_num(z) = num(m) + num(m-1) * z + num(m-2) * z^2 + ... + num(1) * z^m 674 // p_den(z) = den(n) + den(n-1) * z + den(n-2) * z^2 + ... + den(1) * z^n 675 // m<=n 676 //------------------------------------------------------------------- 677 //check if sizes are consistent! 678 assert(numI.Length() == denI.Length()); 679 680 // revert numerator and denominator 681 int len = numI.Length(); 682 Vector tmp1(len), tmp2(len); 683 for(int i = 1; i <= len;i++) 684 { 685 tmp1(len - i + 1) = numI(i); 686 tmp2(len - i + 1) = denI(i); 687 } 688 SetZTransferFunction(tmp1, tmp2); 689 } 690 SetZTransferFunction(const Vector & numI,const Vector & denI)691 virtual void SetZTransferFunction(const Vector& numI, const Vector& denI) 692 { 693 //check if sizes are consistent! 694 assert(numI.Length() == denI.Length()); 695 696 Vector initVector(denI.Length()-1); 697 initVector.SetAll(0); 698 699 SetZTransferFunction(numI, denI, initVector); 700 701 } 702 DataS()703 virtual int DataS() const {return 2+GetNDiscreteStates();} // dim(k)=1, dim(xk)=n, dim(uk) = 1 --> 2+n SetUk(double valI)704 virtual void SetUk(double valI) { XData(DataS()) = valI; } //set input u GetUk()705 virtual double GetUk() const { return XData(DataS()); }//get input u 706 707 // set uk UpdateDiscreteElementInput(double t)708 virtual void UpdateDiscreteElementInput(double t) 709 { 710 SetUk(GetInput(t,1)); 711 }; 712 713 //function is called every discrete event 714 // xk+1 = f(xk,uk) UpdateDiscreteElementState()715 virtual void UpdateDiscreteElementState() 716 { 717 //x(k+1) = A*x(k)+b*u(k); 718 //A=[0 ..... 0 -den1 ] 719 // [1 0 ... 0 -den2 ] 720 // [0 0 ... 1 -den(n)] 721 //bb(i) = num(i) - num(n+1)*den(i) 722 int n = GetNDiscreteStates(); 723 double u = GetUk(); 724 725 xk1_temp.SetLen(n); 726 if(n>0) { xk1_temp(1) = -den(1)*XDiscrete(n) + (num(1)-num(n+1)*den(1))*u;} 727 for(int i = 2; i<=n; i++ ) 728 { 729 xk1_temp(i) = - den(i)*XDiscrete(n) + (num(i)-num(n+1)*den(i))*u ; //A(i,i-1) * x(i-1) + b(i)*u; 730 xk1_temp(i) += XDiscrete(i-1); // ones in A-matrix 731 } 732 733 for(int i = 1; i<=n; i++ ) 734 { 735 XDiscrete(i) = xk1_temp(i); 736 } 737 } 738 739 //To be overwritten in derived class: GetCopy()740 virtual Element* GetCopy() 741 { 742 Element* ec = new ZTransferFunction(*this); 743 return ec; 744 } 745 //To be overwritten in derived class: CopyFrom(const Element & e)746 virtual void CopyFrom(const Element& e) 747 { 748 InputOutputElementDiscrete::CopyFrom(e); 749 const ZTransferFunction& ce = (const ZTransferFunction&)e; 750 751 num = ce.num; 752 den = ce.den; 753 //init_vec = ce.init_vec; // $ MSax 2013-03-01: added 754 } 755 InitConstructor()756 virtual void InitConstructor() 757 { 758 InputOutputElement::InitConstructor(); 759 elementname = GetElementSpec(); 760 761 num = Vector(1); num(1) = 1;// $MSax 2013-02-28: added 762 den = Vector(1); den(1) = 1; 763 //init_vec = Vector(1); 764 } 765 GetElementSpec()766 virtual const char* GetElementSpec() const {return "IODiscreteTransferFunction";} 767 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()768 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 769 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 770 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 771 772 //----------------------------------------------------- 773 //b: auto-generated functions 774 virtual void GetElementDataAuto(ElementDataContainer& edc); 775 virtual int SetElementDataAuto(ElementDataContainer& edc); 776 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 777 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 778 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 779 //e: auto-generated functions 780 //----------------------------------------------------- 781 782 783 virtual double GetOutput(double t, int i=1) const 784 { 785 //to be overwritten in specific class! 786 if (i != 1) 787 { 788 assert(0); 789 return 0; 790 } 791 int n = GetNDiscreteStates(); 792 double u = 0; 793 if (num(n+1) != 0.) 794 { 795 u = GetUk(); 796 } 797 798 double y; 799 if (n==0) 800 { 801 y = num(n+1)*u; 802 } 803 else 804 { 805 y = XDiscrete(n); 806 y += num(n+1)*u; 807 } 808 return y; 809 } 810 IsDirectFeedThrough()811 virtual int IsDirectFeedThrough() const 812 { 813 //assert(num.Length() == den.Length()); 814 return num(num.Length()) != 0; 815 } 816 DrawElement()817 virtual void DrawElement() 818 { 819 InputOutputElement::DrawElement(); 820 }; 821 822 virtual const char* SymbolText() const; 823 virtual void DrawBlockSymbol(); 824 825 protected: 826 Vector num; //!EDC$[varaccess,EDCvarname="num",EDCfolder="IOBlock",tooltiptext="Coefficients of numerator polynomial of z-function, b0+b1*z+b2*z^2+...+bn*z^n"] 827 Vector den; //!EDC$[varaccess,EDCvarname="den",EDCfolder="IOBlock",tooltiptext="Coefficients of denominator polynomial of z-function, a0+a1*z+a2*z^2+...+am*z^m"] //numerator and denominator of transfer function 828 Vector xk1_temp; //temporary variable 829 //Vector init_vec; // $ MSax 2013-03-01: added 830 };//$EDC$[endclass,ZTransferFunction] 831 832 833 //-------------------------------------------------------------------------------------------------------------- 834 // Realization of (pseudo)random value generator 835 836 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 837 //**begin(ued)** 838 // name: Random Source (InputOutputElementDiscrete) 839 // short description: Discontinuous random source 840 // available formulations: Discontinuous state-space elements; internal random generator and Linear Feedback Shift Register (LFSR) 841 // type: SISO (single input-single output) 842 // development status: complete, auto-generation functions not complete 843 // long description: Discontinuous random source using alternatively an internal C++ based pseudo random generator or a Linear Feedback Shift Register 844 // class variables: 845 // -amplitude, offset, seed: maximal amplitude, additional offset of random signal, seed � [0.,1.]... initialization of random generator 846 // -TRandomType method: method of random value generation; method = Trand --> use built-in command "rand"; method = TLFSR --> Linear Feedback Shift Register 847 // -rand_max: maximal value for random value generator RAND_MAX, alternative: 2^N-1 848 // -isConstAmplitude: set to 1 if output value should be only +amplitude or -amplitude 849 //**end(ued)** 850 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 851 852 typedef enum {Trand = 0, TLFSR = 1} TRandomType; // Trand ... use built-in command "rand", TLFSR ... Linear Feedback Shift Register 853 854 class RandomSource: public InputOutputElementDiscrete//$EDC$[beginclass,classname=RandomSource,parentclassname=InputOutputElementDiscrete,addelementtype=TAEinput_output,addelementtypename=IORandomSource, 855 //texdescription="Discontinuous random source using alternatively an internal C++ based pseudo random generator or a linear feedback shift register. It has no input and one output.", 856 //figure="IORandomSource,IORandomSource",example="addRandomSource.txt", 857 //modus="{method $0$}{IOBlock.method must be set to $0$. The built-in random generator is used.}", 858 //modus="{method $1$}{IOBlock.method must be set to $1$. Generate a pseudo random binary signal by using Linear Feedback Shift Register.}"] 859 860 { 861 public: 862 863 // constructor RandomSource(MBS * mbsi)864 RandomSource(MBS* mbsi):InputOutputElementDiscrete(mbsi) 865 { 866 InitConstructor(); 867 }; 868 869 // set function with number of bits of random signal 870 virtual void SetRandomSource(double amplitudeI, double offsetI = 0., TRandomType methodI = (TRandomType)Trand, double seedI = 0, double init_val = 0, int Nbits = 15); 871 // InitRandomSource is used in SetRandomSource 872 virtual void InitRandomSource(double amplitudeI, double offsetI = 0., TRandomType methodI = (TRandomType)Trand, double seedI = 0, double init_val = 0, int rand_maxi = RAND_MAX); 873 874 // random integer number � [0, RAND_MAX]; method TLFSR returns numbers unequal zero 875 virtual int GetRandomInt(); 876 SetRandMax(int val)877 void SetRandMax(int val){rand_max = val;} // set max. value 878 GetRandMax()879 int GetRandMax(){return rand_max; } // get max. value 880 881 void SetConstantAmplitude(int val = 1){isConstAmplitude = val;} 882 // size of data vector DataS()883 virtual int DataS() const {return 1+GetNDiscreteStates();} // dim(k)=1, dim(xk)=1 --> 2 884 885 // set uk UpdateDiscreteElementInput(double t)886 virtual void UpdateDiscreteElementInput(double t) { }; // no input 887 888 //function is called every discrete event 889 // xk+1 = f(xk,uk) 890 virtual void UpdateDiscreteElementState(); 891 892 //To be overwritten in derived class: GetCopy()893 virtual Element* GetCopy() 894 { 895 Element* ec = new RandomSource(*this); 896 return ec; 897 } 898 //To be overwritten in derived class: CopyFrom(const Element & e)899 virtual void CopyFrom(const Element& e) 900 { 901 InputOutputElementDiscrete::CopyFrom(e); 902 const RandomSource& ce = (const RandomSource&)e; 903 904 amplitude = ce.amplitude; 905 offset = ce.offset; 906 seed = 0; 907 method = ce.method; 908 rand_max = ce.rand_max; 909 isConstAmplitude = ce.isConstAmplitude; 910 init_val = ce.init_val; 911 } 912 InitConstructor()913 virtual void InitConstructor() 914 { 915 InputOutputElement::InitConstructor(); 916 elementname = GetElementSpec(); 917 amplitude = 0.; 918 offset = 0.; 919 seed = 0; 920 method = Trand; 921 rand_max = 32767; //RAND_MAX<=>0x7fff 922 isConstAmplitude = 0; 923 init_val = 0; 924 } 925 GetElementSpec()926 virtual const char* GetElementSpec() const {return "IORandomSource";} 927 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()928 virtual int GetExpectedNumberOfInputs(){return 0;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 929 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 930 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 931 932 //----------------------------------------------------- 933 //b: auto-generated functions 934 virtual void GetElementDataAuto(ElementDataContainer& edc); 935 virtual int SetElementDataAuto(ElementDataContainer& edc); 936 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 937 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 938 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 939 //e: auto-generated functions 940 //----------------------------------------------------- 941 942 943 virtual double GetOutput(double t, int i=1) const 944 { 945 //to be overwritten in specific class! 946 if(isConstAmplitude) 947 { 948 return amplitude*Sgn(XDiscrete(1)); 949 } 950 return XDiscrete(1); //yk = xk 951 } 952 IsDirectFeedThrough()953 virtual int IsDirectFeedThrough() const 954 { 955 return 0; 956 } 957 DrawElement()958 virtual void DrawElement() 959 { 960 InputOutputElement::DrawElement(); 961 }; 962 963 virtual const char* SymbolText() const; 964 virtual void DrawBlockSymbol(); 965 966 protected: 967 968 double amplitude; //!EDC$[varaccess,EDCvarname="amplitude",EDCfolder="IOBlock",tooltiptext="maximal amplitude of random signal"] 969 double offset; //!EDC$[varaccess,EDCvarname="offset",EDCfolder="IOBlock",tooltiptext="additional offset of random signal"] 970 double seed; //!EDC$[varaccess,EDCvarname="seed",EDCfolder="IOBlock",tooltiptext="seed � [0.,1.]... initialization of random generator"] // maximal amplitude, additional offset of random signal, seed � [0.,1.]... initialization of random generator 971 TRandomType method; //!EDC$[varaccess,EDCvarname="method",EDCfolder="IOBlock",tooltiptext="method of random value generation: Trand = 0 ... use built-in command "rand", TLFSR = 1... Linear Feedback Shift Register"] // method of random value generation 972 int rand_max; //!EDC$[varaccess,EDCvarname="rand_max",EDCfolder="IOBlock",tooltiptext="maximum value that can be returned by the rand function."] // standard: RAND_MAX, alternative: 2^N-1 973 int isConstAmplitude; // set to 1 if output value should be only +amplitude or -amplitude 974 double init_val; //$ MSax 2013-02-28: added 975 //old: int random_value; // value between [0, RAND_MAX], RAND_MAX <=> 0x7fff <=> binary: 0111 1111 1111 1111 ==> stored in XDiscrete(2) 976 977 //EDC TArray<int> inputs; //$EDC$[varaccess,remove,EDCvarname="input_element_numbers",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 978 //EDC TArray<int> input_types; //$EDC$[varaccess,remove,EDCvarname="input_element_types",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 979 //EDC TArray<int> input_localnum; //$EDC$[varaccess,remove,EDCvarname="input_local_number",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 980 981 };//$EDC$[endclass,RandomSource] 982 983 //-------------------------------------------------------------------------------------------------------------- 984 // DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS DISCRETE SYSTEMS 985 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 986 987 988 989 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 990 //**begin(ued)** 991 // name: LinearTransformation (InputOutputElementDiscrete) 992 // short description: Continuous linear transformation 993 // available formulations: Continuous state-space elements 994 // type: SISO (single input-single output), MIMO (multi input-multi output) 995 // development status: complete, auto-generation functions not complete 996 // long description: Continuous linear transformation y = A*u+b 997 //y = A*u+b; //a..output vector, A...transformation matrix, u..input vector, b=offset vector 998 //--> linear transformation y = A*u 999 //--> simple gain y_1 = A_11*u_1 1000 //--> constant y_1 = b_1 1001 // class variables: 1002 // -A_coeff: transformation matrix A 1003 // -b_coeff: offset vector 1004 //**end(ued)** 1005 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1006 1007 class LinearTransformation: public InputOutputElement//$EDC$[beginclass,classname=LinearTransformation,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOLinearTransformation, 1008 //texdescription="Continuous linear transformation. The transfer function type is SISO (single input-single output) or MIMO (multi input-multi output).", 1009 //figure="IOLinearTransformation,IOLinearTransformation", 1010 //modus="{linear transformation $y=A\,u$}{Set $\mathbf{b}$ to zero.}", 1011 //modus="{gain $y_1=A_{1,1}u_1$}{Set A as scalar value and b is zero.}", 1012 //modus="{constant $y_1=b_1$}{Set A to zero and b to the constant value.}", 1013 //texdescriptionEquations=" 1014 //\begin{equation} 1015 // \mathbf{y} = \mathbf{A}\mathbf{u}+\mathbf{b}; \\ 1016 //\end{equation} 1017 //Matrix $\mathbf{A}$ and vector $\mathbf{b}$ are user defined.", 1018 //example="LinearTransformation.txt"] 1019 { 1020 public: 1021 LinearTransformation(MBS * mbsi)1022 LinearTransformation(MBS* mbsi):InputOutputElement(mbsi) 1023 { 1024 InitConstructor(); 1025 }; 1026 1027 virtual void SetLinearTransformation(const Matrix& A, const Vector& b); 1028 1029 virtual void SetConstant(double val); 1030 1031 virtual void SetGain(double val); 1032 1033 virtual void SetAdder(const Vector& signs); 1034 1035 //To be overwritten in derived class: GetCopy()1036 virtual Element* GetCopy() 1037 { 1038 Element* ec = new LinearTransformation(*this); 1039 return ec; 1040 } 1041 //To be overwritten in derived class: 1042 virtual void CopyFrom(const Element& e); 1043 1044 virtual void InitConstructor(); 1045 GetElementSpec()1046 virtual const char* GetElementSpec() const {return "IOLinearTransformation";} 1047 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1048 virtual int GetExpectedNumberOfInputs(){return -1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1049 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1050 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1051 1052 //----------------------------------------------------- 1053 //b: auto-generated functions 1054 virtual void GetElementDataAuto(ElementDataContainer& edc); 1055 virtual int SetElementDataAuto(ElementDataContainer& edc); 1056 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1057 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1058 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1059 //e: auto-generated functions 1060 //----------------------------------------------------- 1061 1062 1063 virtual double GetOutput(double t, int i=1) const; 1064 DrawElement()1065 virtual void DrawElement() 1066 { 1067 InputOutputElement::DrawElement(); 1068 }; 1069 1070 virtual const char* SymbolText() const; 1071 virtual void DrawBlockSymbol(); IsDirectFeedThrough()1072 virtual int IsDirectFeedThrough() const 1073 { 1074 if (A_coeff.Getrows() == 0 || A_coeff.Getcols() == 0) 1075 { 1076 return 0; 1077 } 1078 if (A_coeff.Norm2() == 0) 1079 { 1080 return 0; 1081 } 1082 return 1; 1083 } 1084 1085 protected: 1086 Matrix A_coeff; //$EDC$[varaccess,EDCvarname="A_matrix",EDCfolder="IOBlock",variable_length_vector,tooltiptext="transformation matrix A: y=A.u+b"] 1087 Vector b_coeff; //$EDC$[varaccess,EDCvarname="b_vector",EDCfolder="IOBlock",variable_length_vector,tooltiptext="offset vector b: y=A.u+b"] 1088 };//$EDC$[endclass,LinearTransformation] 1089 1090 1091 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1092 1093 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1094 //**begin(ued)** 1095 // name: Quantizer (InputOutputElement) 1096 // short description: Quantizer 1097 // available formulations: Continuous state-space elements 1098 // type: SISO(single input-single output) 1099 // development status: complete, auto-generation functions not complete 1100 // long description: Continuous linear transformation y = A*u+b 1101 //y = A*u+b; //a..output vector, A...transformation matrix, u..input vector, b=offset vector 1102 //--> linear transformation y = A*u 1103 //--> simple gain y_1 = A_11*u_1 1104 //--> constant y_1 = b_1 1105 // class variables: 1106 // -A_coeff: transformation matrix A 1107 // -b_coeff: offset vector 1108 //**end(ued)** 1109 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1110 class Quantizer: public InputOutputElement//$EDC$[beginclass,classname=Quantizer,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOQuantizer, 1111 //texdescription="A quantizer block passes its input signal through a stair-step function so that many neighboring points on the input axis are mapped to one point on the output axis. The effect is to quantize a smooth signal into a stair-step output. It is a SISO (single input-single output) control element.", 1112 //figure="IOQuantizer,IOQuantizer", 1113 //texdescriptionEquations=" 1114 //\begin{equation} 1115 //y(u) = 1116 //\begin{cases} 1117 // r\,floor\left(\frac{u}{r}+0.5r\right) , & \text{if } r != 0 \\ 1118 // u, & \text{if } r = 0 1119 //\end{cases} 1120 //\end{equation} 1121 //The user defined rounding value is $r$.", 1122 //example="Quantizer.txt"] 1123 { 1124 public: 1125 Quantizer(MBS * mbsi)1126 Quantizer(MBS* mbsi):InputOutputElement(mbsi) 1127 { 1128 InitConstructor(); 1129 }; 1130 SetQuantizer(double roundI)1131 virtual void SetQuantizer(double roundI) 1132 { 1133 roundval = roundI; 1134 } 1135 1136 //To be overwritten in derived class: GetCopy()1137 virtual Element* GetCopy() 1138 { 1139 Element* ec = new Quantizer(*this); 1140 return ec; 1141 } 1142 //To be overwritten in derived class: CopyFrom(const Element & e)1143 virtual void CopyFrom(const Element& e) 1144 { 1145 InputOutputElement::CopyFrom(e); 1146 const Quantizer& ce = (const Quantizer&)e; 1147 1148 roundval = ce.roundval; 1149 } 1150 InitConstructor()1151 virtual void InitConstructor() 1152 { 1153 SetNOutputs(1); 1154 SetNStates(0); 1155 InputOutputElement::InitConstructor(); 1156 elementname = GetElementSpec(); 1157 roundval = 0.1; //$ MSax 2013-02-28: added 1158 } 1159 GetElementSpec()1160 virtual const char* GetElementSpec() const {return "IOQuantizer";} GetExpectedNumberOfInputs()1161 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1162 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1163 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1164 1165 //----------------------------------------------------- 1166 //b: auto-generated functions 1167 virtual void GetElementDataAuto(ElementDataContainer& edc); 1168 virtual int SetElementDataAuto(ElementDataContainer& edc); 1169 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1170 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1171 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1172 //e: auto-generated functions 1173 //----------------------------------------------------- 1174 1175 1176 virtual double GetOutput(double t, int i=1) const 1177 { 1178 if (GetNInputs() == 1) 1179 { 1180 if (roundval != 0) 1181 return roundval * floor(GetInput(t, 1)/roundval + 0.5*roundval); 1182 else 1183 return GetInput(t, 1); 1184 } 1185 else 1186 { 1187 assert(0 && "Quantizer has no input!!!"); 1188 } 1189 assert(0 && "return value added for compiler"); 1190 return 0; 1191 } 1192 DrawElement()1193 virtual void DrawElement() 1194 { 1195 InputOutputElement::DrawElement(); 1196 }; 1197 1198 virtual const char* SymbolText() const; 1199 virtual void DrawBlockSymbol(); IsDirectFeedThrough()1200 virtual int IsDirectFeedThrough() const 1201 { 1202 return 1; 1203 } 1204 1205 protected: 1206 double roundval; 1207 };//$EDC$[endclass,Quantizer] 1208 1209 1210 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1211 //**begin(ued)** 1212 // name: STransferFunction (InputOutputElement) 1213 // short description: STransferFunction 1214 // available formulations: Continuous state-space elements, linear transfer function 1215 // type: SISO(single input-single output), linear transfer function 1216 // development status: complete, auto-generation functions not complete 1217 // long description: Continuous linear transformation y = A*u+b 1218 // Realization of S-Transfer Function (Laplace Transform): 1219 // G(s) = (num(1)+num(2)*s + ... + num(n)*s^(n+1)) / (den(1) + den(2)*s + ... + den(n)*s^(n+1)); 1220 // class variables: 1221 // -num, den: numerator and denominator of transfer function in ascent order of Laplace variable "s"; must have same lenght (fill numerator with zero's if it has lower order than denominator) 1222 //**end(ued)** 1223 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1224 1225 class STransferFunction: public InputOutputElement//$EDC$[beginclass,classname=STransferFunction,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOContinuousTransferFunction, 1226 //texdescription="The STransferFunction is a linear transfer function for continuous state-space elements. It is a SISO (single input-single output) type.", 1227 //figure="IOContinuousTransferFunction,IOContinuousTransferFunction", 1228 //texdescriptionEquations=" 1229 //$y(s)=\mathbf{G}(s)u(s)$ \\ \\ 1230 //$\mathbf{G}(s)=\frac{\mathbf{num(s)}}{\mathbf{den(s)}}$ \\ \\ 1231 //user input: \\ 1232 //$\mathbf{num}(s) = num_1 + num_2s + num_3s^2 +...+ num_{n+1}s^n$ \\ 1233 //$\mathbf{den}(s) = den_1 + den_2s + den_3s^2 +...+ den_{n+1}s^n$", 1234 //example="STransferFunction.txt"] 1235 { 1236 public: 1237 STransferFunction(MBS * mbsi)1238 STransferFunction(MBS* mbsi):InputOutputElement(mbsi) 1239 { 1240 InitConstructor(); 1241 }; 1242 SetSTransferFunctionWithDescentPolynoms(const Vector & numI,const Vector & denI)1243 virtual void SetSTransferFunctionWithDescentPolynoms(const Vector& numI, const Vector& denI) 1244 { 1245 //------------------------------------------------------------------- 1246 // G(s) = p_num(s)/p_den(s) 1247 // p_num(s) = num(m) + num(m-1) * s + num(m-2) * s^2 + ... + num(1) * s^m 1248 // p_den(s) = den(n) + den(n-1) * s + den(n-2) * s^2 + ... + den(1) * s^n 1249 // m<=n 1250 //------------------------------------------------------------------- 1251 //check if sizes are consistent! 1252 if(numI.Length() != denI.Length()) 1253 { 1254 mbs->UO(UO_LVL_err).InstantMessageText("Error#1 while creating S-Transfer function! Numerator and denominator vectors must have same size.\n"); 1255 return; 1256 } 1257 1258 // revert numerator and denominator 1259 int len = numI.Length(); 1260 Vector tmp1(len), tmp2(len); 1261 for(int i = 1; i <= len;i++) 1262 { 1263 tmp1(len - i + 1) = numI(i); 1264 tmp2(len - i + 1) = denI(i); 1265 } 1266 SetSTransferFunction(tmp1, tmp2); 1267 1268 } SetSTransferFunctionWithDescentPolynoms(const Vector & numI,const Vector & denI,const Vector & initVector)1269 virtual void SetSTransferFunctionWithDescentPolynoms(const Vector& numI, const Vector& denI, const Vector& initVector) 1270 { 1271 //------------------------------------------------------------------- 1272 // G(s) = p_num(s)/p_den(s) 1273 // p_num(s) = num(m) + num(m-1) * s + num(m-2) * s^2 + ... + num(1) * s^m 1274 // p_den(s) = den(n) + den(n-1) * s + den(n-2) * s^2 + ... + den(1) * s^n 1275 // m<=n 1276 //------------------------------------------------------------------- 1277 //check if sizes are consistent! 1278 if(numI.Length() != denI.Length()) 1279 { 1280 mbs->UO(UO_LVL_err).InstantMessageText("Error#2 during creating S-Transfer function! Numerator and denominator vectors must have same size.\n"); 1281 SetSTransferFunction(Vector(1.0), Vector(1.0), Vector(0.)); 1282 return; 1283 } 1284 1285 // revert numerator and denominator 1286 int len = numI.Length(); 1287 Vector tmp1(len), tmp2(len); 1288 for(int i = 1; i <= len;i++) 1289 { 1290 tmp1(len - i + 1) = numI(i); 1291 tmp2(len - i + 1) = denI(i); 1292 } 1293 SetSTransferFunction(tmp1, tmp2, initVector); 1294 } SetSTransferFunction(const Vector & numI,const Vector & denI,const Vector & initVector)1295 virtual void SetSTransferFunction(const Vector& numI, const Vector& denI, const Vector& initVector) 1296 { 1297 //check if sizes are consistent! 1298 if(numI.Length() != denI.Length()) 1299 { 1300 mbs->UO(UO_LVL_err).InstantMessageText("Error#3 during creating S-Transfer function! Numerator and denominator vectors must have same size.\n"); 1301 SetSTransferFunction(Vector(1.0), Vector(1.0), Vector(0.)); 1302 return; 1303 } 1304 1305 //inputs must be added separately 1306 num = numI; 1307 den = denI; 1308 1309 double fact = den(den.Length()); 1310 if(fact == 0) 1311 { 1312 mbs->UO(UO_LVL_err).InstantMessageText("Error#4 while creating S-Transfer function! Denominator coefficient corresponding to highest exponent of Laplace variable is zero.\n"); 1313 fact = 1.; 1314 } 1315 1316 num *= (1./fact); 1317 den *= (1./fact); 1318 1319 SetNStates(den.Length()-1); 1320 if (GetNStates() == 0) UO(UO_LVL_err).InstantMessageText("Error#5 in S-Transfer Function: is fully algebraic!\n"); 1321 SetInitialValues(initVector); 1322 1323 //check if sizes are consistent! 1324 if(GetNStates() != initVector.Length()){UO(UO_LVL_err).InstantMessageText("Error5 in S-Transfer Function: Problems during inizialisation!\n");} 1325 } 1326 SetSTransferFunction(const Vector & numI,const Vector & denI)1327 virtual void SetSTransferFunction(const Vector& numI, const Vector& denI) 1328 { 1329 Vector initVector(numI.Length()-1); 1330 initVector.SetAll(0); 1331 1332 SetSTransferFunction(numI, denI, initVector); 1333 } 1334 1335 //To be overwritten in derived class: GetCopy()1336 virtual Element* GetCopy() 1337 { 1338 Element* ec = new STransferFunction(*this); 1339 return ec; 1340 } 1341 //To be overwritten in derived class: CopyFrom(const Element & e)1342 virtual void CopyFrom(const Element& e) 1343 { 1344 InputOutputElement::CopyFrom(e); 1345 const STransferFunction& ce = (const STransferFunction&)e; 1346 1347 num = ce.num; 1348 den = ce.den; 1349 } 1350 InitConstructor()1351 virtual void InitConstructor() 1352 { 1353 InputOutputElement::InitConstructor(); 1354 SetNOutputs(1); 1355 elementname = GetElementSpec(); 1356 SetSTransferFunction(Vector(1.,0.,0.,0.), Vector(0.,0.,0.,1.0)); // set to valid value 1357 } 1358 GetElementSpec()1359 virtual const char* GetElementSpec() const {return "IOContinuousTransferFunction";} 1360 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1361 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1362 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1363 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1364 1365 //----------------------------------------------------- 1366 //b: auto-generated functions 1367 virtual void GetElementDataAuto(ElementDataContainer& edc); 1368 virtual int SetElementDataAuto(ElementDataContainer& edc); 1369 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1370 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1371 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1372 //e: auto-generated functions 1373 //----------------------------------------------------- 1374 1375 1376 virtual void EvalF(Vector& f, double t); 1377 1378 1379 virtual double GetOutput(double t, int i=1) const; 1380 IsDirectFeedThrough()1381 virtual int IsDirectFeedThrough() const 1382 { 1383 int n = ES(); 1384 if (num.Length() != 0) 1385 { 1386 if (num(n+1) != 0) return 1; 1387 } 1388 return 0; 1389 } 1390 DrawElement()1391 virtual void DrawElement() 1392 { 1393 InputOutputElement::DrawElement(); 1394 }; 1395 1396 virtual const char* SymbolText() const; 1397 virtual void DrawBlockSymbol(); 1398 1399 protected: 1400 Vector num; //$EDC$[varaccess,variable_length_vector,EDCvarname="numerator",EDCfolder="IOBlock",tooltiptext="ascending numerator coefficients n of transfer-function. TF = num/den with num = n(1)*1+n(2)*s+n(3)*s*s+... Will be normalized automatically!"] 1401 Vector den; //$EDC$[varaccess,variable_length_vector,EDCvarname="denominator",EDCfolder="IOBlock",tooltiptext="ascending denominator coeffs d of transfer-function. TF = num/den with den = d(1)*1+d(2)*s+d(3)*s*s+... Will be normalized automatically!"] 1402 };//$EDC$[endclass,STransferFunction] 1403 1404 1405 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1406 //**begin(ued)** 1407 // name: LinearODE (InputOutputElement) 1408 // short description: Linear ODE 1409 // available formulations: Continuous state-space elements, linear ODE 1410 // type: SISO(single input-single output), linear differential equations 1411 // development status: complete, auto-generation functions not complete 1412 // long description: Linear ordinary differential equation 1413 // Realization of Linear ODE 1414 // x_dot = A*x + B*u 1415 // y = C*x + D*u 1416 // class variables: 1417 // -A_coeff, B_coeff, C_coeff, D_coeff: matrices of linear differential equation system 1418 //**end(ued)** 1419 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1420 1421 1422 class LinearODE: public InputOutputElement//$EDC$[beginclass,classname=LinearODE,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOLinearODE, 1423 //texdescription="The LinearODE Element represents a linear ordinary differential equation of SISO (single input-single output) or MIMO (multi input-multi output) type.", 1424 //figure="IOLinearODE,IOLinearODE", 1425 //texdescriptionEquations=" 1426 //$\mathbf{\dot{x}}=\mathbf{A}\,\mathbf{x}+\mathbf{B}\,\mathbf{u}$ \\ 1427 //$\mathbf{y}=\mathbf{C}\,\mathbf{x}+\mathbf{D}\,\mathbf{u}$ \\ \\ 1428 //Matrices $\mathbf{A}$, $\mathbf{B}$, $\mathbf{C}$ and $\mathbf{D}$ are user defined.", 1429 //example="LinearODE.txt"] 1430 { 1431 public: 1432 LinearODE(MBS * mbsi)1433 LinearODE(MBS* mbsi):InputOutputElement(mbsi) 1434 { 1435 InitConstructor(); 1436 }; 1437 SetLinearODE(const Matrix & A,const Matrix & B,const Matrix & C,const Matrix & D,const Vector & initVector)1438 virtual void SetLinearODE(const Matrix& A, const Matrix& B, const Matrix& C, const Matrix& D, const Vector& initVector) 1439 { 1440 //set linear ODE 1441 int ni = B.Getcols(); //number of inputs 1442 int ns = A.Getcols(); //number of states 1443 int no = C.Getrows(); //number of outputs 1444 1445 assert(A.Getrows() == ns); 1446 assert(B.Getrows() == ns); 1447 assert(C.Getcols() == ns); 1448 assert(D.Getrows() == no); 1449 assert(D.Getcols() == ni); 1450 1451 assert(initVector.Length() == ns); 1452 1453 A_coeff = A; 1454 B_coeff = B; 1455 C_coeff = C; 1456 D_coeff = D; 1457 1458 SetNOutputs(no); 1459 SetNStates(ns); 1460 SetInitialValues(initVector); 1461 1462 /*UO() << "Linear ODE:\n"; 1463 UO() << "A=" << A_coeff << "\n"; 1464 UO() << "B=" << B_coeff << "\n"; 1465 UO() << "C=" << C_coeff << "\n"; 1466 UO() << "D=" << D_coeff << "\n"; 1467 UO() << "x_init=" << x_init << "\n";*/ 1468 } 1469 SetFirstOrderODE(double a,double b,double x_0)1470 virtual void SetFirstOrderODE(double a, double b, double x_0) //x_dot = a*x + b*u, y=x 1471 { 1472 Matrix A(a); 1473 Matrix B(b); 1474 Matrix C(1.); 1475 Matrix D(0.); 1476 1477 Vector initVector(x_0); 1478 1479 SetLinearODE(A, B, C, D, initVector); 1480 } 1481 SetSecondOrderODE(double inertia_fact,double damp_fact,double stiff_fact,double input_fact,double x_0,double v_0)1482 virtual void SetSecondOrderODE(double inertia_fact, double damp_fact, double stiff_fact, double input_fact, double x_0, double v_0) //m*x_ddot + d*x_dot + k*x = b*u, y(1) = x, y(2) = x_dot (=v) 1483 { 1484 // this defines a linear oscillator, with one input (input gain b), two outputs (x, v) 1485 //[x] [ 0 1 ] [x] [ 0 ] 1486 //[ ]=[ ]*[ ]+[ ] * [u] 1487 //[v] [-m^-1*k -m^-1*d] [v] [m^-1] 1488 // 1489 //y = C * x + D * u, C=diag(1, 1), D=zero matrix 1490 1491 assert(inertia_fact != 0); 1492 double minv = 1./inertia_fact; 1493 1494 Matrix A(0., 1., -minv*stiff_fact, -minv*damp_fact); 1495 1496 Matrix B(2,1); 1497 B(1,1) = 0.; 1498 B(2,1) = minv*input_fact; 1499 1500 Matrix C(2,2); 1501 C.SetDiagMatrix(1.); 1502 1503 Matrix D(2,1); 1504 D(1,1) = 0.; D(2,1) = 0.; 1505 1506 Vector initVector(x_0, v_0); 1507 1508 SetLinearODE(A, B, C, D, initVector); 1509 } 1510 1511 1512 //To be overwritten in derived class: GetCopy()1513 virtual Element* GetCopy() 1514 { 1515 Element* ec = new LinearODE(*this); 1516 return ec; 1517 } 1518 //To be overwritten in derived class: CopyFrom(const Element & e)1519 virtual void CopyFrom(const Element& e) 1520 { 1521 InputOutputElement::CopyFrom(e); 1522 const LinearODE& ce = (const LinearODE&)e; 1523 1524 A_coeff = ce.A_coeff; 1525 B_coeff = ce.B_coeff; 1526 C_coeff = ce.C_coeff; 1527 D_coeff = ce.D_coeff; 1528 } 1529 InitConstructor()1530 virtual void InitConstructor() 1531 { 1532 InputOutputElement::InitConstructor(); 1533 elementname = GetElementSpec(); 1534 1535 A_coeff = Matrix(1,1); //$ MSax 2013-02-28 added 1536 B_coeff = Matrix(1,1); 1537 C_coeff = Matrix(1,1); 1538 D_coeff = Matrix(1,1); 1539 } 1540 GetElementSpec()1541 virtual const char* GetElementSpec() const {return "IOLinearODE";} 1542 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1543 virtual int GetExpectedNumberOfInputs(){return -1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1544 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1545 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1546 1547 //----------------------------------------------------- 1548 //b: auto-generated functions 1549 virtual void GetElementDataAuto(ElementDataContainer& edc); 1550 virtual int SetElementDataAuto(ElementDataContainer& edc); 1551 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1552 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1553 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1554 //e: auto-generated functions 1555 //----------------------------------------------------- 1556 1557 EvalF(Vector & f,double t)1558 virtual void EvalF(Vector& f, double t) 1559 { 1560 for (int i=1; i <= A_coeff.Getrows(); i++) 1561 { 1562 double val = 0; 1563 for (int j=1; j <= A_coeff.Getcols(); j++) 1564 { 1565 val += A_coeff(i,j)*XG(j); 1566 } 1567 for (int j=1; j <= B_coeff.Getcols(); j++) 1568 { 1569 val += B_coeff(i,j)*GetInput(t, j); 1570 } 1571 f(i) += val; 1572 } 1573 }; 1574 1575 virtual double GetOutput(double t, int i=1) const 1576 { 1577 //to be overwritten in specific class! 1578 if (i <= 0 || i > C_coeff.Getrows()) 1579 { 1580 assert(0); 1581 return 0; 1582 } 1583 //return 0; 1584 1585 //y(i) = Sum_j {C(i,j)*x(j) + D(i,j)*u(j)} 1586 double val = 0; 1587 for (int j=1; j <= C_coeff.Getcols(); j++) 1588 { 1589 val += C_coeff(i,j)*XG(j); 1590 } 1591 for (int j=1; j <= D_coeff.Getcols(); j++) 1592 { 1593 if (D_coeff(i,j) != 0.) 1594 val += D_coeff(i,j)*GetInput(t, j); 1595 } 1596 return val; 1597 } IsDirectFeedThrough()1598 virtual int IsDirectFeedThrough() const 1599 { 1600 if (D_coeff.Getrows() == 0 || D_coeff.Getcols() == 0) 1601 { 1602 return 0; 1603 } 1604 if (D_coeff.Norm2() == 0) 1605 { 1606 return 0; 1607 } 1608 return 1; 1609 } 1610 DrawElement()1611 virtual void DrawElement() 1612 { 1613 InputOutputElement::DrawElement(); 1614 }; 1615 1616 virtual const char* SymbolText() const; 1617 virtual void DrawBlockSymbol(); 1618 1619 protected: 1620 Matrix A_coeff, B_coeff, C_coeff, D_coeff; 1621 };//$EDC$[endclass,LinearODE] 1622 1623 1624 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1625 //**begin(ued)** 1626 // name: IOMathFunction (InputOutputElement) 1627 // short description: Continuous MathFunction and look-up tables 1628 // available formulations: mathematical functions and look-up tables 1629 // type: continuous element, SISO 1630 // development status: auto-generation functions not complete 1631 // long description: Continuous MathFunction and look-up tables (x-variable: Input, y-variable: Output) 1632 // output = Mathfunction(input); //1 input, output is computed via MathFunction 1633 // class variables: 1634 // - mathfunc: MathFunction 1635 // - elementspec: specification of element; variable used for name 1636 // - pieceWiseSwitchOnlyInPostNewton: flag for activation / deactivate switching of index only in post newton 1637 // - pieceWiseIndex: index for inter-(extrapolation) of values 1638 // - pieceWiseIteration: number of iterations (if max. number of iterations is reached, the postnewton error should be zero and this number is reduced) 1639 //**end(ued)** 1640 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1641 1642 class IOMathFunction: public InputOutputElement //$EDC$[beginclass,classname=IOMathFunction,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOMathFunction, 1643 //texdescription="A IOMathFunction contains a mathematical expression or a lookup table with different modes for piecewise interpolation. The output is result of the evalutation of the MathFunction as a function of input. It is a SISO (single input-single output) control element.", 1644 //figure="IOMathFunction,IOMathFunction",example="MathFunction.txt", 1645 //modus="{parsed function}{IOBlock.MathFunction.piecewise\_mode must be set to $-1$. In IOBlock.MathFunction.parsed\_function one specifies a string representing parsed function, e.g. '$A*sin(u)$' with funtion parameter $u$ defined in IOBlock.MathFunction.parsed\_function\_parameter.}", 1646 //modus="{piecewise mode - constant}{IOBlock.MathFunction.piecewise\_mode must be set to $0$. The vectors IOBlock.MathFunction.piecewise\_points and IOBlock.MathFunction.piecewise\_values are used. The output value is piecewise constant with jumps at the supporting points.}", 1647 //modus="{piecewise mode - linear}{IOBlock.MathFunction.piecewise\_mode must be set to $1$. The vectors IOBlock.MathFunction.piecewise\_points and IOBlock.MathFunction.piecewise\_values are used. The output value is piecewise linear between the supporting points.}", 1648 //modus="{piecewise mode - quadratic}{IOBlock.MathFunction.piecewise\_mode must be set to $2$ and in addition to the other piecwise modes the vector IOBlock.MathFunction.piecewise\_diff\_values is needed. The output is a quadratic interpolation between the supporting points.}"] 1649 { 1650 public: 1651 IOMathFunction(MBS * mbsi)1652 IOMathFunction(MBS* mbsi):InputOutputElement(mbsi) 1653 { 1654 InitConstructor(); 1655 }; 1656 1657 virtual void SetIOMathFunction(const MathFunction& mathfuncI); 1658 1659 virtual void SetSwitchOnlyInPostNewton(int val = 1){pieceWiseSwitchOnlyInPostNewton = val;} //$ RL 2012-7-25: 1... change interval after newton computation and evaluate new jacobi matrix in case of new interval, activate this flag only if the IOMathFunction is no function of time (TItime) 1660 1661 //To be overwritten in derived class: 1662 virtual Element* GetCopy(); 1663 1664 //To be overwritten in derived class: 1665 virtual void CopyFrom(const Element& e); 1666 1667 virtual void InitConstructor(); 1668 GetElementSpec()1669 virtual const char* GetElementSpec() const {return "IOMathFunction";} 1670 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1671 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1672 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1673 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1674 1675 //----------------------------------------------------- 1676 //b: auto-generated functions 1677 virtual void GetElementDataAuto(ElementDataContainer& edc); 1678 virtual int SetElementDataAuto(ElementDataContainer& edc); 1679 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1680 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1681 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1682 //e: auto-generated functions 1683 //----------------------------------------------------- 1684 1685 1686 virtual double GetOutput(double t, int i=1) const; 1687 DataS()1688 virtual int DataS() const {return 0;} //Data size for non-state variables (length of XData-vector) 1689 1690 virtual double PostNewtonStep(double t); 1691 1692 virtual void IOMathFunction::PostprocessingStep(); 1693 IsDirectFeedThrough()1694 virtual int IsDirectFeedThrough() const 1695 { 1696 return 1; 1697 } 1698 DrawElement()1699 virtual void DrawElement() 1700 { 1701 InputOutputElement::DrawElement(); 1702 }; 1703 1704 virtual const char* SymbolText() const; 1705 virtual void DrawBlockSymbol(); 1706 1707 protected: 1708 MathFunction mathfunc; 1709 mystr elementspec; //EDC$[varaccess,readonly,EDCfolder="",EDCvarname="elementspec",tooltiptext="element specification"] 1710 int pieceWiseSwitchOnlyInPostNewton; // flag for activation / deactivate switching of index only in post newton 1711 int pieceWiseIndex; // index for inter-(extrapolation) of values 1712 int pieceWiseIteration; // number of iterations (if max. number of iterations is reached, the postnewton error should be zero and this number is reduced) 1713 }; //$EDC$[endclass,IOMathFunction] 1714 1715 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1716 //**begin(ued)** 1717 // name: IOSaturate (InputOutputElement) 1718 // short description: Saturation 1719 // available formulations: Continuous state-space elements 1720 // type: SISO (single input-single output) 1721 // development status: complete, auto-generation functions not complete 1722 // long description: Continuous Saturation element 1723 // class variables: 1724 // -lowerLimit: lower limit; values below are saturated 1725 // -upperLimit: upper limit; values above are saturated 1726 //**end(ued)** 1727 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1728 1729 class IOSaturate: public InputOutputElement//$EDC$[beginclass,classname=IOSaturate,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOSaturate, 1730 //texdescription="Continuous saturation element for upper and lower limits. It is a SISO (single input-single output) control element.", 1731 //figure="IOSaturate,IOSaturate", 1732 //texdescriptionEquations=" 1733 //\begin{equation} 1734 //y(u) = 1735 //\begin{cases} 1736 // ul, & \text{if } u>ul \\ 1737 // u, & \text{if } ll\leq u \leq ul \\ 1738 // ll, & \text{if } u<ll 1739 //\end{cases} 1740 //\end{equation} 1741 //In the defined equation $ul$ is the upper limit and $ll$ is the lower limit.", 1742 //example="Saturate.txt"] 1743 { 1744 public: 1745 IOSaturate(MBS * mbsi)1746 IOSaturate(MBS* mbsi):InputOutputElement(mbsi) 1747 { 1748 InitConstructor(); 1749 }; 1750 1751 // lower/-upperLimit... lower/upper limits of saturation; max_val.. SetIOSaturate(double lowerLimiti,double upperLimiti)1752 virtual void SetIOSaturate(double lowerLimiti, double upperLimiti) 1753 { 1754 lowerLimit = lowerLimiti; 1755 upperLimit = upperLimiti; 1756 1757 SetNOutputs(1); 1758 SetNStates(0); 1759 } 1760 1761 //To be overwritten in derived class: GetCopy()1762 virtual Element* GetCopy() 1763 { 1764 Element* ec = new IOSaturate(*this); 1765 return ec; 1766 } 1767 //To be overwritten in derived class: CopyFrom(const Element & e)1768 virtual void CopyFrom(const Element& e) 1769 { 1770 InputOutputElement::CopyFrom(e); 1771 const IOSaturate& ce = (const IOSaturate&)e; 1772 lowerLimit = ce.lowerLimit; 1773 upperLimit = ce.upperLimit; 1774 1775 } 1776 InitConstructor()1777 virtual void InitConstructor() 1778 { 1779 InputOutputElement::InitConstructor(); 1780 elementname = GetElementSpec(); 1781 lowerLimit = 0; //$ MSax 2013-02-28 added 1782 upperLimit = 0.1; //$ MSax 2013-02-28 added 1783 } 1784 1785 virtual double GetOutput(double t, int i=1) const 1786 { 1787 double u = GetInput(t, i); 1788 if(u < lowerLimit)return lowerLimit; 1789 if(u > upperLimit)return upperLimit; 1790 return u; 1791 } 1792 1793 //----------------------------------------------------- 1794 //b: auto-generated functions 1795 virtual void GetElementDataAuto(ElementDataContainer& edc); 1796 virtual int SetElementDataAuto(ElementDataContainer& edc); 1797 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1798 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1799 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1800 //e: auto-generated functions 1801 //----------------------------------------------------- 1802 GetElementSpec()1803 virtual const char* GetElementSpec() const {return "IOSaturate";} 1804 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1805 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1806 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1807 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1808 1809 virtual const char* IOSaturate::SymbolText() const; 1810 virtual void DrawBlockSymbol(); 1811 1812 protected: 1813 double lowerLimit; 1814 double upperLimit; 1815 };//$EDC$[endclass,IOSaturate] 1816 //$ RL 2011-11:] IOSaturate 1817 1818 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1819 //**begin(ued)** 1820 // name: IODeadZone (InputOutputElement) 1821 // short description: Deadzone 1822 // available formulations: Continuous state-space elements 1823 // type: SISO (single input-single output) 1824 // development status: complete, auto-generation functions not complete 1825 // long description: Continuous Deadzone element 1826 // The outputs between upper and lower limit is the value zero. 1827 // This leads to an offset of the input signal by the corresponding lower or upper limit. 1828 // class variables: 1829 // -start_deadzone: lower limit of deadzone 1830 // -end_deadzone: upper limit of deadzone 1831 //**end(ued)** 1832 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1833 1834 class IODeadZone: public InputOutputElement//$EDC$[beginclass,classname=IODeadZone,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IODeadZone, 1835 //texdescription="Continuous dead-zone element. The outputs between upper and lower limit is zero. This leads to an offset of the input signal by the corresponding lower or upper limit. It is a SISO (single input-single output) control element.", 1836 //figure="IODeadZone,IODeadZone", 1837 //texdescriptionEquations=" 1838 //\begin{equation} 1839 //y(u) = 1840 //\begin{cases} 1841 // u-sd, & \text{if } u<sd \\ 1842 // 0, & \text{if } u \geq sd \text{ and } u \leq ed \\ 1843 // u-ed, & \text{if } u>ed 1844 //\end{cases} 1845 //\end{equation} 1846 //In the defined equation $sd$ is the start dead-zone value, $ed$ is the end dead-zone value.", 1847 //example="DeadZone.txt"] 1848 { 1849 1850 public: 1851 IODeadZone(MBS * mbsi)1852 IODeadZone(MBS* mbsi):InputOutputElement(mbsi) 1853 { 1854 InitConstructor(); 1855 SetNStates(0); 1856 SetNOutputs(1); 1857 }; 1858 SetIODeadZone(double start_deadzoneI,double end_deadzoneI)1859 void SetIODeadZone(double start_deadzoneI, double end_deadzoneI) 1860 { 1861 assert(start_deadzoneI < end_deadzoneI); 1862 start_deadzone = start_deadzoneI; 1863 end_deadzone = end_deadzoneI; 1864 } 1865 //To be overwritten in derived class: GetCopy()1866 virtual Element* GetCopy() 1867 { 1868 Element* ec = new IODeadZone(*this); 1869 return ec; 1870 } 1871 //To be overwritten in derived class: CopyFrom(const Element & e)1872 virtual void CopyFrom(const Element& e) 1873 { 1874 InputOutputElement::CopyFrom(e); 1875 const IODeadZone& ce = (const IODeadZone&)e; 1876 start_deadzone = ce.start_deadzone; 1877 end_deadzone = ce.end_deadzone; 1878 } 1879 InitConstructor()1880 virtual void InitConstructor() 1881 { 1882 InputOutputElement::InitConstructor(); 1883 elementname = GetElementSpec(); 1884 start_deadzone = 0.; 1885 end_deadzone = 0.; 1886 } 1887 GetElementSpec()1888 virtual const char* GetElementSpec() const {return "IODeadZone";} 1889 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()1890 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 1891 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 1892 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 1893 1894 //----------------------------------------------------- 1895 //b: auto-generated functions 1896 virtual void GetElementDataAuto(ElementDataContainer& edc); 1897 virtual int SetElementDataAuto(ElementDataContainer& edc); 1898 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 1899 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 1900 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 1901 //e: auto-generated functions 1902 //----------------------------------------------------- 1903 1904 1905 // 1906 virtual double GetOutput(double t, int i=1) const 1907 { 1908 double u = GetInput(t, i); 1909 if(u < start_deadzone) 1910 { 1911 return u - start_deadzone; 1912 } 1913 else if(u > end_deadzone) 1914 { 1915 return u - end_deadzone; 1916 } 1917 else 1918 { 1919 return 0.; //u >= start_deadzone && u =< end_deadzone 1920 } 1921 } 1922 IsDirectFeedThrough()1923 virtual int IsDirectFeedThrough() const 1924 { 1925 return 1; 1926 } 1927 1928 1929 virtual const char* SymbolText() const; 1930 virtual void DrawBlockSymbol(); 1931 1932 protected: 1933 double start_deadzone; // lower limit of deadzone 1934 double end_deadzone; // upper limit of deadzone 1935 };//$EDC$[endclass,IODeadZone] 1936 //$ RL 2011-01:] IODeadzone added 1937 1938 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1939 //**begin(ued)** 1940 // name: IOProduct (InputOutputElement) 1941 // short description: Product 1942 // available formulations: Continuous state-space elements 1943 // type: SISO (single input-single output), MIMO (multi input-multi output) 1944 // development status: complete, auto-generation functions not complete 1945 // long description: Continuous product (or division) of one or more inputs 1946 // y=u1^exp1*u2^exp2*...*un^expn+offset, y...output, u...input 1947 // exp = -1 ... multiply inverse of input 1948 // exp = 1 ... multiply input 1949 // class variables: 1950 // -exp: exponent of inputs, see formula in long description 1951 // -offset: offset, see formula in long description 1952 //**end(ued)** 1953 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1954 1955 class IOProduct: public InputOutputElement//$EDC$[beginclass,classname=IOProduct,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOProduct, 1956 //texdescription="Continuous product (or division) of one or more inputs. A dedicated exponent for every input and a offset can be applied.", 1957 //figure="IOProduct,IOProduct", 1958 //texdescriptionEquations=" 1959 //\begin{equation} 1960 //y(\mathbf{u}) = u_1^{exp_1}u_2^{exp_2}...u_n^{exp_n}+offset 1961 //\end{equation} 1962 //All exponents are stored in a vector. For a simple multiplication with a input the dedicated exponent is set to 1, for a division the exponent is set to -1. The offset is a scalar value.", 1963 //example="Product.txt"] 1964 { 1965 public: IOProduct(MBS * mbsi)1966 IOProduct(MBS* mbsi):InputOutputElement(mbsi) 1967 { 1968 InitConstructor(); 1969 SetNStates(0); 1970 SetNOutputs(1); 1971 }; 1972 // exp (x) ... 1 = multiplicator, -1 ... division 1973 void SetIOProduct(Vector& expi, double offseti = 0.) 1974 { 1975 exp = expi; 1976 if(exp.Length() <= 0) 1977 { 1978 exp = Vector(1.,1.); 1979 mbs->UO(UO_LVL_err).InstantMessageText("Error in SetIOProduct: exponent vector is empty."); 1980 } 1981 offset = offseti; 1982 } 1983 1984 //To be overwritten in derived class: GetCopy()1985 virtual Element* GetCopy() 1986 { 1987 Element* ec = new IOProduct(*this); 1988 return ec; 1989 } 1990 //To be overwritten in derived class: CopyFrom(const Element & e)1991 virtual void CopyFrom(const Element& e) 1992 { 1993 InputOutputElement::CopyFrom(e); 1994 const IOProduct& ce = (const IOProduct&)e; 1995 exp = ce.exp; 1996 offset = ce.offset; 1997 } 1998 InitConstructor()1999 virtual void InitConstructor() 2000 { 2001 InputOutputElement::InitConstructor(); 2002 elementname = GetElementSpec(); 2003 2004 exp = Vector(1); //$ MSax 2013-02-28 2005 offset = 0; //$ MSax 2013-02-28 2006 } 2007 GetElementSpec()2008 virtual const char* GetElementSpec() const {return "IOProduct";} 2009 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2010 virtual int GetExpectedNumberOfInputs(){return -1; /*MSax 2013-02-28 changed from 1 to -1*/}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2011 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2012 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2013 2014 //----------------------------------------------------- 2015 //b: auto-generated functions 2016 virtual void GetElementDataAuto(ElementDataContainer& edc); 2017 virtual int SetElementDataAuto(ElementDataContainer& edc); 2018 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2019 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2020 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2021 //e: auto-generated functions 2022 //----------------------------------------------------- 2023 2024 virtual double GetOutput(double t, int i=1) const; 2025 IsDirectFeedThrough()2026 virtual int IsDirectFeedThrough() const 2027 { 2028 return 1; 2029 } 2030 2031 virtual const char* SymbolText() const; 2032 virtual void DrawBlockSymbol(); 2033 2034 protected: 2035 Vector exp; // exponents of inputs 2036 double offset; // output offset 2037 };//$EDC$[endclass,IOProduct] 2038 2039 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2040 //**begin(ued)** 2041 // name: IOTime (InputOutputElement) 2042 // short description: Time source 2043 // available formulations: Continuous state-space elements 2044 // type: SISO (single input-single output) 2045 // development status: complete, auto-generation functions not complete 2046 // long description: Continuous time source 2047 // This element simply outputs the time. 2048 // class variables: 2049 //**end(ued)** 2050 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2051 2052 class IOTime: public InputOutputElement //$EDC$[beginclass,classname=IOTime,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOTime, 2053 //texdescription="Continuous time source. This element simply outputs the time.", 2054 //figure="IOTime,IOTime",example="addTime.txt"] 2055 { 2056 public: 2057 IOTime(MBS * mbsi)2058 IOTime(MBS* mbsi):InputOutputElement(mbsi) 2059 { 2060 InitConstructor(); 2061 }; 2062 //To be overwritten in derived class: GetCopy()2063 virtual Element* GetCopy() 2064 { 2065 Element* ec = new IOTime(*this); 2066 return ec; 2067 } 2068 //To be overwritten in derived class: CopyFrom(const Element & e)2069 virtual void CopyFrom(const Element& e) 2070 { 2071 InputOutputElement::CopyFrom(e); 2072 const IOTime& ce = (const IOTime&)e; 2073 } 2074 InitConstructor()2075 virtual void InitConstructor() 2076 { 2077 InputOutputElement::InitConstructor(); 2078 elementname = GetElementSpec(); 2079 SetNStates(0); 2080 SetNOutputs(1); 2081 } 2082 GetElementSpec()2083 virtual const char* GetElementSpec() const {return "IOTime";} 2084 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2085 virtual int GetExpectedNumberOfInputs(){return 0;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2086 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2087 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2088 2089 //----------------------------------------------------- 2090 //b: auto-generated functions 2091 virtual void GetElementDataAuto(ElementDataContainer& edc); 2092 virtual int SetElementDataAuto(ElementDataContainer& edc); 2093 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2094 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2095 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2096 //e: auto-generated functions 2097 //----------------------------------------------------- 2098 2099 2100 virtual double GetOutput(double t, int i=1) const 2101 { 2102 return t; 2103 } IsDirectFeedThrough()2104 virtual int IsDirectFeedThrough() const 2105 { 2106 return 0; 2107 } 2108 2109 2110 virtual const char* SymbolText() const; 2111 virtual void DrawBlockSymbol(); 2112 protected: 2113 2114 //EDC TArray<int> inputs; //$EDC$[varaccess,remove,EDCvarname="input_element_numbers",EDCfolder="IOBlock"] // $ MSax 2013-08-28: removed 2115 //EDC TArray<int> input_types; //$EDC$[varaccess,remove,EDCvarname="input_element_types",EDCfolder="IOBlock"] // $ MSax 2013-08-28: removed 2116 //EDC TArray<int> input_localnum; //$EDC$[varaccess,remove,EDCvarname="input_local_number",EDCfolder="IOBlock"] // $ MSax 2013-08-28: removed 2117 2118 }; //$EDC$[endclass,IOTime] 2119 2120 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2121 //**begin(ued)** 2122 // name: IOPulseGenerator (InputOutputElement) 2123 // short description: Pulse Generator 2124 // available formulations: Continuous state-space elements 2125 // type: SISO (single input-single output) 2126 // development status: complete, auto-generation functions not complete 2127 // long description: Continuous Pulse Generator 2128 // This element outputs repeating sequence or rectangular pulses after a certain delay 2129 // parameters: amplitude pulse width (s) 2130 // ________ ________ __ .... 2131 // | | | | | 2132 // t=0__________| |___| |___| 2133 // phase delay (s) 2134 // period (s) 2135 // |<--------->| 2136 // class variables: 2137 // -amplitude: amplitude of rectangle pulse 2138 // -toffs: offset time for pulse sequence 2139 // -period: period of rectangle 2140 // -pulseWidth: pulse width - output is set to amplitude in this time span 2141 // -useExternalTime: set to nonzero value if input should be used as time source; otherwise use simulation time 2142 //**end(ued)** 2143 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2144 2145 class IOPulseGenerator: public InputOutputElement//$EDC$[beginclass,classname=IOPulseGenerator,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOPulseGenerator, 2146 //texdescription="Continuous pulse generator. This element outputs repeating sequence or rectangular pulses after a certain delay. It has no input and one output.", 2147 //figure="IOPulseGenerator,IOPulseGenerator", 2148 //texdescriptionEquations=" 2149 //\begin{equation} 2150 //\Delta t = t-t_{offset} 2151 //\end{equation} 2152 //\begin{equation} 2153 //t_{rest} = \Delta t \text{ mod } p 2154 //\end{equation} 2155 //\begin{equation} 2156 //y(t) = 2157 //\begin{cases} 2158 // a, & \text{if } \Delta t \geq 0 \text{ and } t_{rest} < pw \\ 2159 // 0, & \text{else } 2160 //\end{cases} 2161 //\end{equation} 2162 //User defined variables are pulse amplitude $a$, time offset $t_{offset}$, signal period $p$ and pulse width $pw$.",example="addPulseGenerator.txt" 2163 //] 2164 2165 { 2166 public: 2167 IOPulseGenerator(MBS * mbsi)2168 IOPulseGenerator(MBS* mbsi):InputOutputElement(mbsi) 2169 { 2170 InitConstructor(); 2171 SetNStates(0); 2172 SetNOutputs(1); 2173 }; 2174 2175 void SetIOPulseGenerator(double amplitudeI, double toffsI, double periodI, double pulseWidthI, int useExternalTimeI = 0) 2176 { 2177 amplitude = amplitudeI; 2178 toffs = toffsI; 2179 period = periodI; 2180 pulseWidth = pulseWidthI; 2181 useExternalTime = useExternalTimeI; 2182 assert(period > 0. && pulseWidth >= 0.); 2183 } 2184 2185 //To be overwritten in derived class: GetCopy()2186 virtual Element* GetCopy() 2187 { 2188 Element* ec = new IOPulseGenerator(*this); 2189 return ec; 2190 } 2191 //To be overwritten in derived class: CopyFrom(const Element & e)2192 virtual void CopyFrom(const Element& e) 2193 { 2194 InputOutputElement::CopyFrom(e); 2195 const IOPulseGenerator& ce = (const IOPulseGenerator&)e; 2196 amplitude = ce.amplitude; 2197 toffs = ce.toffs; 2198 period = ce.period; 2199 pulseWidth = ce.pulseWidth; 2200 useExternalTime = ce.useExternalTime; 2201 } 2202 InitConstructor()2203 virtual void InitConstructor() 2204 { 2205 InputOutputElement::InitConstructor(); 2206 elementname = GetElementSpec(); 2207 2208 amplitude = 1; // $ MSax 2013-02-28: added 2209 toffs = 0; 2210 period = 1; 2211 pulseWidth = 0.5; 2212 useExternalTime = 0; 2213 } 2214 GetElementSpec()2215 virtual const char* GetElementSpec() const {return "IOPulseGenerator";} 2216 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2217 virtual int GetExpectedNumberOfInputs(){return 0;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2218 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2219 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2220 2221 //----------------------------------------------------- 2222 //b: auto-generated functions 2223 virtual void GetElementDataAuto(ElementDataContainer& edc); 2224 virtual int SetElementDataAuto(ElementDataContainer& edc); 2225 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2226 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2227 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2228 //e: auto-generated functions 2229 //----------------------------------------------------- 2230 2231 virtual double GetOutput(double t, int i=1) const 2232 { 2233 double time; 2234 if(useExternalTime)time = GetInput(t, i); 2235 else time = t; 2236 2237 double tt = time-toffs; // shifted time (without offset) 2238 double trest = fmod(tt,period); 2239 2240 if(tt >= 0. && trest < pulseWidth) 2241 { 2242 return amplitude; 2243 } 2244 else 2245 { 2246 return 0.; 2247 } 2248 } IsDirectFeedThrough()2249 virtual int IsDirectFeedThrough() const 2250 { 2251 return 1; 2252 } 2253 2254 virtual const char* SymbolText() const; 2255 virtual void DrawBlockSymbol(); 2256 2257 protected: 2258 double amplitude; // amplitude of rectangle pulse 2259 double toffs; // offset time for pulse sequence 2260 double period; // period of rectangle 2261 double pulseWidth; // pulse width - output is set to amplitude in this time span 2262 int useExternalTime; // set to nonzero value if input should be used as time source; otherwise use simulation time 2263 2264 //EDC TArray<int> inputs; //$EDC$[varaccess,remove,EDCvarname="input_element_numbers",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 2265 //EDC TArray<int> input_types; //$EDC$[varaccess,remove,EDCvarname="input_element_types",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 2266 //EDC TArray<int> input_localnum; //$EDC$[varaccess,remove,EDCvarname="input_local_number",EDCfolder="IOBlock"] // $ MSax 2013-04-23: removed 2267 2268 };//$EDC$[endclass,IOPulseGenerator] 2269 2270 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2271 // INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE 2272 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2273 2274 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2275 //**begin(ued)** 2276 // name: ControllerInterfaceData (Element) 2277 // short description: Superclass for specific controller circuits 2278 // available formulations: Discontinuous state-space elements 2279 // type: SISO (single input-single output), MIMO (multi input-multi output) 2280 // development status: complete, auto-generation functions not complete 2281 // long description: Superclass for discontinuous controller interface 2282 // Specific time discrete input-output elements can be implemented as subclass of ControllerInterfaceData (e.g. from external code) 2283 // The function x(k+1)=f(xk,uk) is called every discrete event from the class "ControllerInterface". 2284 // Example: This Interface contains pointers to global update and initialize functions, sample time and number of element outputs. 2285 // 2286 // The following functions have to be implemented in the subclass: 2287 // virtual const double& Uk(int num=1) const; 2288 // virtual double& Uk(int num=1); 2289 // virtual void SetUk(double valI, int num=1); 2290 // virtual double GetOutput(double t, int i=1) const; 2291 // 2292 // class variables: 2293 // -void (*Reg_Init)(): pointer on initialize function 2294 // -void (*Reg_Update)(): pointer on update function 2295 // -deltaT: Reg_Update is called every deltaT seconds 2296 // -nOut: number of outputs 2297 // -nInp: number of inputs 2298 //**end(ued)** 2299 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2300 2301 class ControllerInterfaceData: public Element//!EDC$[beginclass,classname=ControllerInterfaceData,parentclassname=Element] 2302 { 2303 public: ControllerInterfaceData(MBS * mbsi)2304 ControllerInterfaceData(MBS* mbsi) : Element(mbsi) 2305 { 2306 //problem with debug modus if following two lines are no comment 2307 //Reg_Init = NULL; 2308 //Reg_Update = NULL; 2309 deltaT = 0.0; 2310 nOut = 0; 2311 nInp = 0; 2312 } 2313 ControllerInterfaceData(const ControllerInterfaceData & e)2314 ControllerInterfaceData(const ControllerInterfaceData& e) : Element(e.mbs) {CopyFrom(e);} 2315 2316 // pointer on global functions can be added with &function, e.g. Controller from simulink SetControllerInterfaceData(void (* Reg_InitI)(),void (* Reg_UpdateI)(),double deltaTI,int nOutI,int nInpI)2317 virtual void SetControllerInterfaceData(void (*Reg_InitI)(), void (*Reg_UpdateI)(), double deltaTI, int nOutI, int nInpI) 2318 { 2319 Reg_Init = Reg_InitI; 2320 Reg_Update = Reg_UpdateI; 2321 deltaT = deltaTI; 2322 nOut = nOutI; 2323 nInp = nInpI; 2324 } 2325 2326 //To be overwritten in derived class: GetCopy()2327 virtual Element* GetCopy() 2328 { 2329 Element* ec = new ControllerInterfaceData(*this); 2330 return ec; 2331 } 2332 CopyFrom(const Element & e)2333 virtual void CopyFrom(const Element& e) 2334 { 2335 Element::CopyFrom(e); 2336 const ControllerInterfaceData& ce = (const ControllerInterfaceData&)e; 2337 Reg_Init = ce.Reg_Init; 2338 Reg_Update = ce.Reg_Update; 2339 deltaT = ce.deltaT; 2340 nOut = ce.nOut; 2341 nInp = ce.nInp; 2342 } 2343 Controller_Init()2344 virtual void Controller_Init() {(*Reg_Init)();} Controller_Update()2345 virtual void Controller_Update(){(*Reg_Update)();} 2346 GetNOutputs()2347 virtual int GetNOutputs() const{return nOut;} GetNInputs()2348 virtual int GetNInputs() const{return nInp;} 2349 SetSampleTime(double val)2350 virtual void SetSampleTime(double val){ deltaT = val; }; GetSampleTime()2351 virtual double GetSampleTime() const{return deltaT;}; 2352 2353 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2354 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2355 2356 //----------------------------------------------------- 2357 //b: auto-generated functions 2358 //virtual void GetElementDataAuto(ElementDataContainer& edc); 2359 //virtual int SetElementDataAuto(ElementDataContainer& edc); 2360 //virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2361 //virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2362 //virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2363 //e: auto-generated functions 2364 //----------------------------------------------------- 2365 2366 //----------------------------------------------------- 2367 //b: EXAMPLE INTERFACE DATA (IN CHILD CLASS) 2368 ////implement input and outputs in child class; example: 2369 ////datah is child of class ControllerInterfaceData with specific data storage of inputs and outputs 2370 ////function is called every discrete event 2371 //// xk+1 = f(xk,uk) 2372 // virtual const double& Uk(int num=1) const; 2373 // virtual double& Uk(int num=1); 2374 // virtual void SetUk(double valI, int num=1); 2375 // virtual double GetOutput(double t, int i=1) const; 2376 //e: EXAMPLE INTERFACE DATA (IN CHILD CLASS) 2377 //----------------------------------------------------- 2378 2379 private: 2380 void (*Reg_Init)(); // pointer on initialize function 2381 void (*Reg_Update)(); // pointer on update function 2382 double deltaT; // Reg_Update is called every deltaT seconds 2383 int nOut; // number of outputs 2384 int nInp; // number of inputs 2385 };//!EDC$[endclass,ControllerInterfaceData] 2386 2387 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2388 //**begin(ued)** 2389 // name: ControllerInterface (InputOutputElementDiscrete) 2390 // short description: Interface for time discrete input output-elements 2391 // available formulations: Discontinuous state-space elements 2392 // type: SISO (single input-single output), MIMO (multi input-multi output) 2393 // development status: complete, auto-generation functions not complete 2394 // long description: Interface for time discrete input output-elements (e.g. controller circuits) using special ControllerInterfaceData 2395 // This interface element executes specific time discrete input-output elements in form of a subclass of ControllerInterfaceData (e.g. from external code). 2396 // The function x(k+1)=f(xk,uk) is called every discrete event from this interface. 2397 // class variables: 2398 // -ControllerInterfaceData data: data of special subclass derived from "ControllerInterfaceData" with user defined input-outputs. 2399 //**end(ued)** 2400 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2401 2402 class ControllerInterface: public InputOutputElementDiscrete//!EDC$[beginclass,classname=ControllerInterface,parentclassname=InputOutputElementDiscrete] 2403 { 2404 public: //$ RL 2010-04 2405 ControllerInterface(ControllerInterfaceData & dataI)2406 ControllerInterface(ControllerInterfaceData& dataI): InputOutputElementDiscrete(dataI.GetMBS()), data(dataI.GetMBS()) 2407 { 2408 InitConstructor(); 2409 data.CopyFrom(dataI); 2410 }; 2411 ControllerInterface(MBS * mbsi)2412 ControllerInterface(MBS* mbsi) : InputOutputElementDiscrete(mbsi), data(mbsi) { }; 2413 ControllerInterface(const ControllerInterface & e)2414 ControllerInterface(const ControllerInterface& e) : InputOutputElementDiscrete(e.mbs), data(e.mbs) {CopyFrom(e);} 2415 SetControllerInterface(const ControllerInterfaceData & dataI)2416 virtual void SetControllerInterface(const ControllerInterfaceData& dataI) //old: const Vector& initVector 2417 { 2418 InitConstructor(); 2419 data.CopyFrom(dataI); // copy data container 2420 2421 //SetNOutputs(data.nOut); 2422 SetNStates(0); 2423 int dimIODiscrete = DataS(); // dimension of root element 2424 SetNDiscreteStates(0); //old: SetNDiscreteStates(initVector.Length()) 2425 InputOutputElementDiscrete::SetSampleTime(data.GetSampleTime()); //sample time already stored 2426 SetNOutputs(data.GetNOutputs()); 2427 2428 Vector init; 2429 init.SetLen(0); // new init vector inclusive base element variables 2430 init = init.Append(GetDataInit()); 2431 2432 Vector initVector; 2433 initVector.SetLen(0); 2434 init = init.Append(initVector); // initial vector xk(t=0) (could be inserted here if necessary) 2435 2436 Vector initU; 2437 initU.SetLen(data.GetNInputs()); 2438 init = init.Append(initU); // u0=0.0 2439 2440 SetDataInit(init); 2441 data.Controller_Init(); 2442 } 2443 SetSampleTime(double val)2444 virtual void SetSampleTime(double val){ deltaT = val; }; GetSampleTime()2445 virtual double GetSampleTime(){return data.GetSampleTime(); }; 2446 DataS()2447 virtual int DataS() const {return 1+GetNDiscreteStates()+ data.GetNInputs();} // dim(k)=1, dim(xk)=n, dim(uk) = 1 --> 2+n 2448 2449 virtual void SetUk(double valI, int num = 1) { XData(1+GetNDiscreteStates()+num) = valI; } //set num'th input u 2450 virtual double GetUk(int num = 1) const { return XData(1+GetNDiscreteStates()+num); } //get num'th input u 2451 2452 // set uk-vector UpdateDiscreteElementInput(double t)2453 virtual void UpdateDiscreteElementInput(double t) 2454 { 2455 for(int i=1; i<=data.GetNInputs(); i++) 2456 { 2457 SetUk(GetInput(t, i), i); 2458 } 2459 }; 2460 2461 //function is called every discrete event 2462 // xk+1 = f(xk,uk) UpdateDiscreteElementState()2463 virtual void UpdateDiscreteElementState() { GetMBS()->UO().InstantMessageText("ControllerInterface_UpdateDiscreteElementState_Error: Define function in child class.\n");assert(0);};// data.Controller_Update(); } 2464 2465 //To be overwritten in derived class: GetCopy()2466 virtual Element* GetCopy() 2467 { 2468 Element* ec = new ControllerInterface(*this); 2469 return ec; 2470 } 2471 //To be overwritten in derived class: CopyFrom(const Element & e)2472 virtual void CopyFrom(const Element& e) 2473 { 2474 InputOutputElementDiscrete::CopyFrom(e); 2475 const ControllerInterface& ce = (const ControllerInterface&)e; 2476 data.CopyFrom(ce.data); 2477 } 2478 InitConstructor()2479 virtual void InitConstructor() 2480 { 2481 InputOutputElement::InitConstructor(); 2482 elementname = GetElementSpec(); 2483 } 2484 GetElementSpec()2485 virtual const char* GetElementSpec() const {return "ControllerInterface";} 2486 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2487 virtual int GetExpectedNumberOfInputs(){return -1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2488 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2489 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2490 2491 //----------------------------------------------------- 2492 //b: auto-generated functions 2493 //virtual void GetElementDataAuto(ElementDataContainer& edc); 2494 //virtual int SetElementDataAuto(ElementDataContainer& edc); 2495 //virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2496 //virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2497 //virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2498 //e: auto-generated functions 2499 //----------------------------------------------------- 2500 2501 virtual double GetOutput(double t, int i=1) const { GetMBS()->UO().InstantMessageText("ControllerInterface_GetOutput_Error: Define function in child class.\n");assert(0); return 0; } 2502 IsDirectFeedThrough()2503 virtual int IsDirectFeedThrough() const { return 0; } 2504 DrawElement()2505 virtual void DrawElement() { InputOutputElement::DrawElement(); }; 2506 2507 virtual const char* SymbolText() const; 2508 virtual void DrawBlockSymbol(); 2509 2510 // --------------- EXAMPLE INTERFACE (IN CHILD CLASS)--------------------- 2511 ////implement input and outputs in child class; example: 2512 ////datah is child of class ControllerInterfaceData with specific data storage of inputs and outputs 2513 ////function is called every discrete event 2514 //// xk+1 = f(xk,uk) 2515 //virtual void UpdateDiscreteElementState() { datah.Controller_Update(); } 2516 2517 //virtual double GetOutput(double t, int i=1) const 2518 //{ 2519 // return datah.GetOutput(double t, i); 2520 //} 2521 // 2522 //virtual void SetUk(double valI, int num = 1) //set num'th input u 2523 //{ 2524 // ControllerInterface::SetUk(valI, num); // HOTINT storage 2525 // datah.SetUk(valI, num); // controller specific storage 2526 //} 2527 // ------------------------------------------------------------------------ 2528 2529 protected: 2530 ControllerInterfaceData data; // contains data for interface 2531 };//!EDC$[endclass,ControllerInterface] 2532 2533 // INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE INTERFACE 2534 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2535 2536 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2537 // IOTimeWindow 2538 class IOTimeWindow: public InputOutputElement//$EDC$[beginclass,classname=IOTimeWindow,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOTimeWindow, 2539 //texdescription="This element helps to capture a special time window. It has two inputs and one output.",figure="IOTimeWindow,IOTimeWindow", 2540 //modus="{$t_{end} > t_{start}$}{Output is determined with inequation (a).}", 2541 //modus="{$t_{end} \leq t_{start}$}{Output is determined with inequation (b).}", 2542 //texdescriptionEquations=" 2543 //\begin{equation} 2544 //\left(a\right) \qquad y(\mathbf{u}) = 2545 //\begin{cases} 2546 // u_2, & \text{if } t_{start} \leq u_1 \leq t_{end} \\ 2547 // 0, & \text{else } 2548 //\end{cases} 2549 //\end{equation} 2550 //\begin{equation} 2551 //\left(b\right) \qquad y(\mathbf{u}) = 2552 //\begin{cases} 2553 // u_2, & \text{if } t_{start} \leq u_1 \\ 2554 // 0, & \text{else } 2555 //\end{cases} 2556 //\end{equation}",example="TimeWindow.txt"] 2557 2558 {//$ DR 2011-12:[ IOTimeWindow added 2559 2560 public: 2561 IOTimeWindow(MBS * mbsi)2562 IOTimeWindow(MBS* mbsi):InputOutputElement(mbsi) 2563 { 2564 InitConstructor(); 2565 }; 2566 2567 // y = u(2) if t_start <= u(1) <= t_end, y = 0 else SetIOTimeWindow(const double t_starti,const double t_endi)2568 virtual void SetIOTimeWindow(const double t_starti, const double t_endi) 2569 { 2570 t_start = t_starti; 2571 delta_t = t_endi - t_starti; 2572 SetNOutputs(1); 2573 SetNStates(0); 2574 reached_end = 0; 2575 } 2576 2577 // y = u(2) if t_start <= u(1), y = 0 else SetIOTimeWindow(const double t_starti)2578 virtual void SetIOTimeWindow(const double t_starti) 2579 { 2580 t_start = t_starti; 2581 delta_t = -1; 2582 SetNOutputs(1); 2583 SetNStates(0); 2584 reached_end = 0; 2585 } 2586 2587 //To be overwritten in derived class: GetCopy()2588 virtual Element* GetCopy() 2589 { 2590 Element* ec = new IOTimeWindow(*this); 2591 return ec; 2592 } 2593 //To be overwritten in derived class: CopyFrom(const Element & e)2594 virtual void CopyFrom(const Element& e) 2595 { 2596 InputOutputElement::CopyFrom(e); 2597 const IOTimeWindow& ce = (const IOTimeWindow&)e; 2598 2599 t_start = ce.t_start; 2600 delta_t = ce.delta_t; 2601 t_end = ce.t_end; // $MSax 2013-03-01: added 2602 reached_end = ce.reached_end; 2603 } 2604 InitConstructor()2605 virtual void InitConstructor() 2606 { 2607 InputOutputElement::InitConstructor(); 2608 elementname = GetElementSpec(); 2609 t_start = 0; // $MSax 2013-03-01: added 2610 t_end = 0; // $MSax 2013-03-01: added 2611 } 2612 2613 //----------------------------------------------------- 2614 //b: auto-generated functions 2615 virtual void GetElementDataAuto(ElementDataContainer& edc); 2616 virtual int SetElementDataAuto(ElementDataContainer& edc); 2617 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2618 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2619 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2620 //e: auto-generated functions 2621 //----------------------------------------------------- 2622 GetElementSpec()2623 virtual const char* GetElementSpec() const {return "IOTimeWindow";} 2624 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2625 virtual int GetExpectedNumberOfInputs(){return 2;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2626 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2627 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2628 2629 virtual double GetOutput(double t, int i=1) const; 2630 DrawElement()2631 virtual void DrawElement() 2632 { 2633 InputOutputElement::DrawElement(); 2634 }; 2635 2636 virtual const char* SymbolText() const; 2637 virtual void DrawBlockSymbol(); IsDirectFeedThrough()2638 virtual int IsDirectFeedThrough() const 2639 { 2640 return 1; 2641 } 2642 2643 protected: 2644 double t_start, delta_t, t_end; //$ MSax 2013-03-01: added t_end for script language 2645 mutable bool reached_end; 2646 };//$EDC$[endclass,IOTimeWindow] 2647 //$ DR 2011-12:] IOTimeWindow added 2648 2649 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2650 //$ RL 2012-2-1: //$ MS 2012-2-1:[ this element stops the computation, if input is unequal zero 2651 class IOStopComputation: public InputOutputElement//$EDC$[beginclass,classname=IOStopComputation,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOStopComputation, 2652 //texdescription="This element stops the computation, if input is unequal zero. It has one input and no output.",figure="IOStopComputation,IOStopComputation",example="StopComputation.txt"] 2653 { 2654 public: 2655 IOStopComputation(MBS * mbsi)2656 IOStopComputation(MBS* mbsi):InputOutputElement(mbsi) 2657 { 2658 InitConstructor(); 2659 }; 2660 //To be overwritten in derived class: GetCopy()2661 virtual Element* GetCopy() 2662 { 2663 Element* ec = new IOStopComputation(*this); 2664 return ec; 2665 } 2666 //To be overwritten in derived class: CopyFrom(const Element & e)2667 virtual void CopyFrom(const Element& e) 2668 { 2669 InputOutputElement::CopyFrom(e); 2670 const IOStopComputation& ce = (const IOStopComputation&)e; 2671 } 2672 InitConstructor()2673 virtual void InitConstructor() 2674 { 2675 InputOutputElement::InitConstructor(); 2676 elementname = GetElementSpec(); 2677 SetNStates(0); 2678 SetNOutputs(0); 2679 } 2680 GetElementSpec()2681 virtual const char* GetElementSpec() const {return "IOStopComputation";} 2682 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2683 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2684 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2685 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2686 2687 //----------------------------------------------------- 2688 //b: auto-generated functions 2689 virtual void GetElementDataAuto(ElementDataContainer& edc); 2690 virtual int SetElementDataAuto(ElementDataContainer& edc); 2691 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2692 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2693 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2694 //e: auto-generated functions 2695 //----------------------------------------------------- 2696 2697 virtual double GetOutput(double t, int i=1) const { return 0.;} //dummy, not used yet 2698 IsDirectFeedThrough()2699 virtual int IsDirectFeedThrough() const 2700 { 2701 return 0; 2702 } 2703 2704 2705 virtual const char* SymbolText() const; 2706 virtual void DrawBlockSymbol(); 2707 StartTimeStep()2708 void StartTimeStep() 2709 { 2710 if (GetInput(mbs->GetTime(),1)>0) 2711 { 2712 //GetMBS()->TIFinished();// computation stops, if input is positive 2713 GetMBS()->StopByElement();// computation stops, if input is positive 2714 } 2715 } 2716 2717 protected: 2718 };//$EDC$[endclass,IOStopComputation] 2719 //$ RL 2012-2-1: //$ MS 2012-2-1:] 2720 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2721 2722 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2723 //**begin(ued)** 2724 // name: Modifier (InputOutputElement) 2725 // short description: Modfier is used to change element data variables during static or dynamic simulation 2726 // available formulations: 2727 // type: continuous element 2728 // development status: missing check for closed loops of evaluation (if modifier points to same object data as input) 2729 // long description: 2730 //**end(ued)** 2731 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2732 2733 //$ MSax 2013-1:[ added element data modifier 2734 class IOElementDataModifier: public InputOutputElement //$EDC$[beginclass,classname=IOElementDataModifier,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOElementDataModifier, 2735 //texdescription="This element can be used to modify data of a constraint or element. It has one input and no output.",figure="IOElementDataModifier",example="ElementDataModifier.txt"] 2736 { 2737 public: 2738 IOElementDataModifier(MBS * mbsi)2739 IOElementDataModifier(MBS* mbsi):InputOutputElement(mbsi) 2740 { 2741 InitConstructor(); 2742 }; 2743 SetIOElementDataModifier(int element_numberI,const char * variable_nameI)2744 void SetIOElementDataModifier(int element_numberI, const char* variable_nameI) 2745 { 2746 AddElement(element_numberI); //add element to constraints 2747 2748 successfully_converted = RWdata.GetVariableNameAndComponents(variable_nameI); //convert variable name into name and components in RWdata structure 2749 RWdata.RWaccess = TRWElementDataWrite; //JG 2013-01-11: we only want to read values in sensors 2750 2751 if (!successfully_converted) 2752 { 2753 UO() << "ERROR: IOElementDataModifier: variable name='" << variable_nameI << "' is not legal. Modifier is inactive.\n"; 2754 } 2755 element_number = element_numberI; 2756 variable_name = mystr(variable_nameI); 2757 }; 2758 2759 //To be overwritten in derived class: 2760 virtual Element* GetCopy(); 2761 2762 //To be overwritten in derived class: 2763 virtual void CopyFrom(const Element& e); 2764 2765 virtual void InitConstructor(); 2766 GetElementSpec()2767 virtual const char* GetElementSpec() const {return "IOElementDataModifier";} 2768 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()2769 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2770 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2771 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2772 2773 //----------------------------------------------------- 2774 //b: auto-generated functions 2775 virtual void GetElementDataAuto(ElementDataContainer& edc); 2776 virtual int SetElementDataAuto(ElementDataContainer& edc); 2777 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2778 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2779 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2780 //e: auto-generated functions 2781 //----------------------------------------------------- 2782 DrawElement()2783 virtual void DrawElement() 2784 { 2785 InputOutputElement::DrawElement(); 2786 }; 2787 virtual const char* SymbolText() const; 2788 virtual void DrawBlockSymbol(); ModifyAction()2789 virtual void ModifyAction() //call this function to execute modification 2790 { 2791 if (successfully_converted) 2792 { 2793 double time = GetMBS()->GetStepEndTime(); //modification with e.g. a mathfunction should be made with evaluated function at end of time step 2794 2795 RWdata.value = GetInput(time); 2796 GetElem(1).WriteSingleElementData(RWdata); 2797 } 2798 } 2799 StartTimeStep()2800 virtual void StartTimeStep() //modification at the very beginning of the time step (note that modifier elements should be sorted to the beginning of element list) 2801 { 2802 if (successfully_converted) ModifyAction(); 2803 } PrecomputeEvalFunctions()2804 virtual void PrecomputeEvalFunctions() //modification at the very beginning of every iteration of static of dynamic simulation 2805 { 2806 if (successfully_converted && !modify_at_start_time_step_only) ModifyAction(); 2807 } 2808 2809 protected: 2810 ReadWriteElementDataVariableType RWdata; //this is the structure for the write access 2811 int successfully_converted; //store, if elementdata variable name has been successfully converted 2812 2813 int element_number; 2814 mystr variable_name; 2815 2816 int modify_at_start_time_step_only; //$EDC$[varaccess,int_bool,EDCvarname="start_of_timestep_only",EDCfolder="IOBlock",tooltiptext="modify element data at start time step only."] 2817 2818 }; //$EDC$[endclass,IOElementDataModifier] 2819 //$ MSax 2013-1:] 2820 2821 2822 2823 class IODisplay: public InputOutputElement //$EDC$[beginclass,classname=IODisplay,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IODisplay, 2824 //texdescription="This element can be used to display any (single) numberical value fed into the (single) input.", 2825 //figure="IODisplay,IODisplay",example="Display.txt"] 2826 { 2827 public: IODisplay(MBS * mbsi)2828 IODisplay(MBS* mbsi):InputOutputElement(mbsi) 2829 { 2830 InitConstructor(); 2831 Vector datainit(DataS()); // $MSax 2013-04-02: added 2832 datainit.SetAll(0.); // $MSax 2013-04-02: added 2833 SetDataInit(datainit); // $MSax 2013-04-02: added 2834 }; 2835 //To be overwritten in derived class: GetCopy()2836 virtual Element* GetCopy() 2837 { 2838 Element* ec = new IODisplay(*this); 2839 return ec; 2840 } 2841 //To be overwritten in derived class: CopyFrom(const Element & e)2842 virtual void CopyFrom(const Element& e) 2843 { 2844 InputOutputElement::CopyFrom(e); 2845 const IODisplay& ce = (const IODisplay&)e; 2846 ndigits = ce.ndigits; 2847 } 2848 InitConstructor()2849 virtual void InitConstructor() 2850 { 2851 InputOutputElement::InitConstructor(); 2852 elementname = GetElementSpec(); 2853 SetNStates(0); 2854 SetNOutputs(0); 2855 2856 draw_dim = Vector3D(3*draw_dim.X(),draw_dim.Y(),0.); 2857 SetNDigits(3); 2858 } 2859 DataS()2860 virtual int DataS() const { return 1; } // for initialization of XData vector ( remember the current_value for all times ) $MSax 2013-04-02: added 2861 GetElementSpec()2862 virtual const char* GetElementSpec() const {return "IODisplay";} GetExpectedNumberOfInputs()2863 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2864 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2865 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2866 2867 //----------------------------------------------------- 2868 //b: auto-generated functions 2869 virtual void GetElementDataAuto(ElementDataContainer& edc); 2870 virtual int SetElementDataAuto(ElementDataContainer& edc); 2871 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2872 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2873 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2874 //e: auto-generated functions 2875 //----------------------------------------------------- 2876 2877 virtual double GetOutput(double t, int i=1) const {return 0.;} 2878 EndTimeStep()2879 virtual void EndTimeStep() // $ MSax 2013-04-02: added 2880 { 2881 XData(1) = GetInput(GetMBS()->GetStepEndTime()); 2882 } 2883 IsDirectFeedThrough()2884 virtual int IsDirectFeedThrough() const 2885 { 2886 return 0; 2887 } 2888 2889 virtual const char* SymbolText() const; 2890 virtual void DrawBlockSymbol(); 2891 SetNDigits(int n)2892 virtual void SetNDigits(int n) { ndigits = n; } 2893 protected: 2894 int ndigits; //$EDC$[varaccess,EDCvarname="number_of_digits",EDCfolder="IOBlock",tooltiptext="number of digits"] 2895 2896 }; //$EDC$[endclass,IODisplay] 2897 2898 2899 class IOResponseElement: public InputOutputElement //$EDC$[beginclass,classname=IOResponseElement,parentclassname=InputOutputElement,addelementtype=TAEinput_output+TAENotInRelease,addelementtypename=IOResponseElement, 2900 //texdescription="This element allows the IOBlock to respond to a key or mouse input. ( e.g. pressing '+' or '-' in the IOBlockView Window ) ", 2901 //figure="IOResponseElement,IOResponseElement"] 2902 { 2903 public: 2904 typedef enum { TMouseResponse = 1, TKeyResponse = 2 } TGuiResponseInputMode; 2905 typedef enum { TToggle = 1, TSlider = 2 } TGuiResponseRangeMode; 2906 2907 public: IOResponseElement(MBS * mbsi)2908 IOResponseElement(MBS* mbsi):InputOutputElement(mbsi) 2909 { 2910 InitConstructor(); 2911 }; 2912 //To be overwritten in derived class: GetCopy()2913 virtual Element* GetCopy() 2914 { 2915 Element* ec = new IOResponseElement(*this); 2916 return ec; 2917 } 2918 //To be overwritten in derived class: CopyFrom(const Element & e)2919 virtual void CopyFrom(const Element& e) 2920 { 2921 InputOutputElement::CopyFrom(e); 2922 const IOResponseElement& ce = (const IOResponseElement&)e; 2923 current_value = ce.current_value; 2924 lower_bound = ce.lower_bound; 2925 upper_bound = ce.upper_bound; 2926 increment = ce.increment; 2927 input_mode = ce.input_mode; 2928 range_mode = ce.range_mode; 2929 } 2930 InitConstructor()2931 virtual void InitConstructor() 2932 { 2933 InputOutputElement::InitConstructor(); 2934 elementname = GetElementSpec(); 2935 SetNStates(0); 2936 SetNOutputs(1); 2937 // default mode: mouse response - Off/On 2938 current_value = 0.; 2939 lower_bound = 0.; 2940 upper_bound = 1.; 2941 increment = 1.; 2942 range_mode = TToggle; 2943 2944 InitXData(); 2945 } 2946 GetElementSpec()2947 virtual const char* GetElementSpec() const {return "IOResponseElement";} GetExpectedNumberOfInputs()2948 virtual int GetExpectedNumberOfInputs(){return 0;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 2949 virtual void GetElementData(ElementDataContainer& edc); //fill in all element data 2950 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 2951 2952 //----------------------------------------------------- 2953 //b: auto-generated functions 2954 virtual void GetElementDataAuto(ElementDataContainer& edc); 2955 virtual int SetElementDataAuto(ElementDataContainer& edc); 2956 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 2957 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 2958 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 2959 //e: auto-generated functions 2960 //----------------------------------------------------- 2961 2962 // functinos to store the current value in XData DataS()2963 virtual int DataS() const { return 1; } // for initialization of XData vector ( remember the current_value for all times ) InitXData()2964 virtual void InitXData() 2965 { 2966 Vector datainit(DataS()); 2967 datainit(1) = current_value; 2968 SetDataInit(datainit); 2969 } WriteToXData()2970 virtual void WriteToXData() 2971 { 2972 XData(1) = current_value; 2973 } Initialize()2974 virtual void Initialize() 2975 { 2976 if (lower_bound == 0. && upper_bound == 1. && increment == 1.) 2977 range_mode = TToggle; 2978 else range_mode = TSlider; 2979 2980 WriteToXData(); // set XData after System is assembled 2981 } ApplyChange()2982 virtual void ApplyChange() 2983 { 2984 SimulationStatus status = GetMBS()->GetSimulationStatus(); //$ MaSch 2013-08-19 2985 2986 //if ( status == TSimulationNotStarted || status == TSimulationEndedRegularly) 2987 if ( status.GetStatusFlag(TSimulationNotStarted) || status.GetStatusFlag(TSimulationEndedRegularly) ) //$ MaSch 2013-08-19 2988 WriteToXData(); // Apply data imediately ONLY if the simulation has not been started ... 2989 } StartTimeStep()2990 virtual void StartTimeStep() 2991 { 2992 WriteToXData(); // when the simulation is running, apply changes at the beginning of a step ( no iterations etc.. ) 2993 } 2994 2995 virtual double GetOutput(double t, int i=1) const { return XData(1); /*return current_value;*/ } IsDirectFeedThrough()2996 virtual int IsDirectFeedThrough() const { return 0; } 2997 2998 virtual const char* SymbolText() const; 2999 virtual void DrawBlockSymbol(); 3000 3001 // Get Funcitons GetInputMode()3002 virtual TGuiResponseInputMode GetInputMode() { return input_mode; } // response on mouse or key GetCurrentValue()3003 virtual double GetCurrentValue() { return current_value; } // get the current value IsToggle()3004 virtual int IsToggle() { if (range_mode == TToggle) return true; else return false; } // Toggle or Slide 3005 3006 // Set Functions without update ( can be used before Assemble ) SetInputMode(TGuiResponseInputMode mode)3007 virtual void SetInputMode(TGuiResponseInputMode mode) { input_mode = mode; } SetIncrement(double inc)3008 virtual void SetIncrement(double inc) { increment = inc; } SetCurrentVaule(double val)3009 virtual int SetCurrentVaule(double val) 3010 { 3011 if (lower_bound > val || val > upper_bound) { return false; } // conflict range <-> current_value 3012 else { current_value = val; return true; } 3013 } SetRange(double lower,double upper)3014 virtual int SetRange(double lower, double upper) 3015 { 3016 if ( lower > current_value || current_value > upper ) { return false; } // conflict range <-> current_value 3017 else { lower_bound = lower; upper_bound = upper; return true; } 3018 } 3019 3020 // Set Functions with update ( use only after Assemble - these are the resoponse to the GUI ) Increase()3021 virtual void Increase() { if (!IsToggle()) SetCurrentVaule(GetCurrentValue()+1); else FlipState(); ApplyChange(); } Decrease()3022 virtual void Decrease() { if (!IsToggle()) SetCurrentVaule(GetCurrentValue()-1); else FlipState(); ApplyChange(); } FlipState()3023 virtual void FlipState() { if (GetCurrentValue() == 0) SetCurrentVaule(1); else SetCurrentVaule(0); ApplyChange(); } 3024 3025 // functions to catch the input - implemented in derived class KeyPressed(int key)3026 virtual int KeyPressed(int key) { return false; } 3027 3028 3029 protected: 3030 double current_value; 3031 double lower_bound, upper_bound, increment; 3032 TGuiResponseInputMode input_mode; 3033 TGuiResponseRangeMode range_mode; 3034 }; //$EDC$[endclass,IOResponseElement] 3035 3036 class IOKeyResponseElement: public IOResponseElement //$EDC$[beginclass,classname=IOKeyResponseElement,parentclassname=IOResponseElement,addelementtype=TAEinput_output+TAENotInRelease,addelementtypename=IOKeyResponseElement, 3037 //texdescription="This element allows the IOBlock to respond to a key input. ( e.g. pressing '+' or '-' ) ", 3038 //figure="IOKeyResponseElement,IOKeyResponseElement"] 3039 { 3040 public: IOKeyResponseElement(MBS * mbsi)3041 IOKeyResponseElement(MBS* mbsi):IOResponseElement(mbsi) 3042 { 3043 InitConstructor(); 3044 }; 3045 3046 //To be overwritten in derived class: GetCopy()3047 virtual Element* GetCopy() 3048 { 3049 Element* ec = new IOKeyResponseElement(*this); 3050 return ec; 3051 } 3052 //To be overwritten in derived class: CopyFrom(const Element & e)3053 virtual void CopyFrom(const Element& e) 3054 { 3055 IOResponseElement::CopyFrom(e); 3056 const IOKeyResponseElement& ce = (const IOKeyResponseElement&)e; 3057 inc_key = ce.inc_key; 3058 dec_key = ce.dec_key; 3059 } 3060 3061 // copied from winuser.h 3062 // chould be <included> 3063 #define VK_OEM_PLUS 0xBB // '+' any country 3064 #define VK_OEM_MINUS 0xBD // '-' any country 3065 InitConstructor()3066 virtual void InitConstructor() 3067 { 3068 IOResponseElement::InitConstructor(); 3069 input_mode = IOResponseElement::TKeyResponse; 3070 inc_key = VK_OEM_PLUS; 3071 dec_key = VK_OEM_MINUS; 3072 } GetElementSpec()3073 virtual const char* GetElementSpec() const {return "IOKeyResponseElement";} 3074 3075 //----------------------------------------------------- 3076 //b: auto-generated functions 3077 virtual void GetElementDataAuto(ElementDataContainer& edc); 3078 virtual int SetElementDataAuto(ElementDataContainer& edc); 3079 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 3080 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 3081 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 3082 //e: auto-generated functions 3083 //----------------------------------------------------- 3084 3085 // set the keys to respond to SetIncKey(int key)3086 virtual void SetIncKey(int key) { inc_key = key; } SetDecKey(int key)3087 virtual void SetDecKey(int key) { dec_key = key; } 3088 3089 // trigger response to a key pressed RespondToKey(int key)3090 virtual int RespondToKey(int key) 3091 { 3092 if (key == inc_key) 3093 { 3094 Increase(); 3095 return 1; 3096 } 3097 if (key == dec_key) 3098 { 3099 Decrease(); 3100 return 1; 3101 } 3102 return 0; 3103 } 3104 3105 3106 private: 3107 int inc_key; // key that triggers increase 3108 int dec_key; // key that triggers decrease 3109 }; //$EDC$[endclass,IOKeyResponseElement] 3110 3111 class IOMouseResponseElement: public IOResponseElement //$EDC$[beginclass,classname=IOMouseResponseElement,parentclassname=IOResponseElement,addelementtype=TAEinput_output+TAENotInRelease,addelementtypename=IOMouseResponseElement, 3112 //texdescription="This element allows the IOBlock to respond to a mouse input. ( e.g. clicking the IOElement in the IOBlocksView) ", 3113 //figure="IOMouseResponseElement,IOMouseResponseElement"] 3114 { 3115 public: IOMouseResponseElement(MBS * mbsi)3116 IOMouseResponseElement(MBS* mbsi):IOResponseElement(mbsi) 3117 { 3118 InitConstructor(); 3119 }; 3120 //To be overwritten in derived class: GetCopy()3121 virtual Element* GetCopy() 3122 { 3123 Element* ec = new IOMouseResponseElement(*this); 3124 return ec; 3125 } 3126 //To be overwritten in derived class: CopyFrom(const Element & e)3127 virtual void CopyFrom(const Element& e) 3128 { 3129 IOResponseElement::CopyFrom(e); 3130 const IOMouseResponseElement& ce = (const IOMouseResponseElement&)e; 3131 } 3132 InitConstructor()3133 virtual void InitConstructor() 3134 { 3135 IOResponseElement::InitConstructor(); 3136 input_mode = IOResponseElement::TMouseResponse; 3137 } GetElementSpec()3138 virtual const char* GetElementSpec() const {return "IOMouseResponseElement";} 3139 3140 //----------------------------------------------------- 3141 //b: auto-generated functions 3142 virtual void GetElementDataAuto(ElementDataContainer& edc); 3143 virtual int SetElementDataAuto(ElementDataContainer& edc); 3144 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 3145 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 3146 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 3147 //e: auto-generated functions 3148 //----------------------------------------------------- 3149 3150 }; //$EDC$[endclass,IOMouseResponseElement] 3151 3152 3153 class IOMinMax: public InputOutputElement//$EDC$[beginclass,classname=IOMinMax,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOMinMax, 3154 //texdescription="This block returns the minimum, maximum or average value of the input. Up to a specific point of time, this functionality is switched off and the output y is equal to the input u. This block can be used to postprocess sensor values.", 3155 //modus="{1 = minimum}{$y = u$ for $t \leq t_0$ \newline $y = \min_{t \geq t_0}(u)$ for $t > t_0 $ \newline with $t_0 = $ IOBlock.start\_time}", 3156 //modus="{2 = maximum}{$y = u$ for $t \leq t_0$ \newline $y = \max_{t \geq t_0}(u)$ for $t > t_0 $}", 3157 //modus="{3 = average}{$y = u$ for $t \leq t_0$ \newline $y = \frac{1}{N} \sum_{t_i \geq t_0} u_i $ for $t_i > t_0 $}", 3158 //modus="{4 = minimum(abs)}{$y = u$ for $t \leq t_0$ \newline $y = \min_{t \geq t_0}(\left|u\right|)$ for $t > t_0 $}", 3159 //modus="{5 = maximum(abs)}{$y = u$ for $t \leq t_0$ \newline $y = \min_{t \geq t_0}(\left|u\right|)$ for $t > t_0 $}", 3160 //modus="{6 = average(abs)}{$y = u$ for $t \leq t_0$ \newline $y = \frac{1}{N} \sum_{t_i \geq t_0} \left|u_i\right| $ for $t_i > t_0 $}", 3161 //example="IOMinMax.txt", 3162 //figure="IOMinMax,IOMinMax"] 3163 { 3164 public: 3165 IOMinMax(MBS * mbsi)3166 IOMinMax(MBS* mbsi):InputOutputElement(mbsi) 3167 { 3168 InitConstructor(); 3169 SetNStates(0); 3170 SetNOutputs(1); 3171 }; 3172 3173 void SetIOMinMax(int mode_i, double start_time_i = 0.) 3174 { 3175 start_time = start_time_i; 3176 mode = mode_i; 3177 } 3178 //To be overwritten in derived class: GetCopy()3179 virtual Element* GetCopy() 3180 { 3181 Element* ec = new IOMinMax(*this); 3182 return ec; 3183 } 3184 //To be overwritten in derived class: CopyFrom(const Element & e)3185 virtual void CopyFrom(const Element& e) 3186 { 3187 InputOutputElement::CopyFrom(e); 3188 const IOMinMax& ce = (const IOMinMax&)e; 3189 start_time = ce.start_time; 3190 mode = ce.mode; 3191 first_time_step = ce.first_time_step; 3192 current_value = ce.current_value; 3193 } 3194 InitConstructor()3195 virtual void InitConstructor() 3196 { 3197 InputOutputElement::InitConstructor(); 3198 elementname = GetElementSpec(); 3199 start_time = 0.; 3200 mode = 1; 3201 InitXData(); 3202 first_time_step = 1; 3203 } 3204 3205 // functions to store the min/max value in XData DataS()3206 virtual int DataS() const { return 2; } // for initialization of XData vector ( remember the min/max value for all times ) InitXData()3207 virtual void InitXData() 3208 { 3209 Vector datainit(DataS()); 3210 datainit(1) = 0.; // just dummy value 3211 datainit(2) = 0.; // start counter with 0 3212 SetDataInit(datainit); 3213 } WriteToXData()3214 virtual void WriteToXData() 3215 { 3216 XData(1) = current_value; 3217 XData(2) = XData(2)+1; // counter for average 3218 } 3219 GetElementSpec()3220 virtual const char* GetElementSpec() const {return "IOMinMax";} 3221 virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()3222 virtual int GetExpectedNumberOfInputs(){return 1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected GetElementData(ElementDataContainer & edc)3223 virtual void GetElementData(ElementDataContainer& edc) //fill in all element data 3224 { 3225 InputOutputElement::GetElementData(edc); 3226 } SetElementData(ElementDataContainer & edc)3227 virtual int SetElementData(ElementDataContainer& edc) //set element data according to ElementDataContainer 3228 { 3229 return InputOutputElement::SetElementData(edc); 3230 } 3231 3232 //----------------------------------------------------- 3233 //b: auto-generated functions 3234 virtual void GetElementDataAuto(ElementDataContainer& edc); 3235 virtual int SetElementDataAuto(ElementDataContainer& edc); 3236 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 3237 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 3238 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 3239 //e: auto-generated functions 3240 //----------------------------------------------------- 3241 3242 virtual void StartTimeStep(); 3243 virtual double GetOutput(double t, int i=1) const 3244 { 3245 if(first_time_step) 3246 return GetInput(t,1); 3247 else 3248 { 3249 if(mode == 3 || mode == 6) // average 3250 { 3251 return current_value/XData(2); 3252 } 3253 else 3254 return current_value; 3255 } 3256 } IsDirectFeedThrough()3257 virtual int IsDirectFeedThrough() const { return 1; } 3258 3259 virtual const char* SymbolText() const; DrawBlockSymbol()3260 virtual void DrawBlockSymbol() { return InputOutputElement::DrawBlockSymbol(); } 3261 3262 protected: 3263 int mode; //$EDC$[varaccess,EDCvarname="mode", minval=1,maxval=6,EDCfolder="IOBlock",tooltiptext="1..min, 2..max, 3..avg, 4..min(abs), 5..max(abs), 6..avg(abs)"] 3264 double start_time; //$EDC$[varaccess,EDCvarname="start_time", EDCfolder="IOBlock",tooltiptext="Up to this point of time, the output is equal to the input. Afterwards the output is computed according to the mode."] 3265 int first_time_step; 3266 double current_value; 3267 };//$EDC$[endclass,IOMinMax] 3268 3269 3270 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3271 //**begin(ued)** 3272 // name: IOTCPIPBlock 3273 // short description: Communication block for TCP/IP 3274 // available formulations: 3275 // type: 3276 // development status: not finished 3277 // long description: 3278 //**end(ued)** 3279 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3280 3281 enum CommunicationFlag {Fneutral = 0x00000000, Freset = 0x00000001, Ferror = 0x00000002, Fclose = 0x00000003}; 3282 3283 //$ MSax 2013-5:[ added 3284 class IOTCPIPBlock: public InputOutputElement //$EDC$[beginclass,classname=IOTCPIPBlock,parentclassname=InputOutputElement,addelementtype=TAEinput_output,addelementtypename=IOTCPIPBlock, 3285 //texdescription="This I/O element is a communication block based on TCP/IP which allows HOTINT to connect to other programs or tools, opening up a large range of possible applications 3286 // including external control, user-defined ``add-ons'', or even co-simulation.// 3287 // Based on the specified IP (v4) address and port number the IOTCPIPBlock sets up a server socket and waits for a 3288 // connection request from a client. Hence, HOTINT here plays the server role, and the external program is the client application. Data exchange is performed at a stage before every time step in HOTINT, following below protocol:\\ 3289 // The outgoing data, i.e.~the data sent from HOTINT to the client, is an array of 8-byte double precision numbers corresponding to the current values of the inputs of the I/O element, and additionally, an 8-byte sequence 3290 // which is appended to that array and includes communication control flags (see the \textit{Communication flags} - section below for more details). Hence, the total amount of outgoing data is (number of inputs\,+\,1) times 8 bytes (double precision numbers). 3291 // After the client has received and processed that data, it sends back a data package to HOTINT -- the incoming data for the I/O element -- which again consists of an array of double precision numbers, this time with the length (number of outputs\,+\,1). 3292 // The first (number of output) double precision values determine the outputs of the I/O element, and the last 8 bytes again are used for the transfer of communication flags.\\ 3293 // HOTINT now begins the computation of one time step, where the transmitted data from the client is accessible via the outputs of the IOTCPIPBlock. \vspace*{12pt} \\ 3294 // \textit{Important notes} \vspace*{6pt} \\ 3295 // -- The waiting procedure for the client connection request, as well as the send and receive operations all are so-called ``blocking calls''. This means that HOTINT will wait for those operations to 3296 // finish, and during that time, not respond to any user input. Therefore, a reasonable timeout (default is 10 seconds) should be specified for the IOTCPIPBlock to allow TCP/IP connection or transmission error handling. \vspace*{6pt}\\ 3297 // -- You will probably have to adjust your firewall settings and set appropriate permissions for HOTINT and the client application. \vspace*{6pt}\\ 3298 // -- Depending on the implementation of the client, it might be neccessary to start the server, i.e., HOTINT, first. \vspace*{6pt} \\ 3299 // -- Since HOTINT is running on Microsoft Windows, the memory byte order, also called ``endianness'', is ``Little Endian'', which means that the least significant bytes/digits are stored ``first'' in memory, i.e., on the smallest memory address. 3300 // Therefore, any data sent from or received by the IOTCPIPBlock has or must have that byte order, respectively. 3301 // You probably have to take that into account on the client side, especially if the client is running on a different platform and/or architecture on another computer. \vspace*{12pt}\\ 3302 // \textit{Communication flags} \vspace*{6pt} \\ 3303 // Currently, the following 4-byte flags are implemented: \vspace*{6pt}\\ 3304 // (1) Neutral flag: \texttt{0x00000000} (integer value: \texttt{0}). This flag signals that the application is running (properly) and no further action is required. \\ 3305 // (2) Reset flag: \texttt{0x00000001} (integer value: \texttt{1}). This flag is sent from HOTINT to the client in the first step of the computation. This can be used, for instance, to 3306 // reset the client application.\\ 3307 // (3) Error flag: \texttt{0x00000002} (integer value: \texttt{2}). Indicates that an error has occurred. If HOTINT receives the error flag, an error message is issued, the connection is closed and the program execution terminated. \\ 3308 // (4) Close flag: \texttt{0x00000003} (integer value: \texttt{3}). This flag is sent from HOTINT to the client to indicate that the computation has finished and the connection will be closed, which is the case when the computation has actually finished, or the ``Stop''-button has been hit. \\ 3309 // (5) Any other value: Treated as error flag (3). \vspace*{6pt}\\ 3310 // One of these flags is stored in and read from the last 8 bytes of the exchanged data -- corresponding to one additional double precision number -- in either direction in every time step. Currently, for simplicity, the flag is just casted explicitly from an integer to 3311 // a double precision number which then can be transmitted and casted back to an integer exactly. Of course, this procedure must be followed on both the server and the client side. 3312 //", 3313 //texdescriptionComments="For the use of this element an active network adapter is required. If you only want to communicate locally on your computer and do not have an active network adapter, 3314 // you can use a so-called ``loopback adapter'' which emulates an active real adapter in a real network and can be configured and used as such. The following steps summarize how 3315 // a ``loopback adapter'' can be installed on Microsoft Windows: \vspace*{6pt} \\ 3316 //(1) Open the device manager\\ 3317 //(2) Select the network category and choose ``Action $\rightarrow$ Add legacy hardware'' via the menu\\ 3318 //(3) Choose the option for manual installation and select the category ``network adapters'' from the list\\ 3319 //(4) In the next dialog select ``Microsoft'' as vendor and ``Microsoft loopback adapter'' as hardware component\\ 3320 //(5) Proceed and finish the installation\\ \\ 3321 //\textbf{Example: Communication with Simulink/Matlab} \\ 3322 //This example demonstrates how to realize a connection between HOTINT and Matlab/Simulink. The purpose of the TCP/IP block is to use other powerful tools for some computations. For example it is possible to do the control law calculations for the actuation of the multibody system in Simulink (as alternative to the IOBlocks in HOTINT). It's also very simple to do a parameter variation, see the advanced example in the folder ``examples/balancing\_cart\_TCPIP''. \\ 3323 //In ``examples/TCPIP'' a very simple communication example is included: From the HOTINT side four different double values (simulation time t multiplied by the gain factors one to four) are transmitted to Simulink. Simulink summates the first and second respectively the third and fourth value and sends the two double values back to HOTINT. The values are captured by sensors, stored in the solution file and can be visualized in the plot tool. \\ 3324 //Comment: For testing purposes you can also use the executable ``TCPIP\_client.exe'' which has the same functionality as the Simulink example. To use this client executable create a ``IP.txt'' file in the same folder. The first four lines represent the IP address of the HOTINT computer, the fifth line is the port number. \\ \\ 3325 //To start this example, following things have to be done: \\ 3326 //(1) Start Matlab/Simulink and open the file \textsf{communication.mdl} in the folder ``examples/TCPIP'', see figure \ref{structure_Simulink}.\\ 3327 //Comment: If the ``Instrument Control Toolbox'' is not installed the TCP/IP communication blocks appear red and indicate an unresolved reference to a library block (bad link). The figure shows the basic structure that should not be changed. The output of the ``TCP/IP Receive'' block is a vector $y_{rec}=[t,x_1,...,x_n,f]^{T}$ with HOTINT time $t$, data variables $x_1$ to $x_n$ and the handling flag $f$. The ``Selector'' block outputs the last element of the vector (flag $f$) for the flag handling. You have to adapt the these two blocks if you want to change the number of received variables. There is no need to change the ``flag handling in'' block.\\ 3328 //\begin{figure}[H] 3329 // \begin{center} 3330 // \includegraphics[width=0.9\textwidth]{D:/cpp/HotInt_V1/documentation/EDCauto_documentation/figures/TCPIP.png} 3331 // \caption{TCP/IP communication with Matlab/Simulink (do not change this structure)} 3332 // \label{structure_Simulink} 3333 // \end{center} 3334 //\end{figure} 3335 //\begin{figure}[H] 3336 // \begin{center} 3337 // \includegraphics[width=0.9\textwidth]{D:/cpp/HotInt_V1/documentation/EDCauto_documentation/figures/TCPIP_SS_computations.png} 3338 // \caption{Subsystem computations} 3339 // \label{SS_comp} 3340 // \end{center} 3341 //\end{figure} 3342 //(2) Make sure that the ``Current Folder'' is the folder which include the \textsf{communication.mdl} file.\\ 3343 //(3) Double click the ``TCP/IP Receive'' block and select the ``Remote address'' (i.e., the IP address) of the computer HOTINT is running on and select a ``Port''. Repeat this point for the ``TCP/IP Send'' block. \\ 3344 //Comment: If HOTINT and Simulink is running on the same computer you can also choose localhost (``127.0.0.1''). \\ 3345 //(4) Set the ``Sample Time'' of every block (TCP/IP Receive, Constants,...) and choose fixed step size in the ``Solver Options''. \\ 3346 //(5) Open the subsystem ``computations'', see figure \ref{SS_comp}. This subsystem contains all computations $\mathbf{y=f\left(u\right)}$ with input $\mathbf{u}$ and output $\mathbf{y}$. \\ 3347 //Comment: Change this subsystem to your needs. \\ 3348 //(6) Open the subsystem ``flag handling out'', see figure \ref{fho}. In default no handling flags are transmitted to HOTINT. \\ 3349 //Comment: Change this subsystem to your needs. \\ 3350 //(7) Save the mdl file. 3351 //\begin{figure}[H] 3352 // \begin{center} 3353 // \includegraphics[width=0.9\textwidth]{D:/cpp/HotInt_V1/documentation/EDCauto_documentation/figures/TCPIP_flagHandlingIn.png} 3354 // \caption{TCP/IP subsystem ``flag handling in''} 3355 // \end{center} 3356 //\end{figure} 3357 //\begin{figure}[H] 3358 // \begin{center} 3359 // \includegraphics[width=0.9\textwidth]{D:/cpp/HotInt_V1/documentation/EDCauto_documentation/figures/TCPIP_flagHandlingOut.png} 3360 // \caption{TCP/IP subsystem ``flag handling out''} 3361 // \label{fho} 3362 // \end{center} 3363 //\end{figure} 3364 //(8) Open the \textsf{TCPIP.hid} HOTINT file and type in the same ``ip\_address'' and ``port\_number'' as for the Matlab/Simulink side. \\ 3365 //(9) Make sure that ``max\_step\_size'' and ``min\_step\_size'' in the subtree ``SolverOptions.Timeint'' are set to the same value as the fixed ``Sample Time'' in Simulink. \\ 3366 //Comment: This is very important especially for the case of time dependent blocks like integrators in Simulink. \\ 3367 //(10) Save the file. \\ 3368 //(11) Load the \textsf{communication.hid} file in HOTINT. \\ 3369 //(12) Click the ``Start simulation'' button in Simulink. \\ 3370 //(13) Click the ``Start!'' button in HOTINT. \\ \\ 3371 //Comment: The points 11-13 have to be executed within the timeout limits. You can change the latter in the TCP/IP blocks for both HOTINT and Simulink. During these steps connection errors might occur due to firewall restrictions; you will probably have to set the corresponding permissions in your firewall(s). \\ 3372 //It is also recommended to choose the Simulink ``Simulation stop time'' higher as the ``end\_time'' in HOTINT. The reason is that HOTINT sends a stop flag after the last simulation step and in Simulink this flag is used to execute a ``Stop'' block which ends the communication and simulation. 3373 //",example="TCPIP.txt"] 3374 { 3375 public: 3376 IOTCPIPBlock(MBS * mbsi)3377 IOTCPIPBlock(MBS* mbsi):InputOutputElement(mbsi),serversocket(mbsi->GetServerSocket()) 3378 { 3379 InitConstructor(); 3380 }; 3381 3382 //void SetIOTCPIPBlock(....) // TODO 3383 //{ 3384 3385 //}; 3386 3387 //To be overwritten in derived class: 3388 virtual Element* GetCopy(); 3389 3390 //To be overwritten in derived class: 3391 virtual void CopyFrom(const Element& e); 3392 3393 virtual void InitConstructor(); 3394 GetElementSpec()3395 virtual const char* GetElementSpec() const {return "IOTCPIPBlock";} 3396 //virtual int CheckConsistency(mystr& errorstr); //rv==0 --> OK, rv==1 --> can not compute, rv==2 --> can not draw and not compute GetExpectedNumberOfInputs()3397 virtual int GetExpectedNumberOfInputs(){return -1;}; // return the needed expected inputs, if not correct, the check of consistency reports error; -1 ... arbitrary number of inputs expected 3398 3399 virtual int SetElementData(ElementDataContainer& edc); //set element data according to ElementDataContainer 3400 3401 //----------------------------------------------------- 3402 //b: auto-generated functions 3403 virtual void GetElementDataAuto(ElementDataContainer& edc); 3404 virtual int SetElementDataAuto(ElementDataContainer& edc); 3405 virtual int ReadSingleElementDataAuto(ReadWriteElementDataVariableType& RWdata); 3406 virtual int WriteSingleElementDataAuto(const ReadWriteElementDataVariableType& RWdata); // Write access to a single element variable 3407 virtual int GetAvailableSpecialValuesAuto(TArrayDynamic<ReadWriteElementDataVariableType>& available_variables); // returns all available directly (ReadWrite-) accessable variables 3408 //e: auto-generated functions 3409 //----------------------------------------------------- 3410 DrawElement()3411 virtual void DrawElement() 3412 { 3413 InputOutputElement::DrawElement(); 3414 }; 3415 virtual const char* SymbolText() const; DrawBlockSymbol()3416 virtual void DrawBlockSymbol() { return InputOutputElement::DrawBlockSymbol(); } 3417 3418 virtual double GetOutput(double t, int i=1) const 3419 { 3420 return XData(i); 3421 } 3422 3423 void SetOutput(double val, int i=1) //write-access to XData 3424 { 3425 XData(i)=val; 3426 } 3427 StartTimeStep()3428 virtual void StartTimeStep() // communication -> receive and send data 3429 { 3430 //double t_end = GetMBS()->GetStepEndTime(); //t_end = t+deltaT 3431 double t = GetMBS()->GetTime(); 3432 3433 //int i = 1; 3434 //double u = GetInput(t, i); 3435 // TODO 3436 3437 Communicate(t); 3438 3439 //double u1 = GetInput(t, 1); 3440 //double u2 = GetInput(t, 2); 3441 //for (int i=1; i<=n_output; i++) 3442 //{ 3443 // if (i<3) XData(i) = u1+i; 3444 // else XData(i) = u2+i; 3445 //} 3446 } 3447 3448 virtual void Initialize(); // initialization TCPIP connection 3449 DataS()3450 virtual int DataS() const { return n_output; } // for initialization of XData vector ( remember the current_value for all times ) 3451 3452 virtual void ComputationFinished(); 3453 3454 virtual ~IOTCPIPBlock(); 3455 3456 //set a CommunicationFlag on byte position pos (starting from 0) in the array addtcpdata (i.e., at the address addtcpdata+i) 3457 //if convertdouble is set, the flag is converted explicitly to double before 3458 void SetCommunicationFlag(int pos, CommunicationFlag flag, int convertdouble=0); 3459 3460 //get a CommunicationFlag on byte position pos in addtcpdata 3461 //if convertdouble is set, it is assumed that the flag has been converted to a an 8-byte double-precision number before 3462 CommunicationFlag GetCommunicationFlag(int pos, int convertdouble=0); 3463 3464 protected: 3465 //variables 3466 int port_number; //$EDC$[varaccess,EDCvarname="port_number", EDCfolder="IOBlock",tooltiptext="Port number, e.g. '50000'."] 3467 mystr ip_address; //$EDC$[varaccess,EDCvarname="ip_address", EDCfolder="IOBlock",tooltiptext="IP address, e.g. '127.0.0.1' (localhost). Do not neglect the dots between the numbers."] 3468 //EDC int n_output; //$EDC$[varaccess,EDCvarname="received_data_size", EDCfolder="IOBlock",tooltiptext="Number of received data values (outputs). This number has to be consistent with the transmitted data values of the other communication side (the additional double for the communication flags is not corresponding to this number)."] 3469 3470 int timeout; //$EDC$[varaccess,EDCvarname="timeout", EDCfolder="IOBlock",tooltiptext="TCP/IP timeout in milliseconds; default is 10000."] 3471 3472 TCPIPHotInt* & serversocket; 3473 double* tcpdata; // auxiliary array for TCP/IP data transfer (data must be contiguous in memory) 3474 char* addtcpdata; // auxiliary array for additional TCP/IP data 3475 3476 int use_default_protocol; //enabled by default; if so, the following flags and parameters are set to their defaults and the default protocol is used (for more details see element description) 3477 int use_additional_communication; // flag to enable/disable transfer of additional data (e.g. protocol information); 1 by default 3478 int separate_additional_communication; // if this flag is set, first, the additional information is transferred, and then the actual data separately; otherwise, the additional info is just appended to the data; 0 by default 3479 int additional_communication_length; // number of data units of additional data (same for incoming and outgoing data); zero, if use_additional_communication is not set; 1 by default 3480 int additional_communication_unit_size; // size of data units of additional data; possible values: 1,2,4,8 bytes; default value is 8; if separate_additional_communication is not set, the default is used 3481 3482 int isinitialized; //internally used for this element; status of the TCPIP socket via serversocket.GetStatus() 3483 void Communicate(double t); 3484 void OutgoingDataCommunication(double t); 3485 void IncomingDataCommunication(); 3486 int ReactToAdditionalCommunication(double t); // for support of any communication scheme / protocol 3487 3488 //close connection, memory clean-up 3489 void CloseAndCleanUp(); 3490 3491 }; //$EDC$[endclass,IOTCPIPBlock] 3492 //$ MSax 2013-5:] 3493 3494 #endif 3495