Skip to content

Commit

Permalink
CLUI: solverID now gives hint of what type of global-search criterion…
Browse files Browse the repository at this point in the history
… was used
  • Loading branch information
Steinar Elgsæter committed Dec 11, 2024
1 parent 92c5eca commit b4e20da
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 24 deletions.
22 changes: 8 additions & 14 deletions Dynamic/Identification/ClosedLoopGainGlobalSearchResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ public void Add(double gain, UnitParameters unitParameters, double covBtwDestAnd
/// </summary>
/// <param name="initalGainEstimate"></param>
/// <returns></returns>
public Tuple<UnitModel,bool> GetBestModel(double initalGainEstimate)
public Tuple<UnitModel,string> GetBestModel(double initalGainEstimate)
{
if (unitParametersList.Count()== 0)
return new Tuple<UnitModel,bool>(null,false);
return new Tuple<UnitModel,string>(null,"");

// calculate strenght of a minimum - strength is value between 0 and 100, higher is stronger
Tuple<double,int> MinimumStrength(double[] values)
Expand All @@ -113,7 +113,6 @@ Tuple<double,int> MinimumStrength(double[] values)
// so it is not unexpected to have a vaue on one side be quite close to the value at "minIndex"
double valBeside = Math.Max(valAbove, valBelow);
return new Tuple<double,int>(100 * (1 - val / valBeside),minIndex);
// return new Tuple<double, int>(valBeside-val, minIndex);
}

double[] Scale(double[] v_in)
Expand All @@ -129,7 +128,6 @@ double[] Scale(double[] v_in)
}
}
Vec vec = new Vec();

var v1 = uPidVarianceList.ToArray();
var v2 = covBtwDestAndYsetList.ToArray();
var v3 = covBtwDestAndUexternal.ToArray();
Expand All @@ -152,19 +150,17 @@ double[] Scale(double[] v_in)
if (v4_Strength > 0)
{
var unitPara = unitParametersList.ElementAt(min_ind_v4);
// unitPara.Fitting = new FittingInfo();
// unitPara.Fitting.SolverID = "ClosedLoopId (global-search:v4)";
return new Tuple<UnitModel, bool>(new UnitModel(unitPara), true);
return new Tuple<UnitModel, string>(new UnitModel(unitPara), "v4");
}
else
{
return new Tuple<UnitModel, bool>(null, false);
return new Tuple<UnitModel, string>(null, "");
}
//modelParameters.AddWarning(UnitdentWarnings.ClosedLoopEst_GlobalSearchFailedToFindLocalMinima);

}
double[] objFun = v1;
// string vString = "v1";
var retString = "v1";

if (v1_Strength < v1_Strength_Threshold)
{
Expand All @@ -177,24 +173,22 @@ double[] Scale(double[] v_in)
// var v3 = linregGainYsetToDestList.ToArray();
// var v3_scaled = vec.Div(vec.Subtract(v3, vec.Min(v3)), vec.Max(v3) - vec.Min(v3));
objFun = vec.Add(objFun, vec.Multiply(v2_scaled, v2_factor));
// vString = "v2";
retString = "v2";
}

// if the system has external inputs, and they change in value
if (!Vec.IsAllValue(v3, 0))
{
var v3_scaled = Scale(v3);
objFun = vec.Add(objFun, vec.Multiply(v3_scaled, v3_factor));
// vString = "v3";
retString = "v3";
}
}

vec.Min(objFun, out min_ind);
var unitParams = unitParametersList.ElementAt(min_ind);
// unitParams.Fitting = new FittingInfo();
// unitParams.Fitting.SolverID = "ClosedLoopId (global-search:" + vString + ")";

return new Tuple<UnitModel, bool>(new UnitModel(unitParams), true);
return new Tuple<UnitModel, string>(new UnitModel(unitParams), retString);
}
}
}
19 changes: 15 additions & 4 deletions Dynamic/Identification/ClosedLoopUnitIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
var dataSetRun2 = new UnitDataSet(dataSet);
var fittingSpecs = new FittingSpecs();
fittingSpecs.u0 = u0;

var GSdescription = "";

{
// ----------------
// run1: no process model assumed, let disturbance estimator guesstimate a pid-process gain,
Expand Down Expand Up @@ -170,9 +173,16 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
unitModel_step1, pidProcessInputInitalGainEstimate,
min_gain, max_gain, fittingSpecs, firstPassNumIterations);
var bestUnitModel = retGlobalSearch1.Item1;

if (bestUnitModel != null)
{
GSdescription = bestUnitModel.GetModelParameters().Fitting.SolverID;
wasGainGlobalSearchDone = true;
}
if (doConsoleDebugOut && retGlobalSearch1.Item1 != null)
{

Console.WriteLine("Step2,GS1: " + retGlobalSearch1.Item1.GetModelParameters().LinearGains.First().ToString("F3", CultureInfo.InvariantCulture));
}
else
Console.WriteLine("Step2,GS1: FAILED");

