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