@@ -60,6 +60,7 @@ class ControlSystem(object):
6060 eps 1e-2 Tolerance for the solution of the initial value problem
6161 ierr 1e-1 Tolerance for the error on the whole interval
6262 tol 1e-5 Tolerance for the solver of the equation system
63+ dt_sim 1e-2 Sample time for integration (initial value problem)
6364 use_chains True Whether or not to use integrator chains
6465 sol_steps 100 Maximum number of iteration steps for the eqs solver
6566 first_guess None to initiate free parameters (might be useful: {'seed': value})
@@ -72,6 +73,8 @@ def __init__(self, ff, a=0., b=1., xa=[], xb=[], ua=[], ub=[], constraints=None,
7273 self ._parameters ['maxIt' ] = kwargs .get ('maxIt' , 10 )
7374 self ._parameters ['eps' ] = kwargs .get ('eps' , 1e-2 )
7475 self ._parameters ['ierr' ] = kwargs .get ('ierr' , 1e-1 )
76+ self ._parameters ['dt_sim' ] = kwargs .get ('dt_sim' , 0.01 )
77+ self ._parameters ['accIt' ] = kwargs .get ('accIt' , 5 )
7578
7679 # create an object for the dynamical system
7780 self .dyn_sys = DynamicalSystem (f_sym = ff , a = a , b = b , xa = xa , xb = xb , ua = ua , ub = ub )
@@ -108,7 +111,7 @@ def set_param(self, param='', value=None):
108111 The new value
109112 '''
110113
111- if param in {'maxIt' , 'eps' , 'ierr' }:
114+ if param in {'maxIt' , 'eps' , 'ierr' , 'dt_sim' }:
112115 self ._parameters [param ] = value
113116
114117 elif param in {'n_parts_x' , 'sx' , 'n_parts_u' , 'su' , 'kx' , 'use_chains' , 'nodes_type' , 'use_std_approach' }:
@@ -262,13 +265,18 @@ def solve(self):
262265
263266 # do the first iteration step
264267 logging .info ("1st Iteration: {} spline parts" .format (self .eqs .trajectories .n_parts_x ))
265- self ._iterate ()
266-
268+ try :
269+ self ._iterate ()
270+ except auxiliary .NanError :
271+ logging .warn ("NanError" )
272+ return None , None
273+
267274 # this was the first iteration
268275 # now we are getting into the loop
269276 self .nIt = 1
270277
271278 while not self .reached_accuracy and self .nIt < self ._parameters ['maxIt' ]:
279+
272280 # raise the number of spline parts
273281 self .eqs .trajectories ._raise_spline_parts ()
274282
@@ -280,8 +288,12 @@ def solve(self):
280288 logging .info ("{}th Iteration: {} spline parts" .format (self .nIt + 1 , self .eqs .trajectories .n_parts_x ))
281289
282290 # start next iteration step
283- self ._iterate ()
284-
291+ try :
292+ self ._iterate ()
293+ except auxiliary .NanError :
294+ logging .warn ("NanError" )
295+ return None , None
296+
285297 # increment iteration number
286298 self .nIt += 1
287299
@@ -308,6 +320,16 @@ def _iterate(self):
308320
309321 As a last, the resulting initial value problem is simulated.
310322 '''
323+
324+ # Note: in pytrajectory there are Three main levels of 'iteration'
325+ # Level 3: perform one LM-Step (i.e. calculate a new set of parameters)
326+ # This is implemented in solver.py. Ends when tolerances are met or
327+ # the maximum number of steps is reached
328+ # Level 2: restarts the LM-Algorithm with the last values
329+ # and stops if the desired accuracy for the initial value problem
330+ # is met or if the maximum number of steps solution attempts is reached
331+ # Level 1: increasing the spline number.
332+ # In Each step solve a nonlinear optimization problem (with LM)
311333
312334 # Initialise the spline function objects
313335 self .eqs .trajectories .init_splines ()
@@ -320,16 +342,40 @@ def _iterate(self):
320342 G , DG = C .G , C .DG
321343
322344 # Solve the collocation equation system
323- sol = self .eqs .solve (G , DG )
324345
325- # Set the found solution
326- self .eqs .trajectories .set_coeffs (sol )
346+ new_solver = True
347+ while True :
348+ sol = self .eqs .solve (G , DG , new_solver = new_solver )
349+
350+ # in the following iterations we want to use the same solver
351+ # object (we just had an intermediate look, whether the solution
352+ # of the initial value problem is already sufficient accurate.)
353+
354+ new_solver = False
327355
328- # Solve the resulting initial value problem
329- self .simulate ()
330-
331- # check if desired accuracy is reached
332- self .check_accuracy ()
356+ # Set the found solution
357+ self .eqs .trajectories .set_coeffs (sol )
358+
359+ # Solve the resulting initial value problem
360+ self .simulate ()
361+
362+ # check if desired accuracy is reached
363+ self .check_accuracy ()
364+
365+ # any of the follwing conditions ends the loop
366+ slvr = self .eqs .solver
367+ cond1 = self .reached_accuracy
368+
369+ # following means: solver stopped not
370+ # only because of maximum stepp # number
371+ cond2 = (not slvr .cond_num_steps ) or slvr .cond_abs_tol \
372+ or slvr .cond_rel_tol
373+ cond3 = self .eqs .solver .solve_count >= self ._parameters ['accIt' ]
374+
375+ if cond1 or cond2 or cond3 :
376+ break
377+ else :
378+ logging .debug ('New attempt\n \n ' )
333379
334380 def simulate (self ):
335381 '''
@@ -358,7 +404,7 @@ def simulate(self):
358404 start .append (start_dict [x ])
359405
360406 # create simulation object
361- S = Simulator (ff , T , start , self .eqs .trajectories .u )
407+ S = Simulator (ff , T , start , self .eqs .trajectories .u , dt = self . _parameters [ 'dt_sim' ] )
362408
363409 logging .debug ("start: %s" % str (start ))
364410
0 commit comments