Expand All @@ -188,7 +198,7 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters
retGlobalSearch1.Item1, gainPass1, gainPass1 - retGlobalSearch1.Item2 * WIDTH_OF_SEARCH_PASS2, gainPass1 + retGlobalSearch1.Item2 * WIDTH_OF_SEARCH_PASS2,
fittingSpecs, secondPassNumIterations);
bestUnitModel = retGlobalSearch2.Item1;
wasGainGlobalSearchDone = true;

if (doConsoleDebugOut)
Console.WriteLine("Step2,GS2: " + retGlobalSearch2.Item1.GetModelParameters().LinearGains.First().ToString("F3", CultureInfo.InvariantCulture));
}
Expand Down Expand Up @@ -425,7 +435,7 @@ public static (UnitModel, double[]) Identify(UnitDataSet dataSet, PidParameters

if (wasGainGlobalSearchDone)
{
identUnitModel.modelParameters.Fitting.SolverID = "ClosedLoop/w gain global search/2 step";
identUnitModel.modelParameters.Fitting.SolverID = "ClosedLoop/w gain global search "+ GSdescription;
}
else
identUnitModel.modelParameters.Fitting.SolverID = "ClosedLoop local (NO global search)";
Expand Down Expand Up @@ -803,7 +813,7 @@ double Range(double[] inSignal)


// finally, select the best model from all the tested models by looking across all the kpis stored
(UnitModel bestUnitModel,bool didFindMimimum) = searchResults.GetBestModel(pidProcessInputInitalGainEstimate);
(UnitModel bestUnitModel,string gsMiniumType) = searchResults.GetBestModel(pidProcessInputInitalGainEstimate);
if (bestUnitModel != null)
{
if (bestUnitModel.modelParameters != null)
Expand All @@ -820,6 +830,7 @@ double Range(double[] inSignal)
if (bestUnitModel.modelParameters.Fitting == null)
bestUnitModel.modelParameters.Fitting = new FittingInfo();
bestUnitModel.modelParameters.Fitting.WasAbleToIdentify = true;
bestUnitModel.modelParameters.Fitting.SolverID = gsMiniumType;
}
return new Tuple<UnitModel,double>(bestUnitModel, gainStepSize);
}
Expand Down
1 change: 0 additions & 1 deletion Dynamic/Identification/DisturbanceIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ public static DisturbanceIdResult CalculateDisturbanceVector(UnitDataSet unitDat
}
}


double[] d_LF = vec.Multiply(vec.Subtract(y_sim, y_sim[indexOfFirstGoodValue]), -1);
double[] d_HF = vec.Subtract(unitDataSet_adjusted.Y_meas, unitDataSet_adjusted.Y_setpoint);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public void StaticMISO_SetpointChanges_WITH_disturbance_detectsProcessOk(int pid
// be aware that adding any sort of dynamics to the "true" model here seems to destroy the
// model estimate.
[TestCase(0, false)]
[TestCase(0, true, Category = "NotWorking_AcceptanceTest")]
[TestCase(0, true)]
[TestCase(1, false)]
public void StaticMISO_externalUchanges_NOsetpointChange_detectsProcessOk(int pidInputIdx, bool doNegative)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,19 @@ public void SinusDisturbanceANDSetpointStep(double distSinusAmplitude, double ys
public void SinusDisturbance(double distSinusAmplitude)
{
double precisionPrc = 20;

bool doAddBadData = false;
var trueDisturbance = TimeSeriesCreator.Sinus(distSinusAmplitude, N / 8, timeBase_s, N);
var yset = TimeSeriesCreator.Step(N / 2, N, 50, 50 );
CluiCommonTests.GenericDisturbanceTest(new UnitModel(modelParameters, "Process"), trueDisturbance,
false, true, yset, precisionPrc,isStatic);
false, true, yset, precisionPrc,doAddBadData,isStatic);
}


// 0.25: saturates the controller
[TestCase(0.5, 0.1,20, Category = "NotWorking_AcceptanceTest")]
[TestCase(0.5, 1, 20, Category = "NotWorking_AcceptanceTest")]
[TestCase(1, 0.1, 20, Category = "NotWorking_AcceptanceTest")]
[TestCase(1, 1, 20, Category = "NotWorking_AcceptanceTest")]
[TestCase(1, 0.1, 20)]
[TestCase(1, 1, 20)]
[TestCase(2, 0.1, 20)]
[TestCase(2, 1, 20)]
// gain of 5 starts giving huge oscillations...
Expand Down

0 comments on commit b4e20da

Please sign in to comment.