Skip to content

Commit e3f81a1

Browse files
committed
Send logging to Matlab console.
1 parent 077e835 commit e3f81a1

File tree

2 files changed

+94
-58
lines changed

2 files changed

+94
-58
lines changed

matlab/JSBSim_SFunction.cpp

Lines changed: 93 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -29,92 +29,92 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929
/* JSBSIm SFunction 2021-07-08
3030
*
3131
* Several changes have been made to integrate Simulink with JSBSim Version 1.1.6
32-
* For the original code, see
32+
* For the original code, see
3333
* https://se.mathworks.com/matlabcentral/fileexchange/25042-jsbsim-s-function-gui-0-3
34-
* and
34+
* and
3535
* https://github.com/podhrmic/JSBSim-Matlab
36-
* A big thanks to Michal Podhradsky for the work done.
36+
* A big thanks to Michal Podhradsky for the work done.
3737
*
38-
* SFunction block parameters are changed to:
39-
* 'ac_name_string', [u-fps v-fps w-fps p-radsec q-radsec r-radsec h-sl-ft long-gc-deg lat-gc-deg
38+
* SFunction block parameters are changed to:
39+
* 'ac_name_string', [u-fps v-fps w-fps p-radsec q-radsec r-radsec h-sl-ft long-gc-deg lat-gc-deg
4040
* phi-rad theta-rad psi-rad],
4141
* [throttle-cmd-norm aileron-cmd-norm elevator-cmd-norm rudder-cmd-norm mixture-cmd-norm set-running flaps-cmd-norm gear-cmd-norm],
4242
* [delta_T], 'script/scriptname'
43-
*
43+
*
4444
* This means it is now possible to define a script as usual in JSBSim. If
45-
* a valid script name is not defined, Simulink will try to load the specified
46-
* aircraft and run the script using the input parameters.
45+
* a valid script name is not defined, Simulink will try to load the specified
46+
* aircraft and run the script using the input parameters.
4747
*
4848
* Input parameters: [throttle, aileron, elevator, rudder, mixture, set-running, flaps and gear]
4949
*
50-
* Output parameters have been updated, there are 4 output ports.
50+
* Output parameters have been updated, there are 4 output ports.
5151
* 0 (states): [u-fps v-fps w-fps p-rad-sec q-rad-sec r-rad-sec h-sl-ft long-deg lat-deg phi-rad theta-rad psi-rad]
52-
* 1 (Flight controls): [thr-pos-norm left-ail-pos-rad right-ail-pos-rad el-pos-rad rud-pos-rad flap-pos-norm
53-
* speedbrake-pos-rad spoiler-pos-rad gear-pos-norm]
54-
* 2: (Propulsion output): Not yet defined in the SFunction. Placeholder. Needs to be engine dependent.
55-
* 3: (Pilot related output): [pilot-Nz alpha-rad alpha-dot-rad-sec beta-rad beta-dot-rad-sec vc-fps vc-kts
52+
* 1 (Flight controls): [thr-pos-norm left-ail-pos-rad right-ail-pos-rad el-pos-rad rud-pos-rad flap-pos-norm
53+
* speedbrake-pos-rad spoiler-pos-rad gear-pos-norm]
54+
* 2: (Propulsion output): Not yet defined in the SFunction. Placeholder. Needs to be engine dependent.
55+
* 3: (Pilot related output): [pilot-Nz alpha-rad alpha-dot-rad-sec beta-rad beta-dot-rad-sec vc-fps vc-kts
5656
* Vt-fps vg-fps mach climb-rate-fps qbar-psf]
5757
*
58-
* Verbosity settings and JSBSim Multiplier have been removed.
59-
*
60-
* It is currently needed to run the clearSF.m function in the command window
61-
* in matlab before each simulation. This should be fixed.
58+
* Verbosity settings and JSBSim Multiplier have been removed.
59+
*
60+
* It is currently needed to run the clearSF.m function in the command window
61+
* in matlab before each simulation. This should be fixed.
6262
*
6363
* 2021-07-08 Tilda Sikström
64-
* Linköping, Sweden
64+
* Linköping, Sweden
65+
*
6566
*
66-
*
6767
* ***********************************************************************************************
6868
* **************************************************************************************************
6969
* Bug fixes
7070
* %%% Fixed issues with Debug Verbosity settings
7171
* %%% Fixed problem with "verbose" Verbosity setting that did not allow simulation to run properly
72-
* %%% Fixed issue with throttles not being initialized properly and angines not being properly spooled up to the
72+
* %%% Fixed issue with throttles not being initialized properly and angines not being properly spooled up to the
7373
* intended power setting
7474
*
7575
* 01/22/10 Brian Mills
76-
*
76+
*
7777
* *********Discrete States Version******************************************************************
7878
* JSBSim calculates states. NO integration performed by Simulink.
7979
* Use fixed step discrete state solver
8080
* Basic implementation of a JSBSim S-Function that takes 5 input parameters
8181
* at the S-Function's block parameters dialog box:
82-
* 'ac_name_string',
83-
* [u-fps v-fps w-fps p-radsec q-radsec r-radsec h-sl-ft long-gc-deg lat-gc-deg
82+
* 'ac_name_string',
83+
* [u-fps v-fps w-fps p-radsec q-radsec r-radsec h-sl-ft long-gc-deg lat-gc-deg
8484
* phi-rad theta-rad psi-rad],
8585
* [throttle-cmd-norm aileron-cmd-norm elevator-cmd-norm rudder-cmd-norm mixture-cmd-norm set-running flaps-cmd-norm gear-cmd-norm],
8686
* [delta_T], 'script/scriptname'
8787
* The model currently takes 8 control inputs:throttle, aileron, elevator, rudder, mixture, set-running, flaps and gear.
88-
* The model has 12 states:[u-fps v-fps w-fps p-rad-sec q-rad-sec r-rad-sec h-sl-ft long-deg lat-deg phi-rad theta-rad psi-rad]
88+
* The model has 12 states:[u-fps v-fps w-fps p-rad-sec q-rad-sec r-rad-sec h-sl-ft long-deg lat-deg phi-rad theta-rad psi-rad]
8989
* Model has 4 output ports: state vector, control output vector, propulsion output vector and calculated output vector.
90-
* States output [u-fps v-fps w-fps p-rad-sec q-rad-sec r-rad-sec h-sl-ft long-deg lat-deg phi-rad theta-rad psi-rad]
91-
* Flight Controls output [thr-pos-norm left-ail-pos-rad right-ail-pos-rad el-pos-rad rud-pos-rad flap-pos-norm
90+
* States output [u-fps v-fps w-fps p-rad-sec q-rad-sec r-rad-sec h-sl-ft long-deg lat-deg phi-rad theta-rad psi-rad]
91+
* Flight Controls output [thr-pos-norm left-ail-pos-rad right-ail-pos-rad el-pos-rad rud-pos-rad flap-pos-norm
9292
speedbrake-pos-rad spoiler-pos-rad gear-pos-norm]
93-
* Propulsion output piston (per engine) [prop-rpm prop-thrust-lbs mixture fuel-flow-gph advance-ratio power-hp pt-lbs_sqft
93+
* Propulsion output piston (per engine) [prop-rpm prop-thrust-lbs mixture fuel-flow-gph advance-ratio power-hp pt-lbs_sqft
9494
* volumetric-efficiency bsfc-lbs_hphr prop-torque blade-angle prop-pitch]
95-
* Propulsion output turbine (per engine) [thrust-lbs n1 n2 fuel-flow-pph fuel-flow-pps pt-lbs_sqft pitch-rad reverser-rad yaw-rad inject-cmd
95+
* Propulsion output turbine (per engine) [thrust-lbs n1 n2 fuel-flow-pph fuel-flow-pps pt-lbs_sqft pitch-rad reverser-rad yaw-rad inject-cmd
9696
* set-running fuel-dump]
97-
* Calculated outputs [pilot-Nz alpha-rad alpha-dot-rad-sec beta-rad beta-dot-rad-sec vc-fps vc-kts
97+
* Calculated outputs [pilot-Nz alpha-rad alpha-dot-rad-sec beta-rad beta-dot-rad-sec vc-fps vc-kts
9898
* Vt-fps vg-fps mach climb-rate-fps]
9999
*
100100
* The UpdateStates method added to JSBSimInterface is called for every s-function simulation time step.
101-
* Currently it is advised that if the AC model FCS has integrators, then after each simulation run "clearSF"
101+
* Currently it is advised that if the AC model FCS has integrators, then after each simulation run "clearSF"
102102
* should be entered at the Matlab command line to reset the simulation.
103-
* This will ensure that every consecutive simulation run starts from the same initial states.
103+
* This will ensure that every consecutive simulation run starts from the same initial states.
104104
* It is planned to fix this in the near future.
105105
* Please look in the mdlInitializeSizes method for more detailed input port and output port details.
106106
* *************************************************************************************************************************
107107
* *************************************************************************************************************************
108108
* 08/08/09 JSBSimSFunction revision 1.0 for campatibility with JSBSim 1.0
109109
* Brian Mills
110110
* *************************************************************************************************************************
111-
* JSBSimInterface written by Agostino De Marco for use in the JSBSimMexFunction project. Additional functions have been added and changes
111+
* JSBSimInterface written by Agostino De Marco for use in the JSBSimMexFunction project. Additional functions have been added and changes
112112
* made to work with SFunction API. Thanks to Agostino for providing the basis for this project.
113113
* *************************************************************************************************************************
114114
115115
*/
116116
#ifdef __cplusplus
117-
117+
118118
#endif // defined within this scope
119119
#define S_FUNCTION_NAME JSBSim_SFunction
120120
#define S_FUNCTION_LEVEL 2
@@ -184,7 +184,7 @@ std::string getMxArrayString(const mxArray* mxArrayStr) {
184184

185185
mwSize strLen = mxGetNumberOfElements(mxArrayStr) + 1;
186186
char* strBuf = (char*) malloc(strLen * sizeof(char));
187-
mxGetString(mxArrayStr, strBuf, strLen);
187+
mxGetString(mxArrayStr, strBuf, strLen);
188188
std::string str = std::string(strBuf);
189189
free(strBuf);
190190
return str;
@@ -214,6 +214,41 @@ std::string getMxArrayString(const mxArray* mxArrayStr) {
214214
* See matlabroot/simulink/src/sfuntmpl_doc.c for more details.
215215
*/
216216

217+
class LogMatlab : public FGLogConsole
218+
{
219+
public:
220+
LogMatlab(SimStruct *s) : S(s) {}
221+
void Format(LogFormat format) override {} // Ignore text formatting.
222+
void Flush(void) override {
223+
static char error_msg[1024];
224+
std::string message = buffer.str();
225+
switch (log_level) {
226+
case LogLevel::BULK:
227+
case LogLevel::DEBUG:
228+
case LogLevel::INFO:
229+
case LogLevel::STDOUT:
230+
mexPrintf("JSBSim: %s", message.c_str());
231+
break;
232+
case LogLevel::WARN:
233+
mexWarnMsgIdAndTxt("JSBSim:Warning", message.c_str());
234+
break;
235+
case LogLevel::ERROR:
236+
case LogLevel::FATAL:
237+
{
238+
snprintf(error_msg, sizeof(error_msg), "%s", message.c_str());
239+
ssSetErrorStatus(S, error_msg);
240+
break;
241+
}
242+
default:
243+
break;
244+
}
245+
buffer.str("");
246+
}
247+
private:
248+
SimStruct *S;
249+
};
250+
251+
217252
/*====================*
218253
* S-function methods *
219254
*====================*/
@@ -227,32 +262,32 @@ static void mdlCheckParameters(SimStruct *S)
227262
ssSetErrorStatus(S,"JSBSim S-function must have 6 parameters.");
228263
return;
229264
}
230-
265+
231266
if (!mxIsChar(ac_name)) {
232267
ssSetErrorStatus(S, "Parameter 1 to JSBSim S-function must be a string.");
233268
return;
234269
}
235-
270+
236271
if (!mxIsNumeric(ssGetSFcnParam(S, TIME_STEP_PARAM)) || delta_t < 0) {
237272
ssSetErrorStatus(S, "Parameter 2 to JSBSim S-function must be a nonnegative number.");
238273
return;
239274
}
240-
275+
241276
if (!mxIsNumeric(ssGetSFcnParam(S, USE_SCRIPT_PARAM)) || !(use_script == 1 || use_script == 0)) {
242277
ssSetErrorStatus(S, "Parameter 3 to JSBSim S-function must be either 0 (disabled) or 1 (enabled).");
243-
return;
278+
return;
244279
}
245-
280+
246281
if (!mxIsChar(script_name)) {
247282
ssSetErrorStatus(S, "Parameter 4 to JSBSim S-function must be a string.");
248283
return;
249284
}
250-
285+
251286
if (!mxIsChar(reset_name)) {
252287
ssSetErrorStatus(S, "Parameter 5 to JSBSim S-function must be a string.");
253288
return;
254289
}
255-
290+
256291
if (!mxIsChar(io_config_file_name)) {
257292
ssSetErrorStatus(S, "Parameter 6 to JSBSim S-function must be a string.");
258293
return;
@@ -316,7 +351,7 @@ static void mdlProcessParameters(SimStruct *S)
316351

317352
// Configure the output port(s).
318353
if (!ssSetNumOutputPorts(S, numOutputs)) return;
319-
354+
320355
int i;
321356
Element* outputElement = outputsElement->FindElement("output");
322357
int outputSize;
@@ -329,7 +364,7 @@ static void mdlProcessParameters(SimStruct *S)
329364
// to set the name.
330365

331366
outputElement = outputsElement->FindNextElement("output");
332-
}
367+
}
333368
}
334369
#endif /* MDL_PROCESS_PARAMETERS */
335370

@@ -342,7 +377,7 @@ static void mdlInitializeSizes(SimStruct *S)
342377
{
343378

344379
/* See sfuntmpl_doc.c for more details on the macros below */
345-
ssSetNumSFcnParams(S, NUM_PARAMS); /* Number of expected parameter vectors*/
380+
ssSetNumSFcnParams(S, NUM_PARAMS); /* Number of expected parameter vectors*/
346381
if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
347382
mdlCheckParameters(S);
348383
mdlProcessParameters(S);
@@ -352,7 +387,7 @@ static void mdlInitializeSizes(SimStruct *S)
352387
}
353388

354389
// Create the work vectors.
355-
if(!ssSetNumDWork( S, useWeather ? 2 + numOutputs : 1 + numOutputs)) return; //HW change
390+
if(!ssSetNumDWork( S, useWeather ? 2 + numOutputs : 1 + numOutputs)) return; //HW change
356391

357392
// Work vector for input port.
358393
ssSetDWorkWidth( S, 0, ssGetInputPortWidth(S,0));
@@ -369,7 +404,7 @@ static void mdlInitializeSizes(SimStruct *S)
369404
ssSetDWorkWidth( S, i+1, ssGetOutputPortWidth(S,i));
370405
ssSetDWorkDataType( S, i+1, SS_DOUBLE);
371406
}
372-
407+
373408
// Reserve element in the pointers vector to store the JSBSimInterface.
374409
ssSetNumPWork(S, 1);
375410

@@ -405,11 +440,12 @@ static void mdlInitializeSampleTimes(SimStruct *S)
405440
* restarts execution to reset the states.
406441
*/
407442
static void mdlInitializeConditions(SimStruct *S)
408-
{
409-
443+
{
444+
410445
mexPrintf("\nJSBSim S-Function is initializing...\n\n");
411-
446+
412447
// Create new JSBSimInterface object and initialize it with delta_t and num_outputs.
448+
SetLogger(std::make_shared<LogMatlab>(S));
413449
JSBSimInterface *JII = new JSBSimInterface(delta_t, numOutputs);
414450
ssGetPWork(S)[0] = (void *) JII;
415451

@@ -449,7 +485,7 @@ static void mdlInitializeConditions(SimStruct *S)
449485
return;
450486
}
451487
}
452-
488+
453489
// Get the user provided input/output config.
454490
std::string io_config_file = getMxArrayString(io_config_file_name);
455491

@@ -529,8 +565,8 @@ static void mdlInitializeConditions(SimStruct *S)
529565
* block.
530566
*/
531567
static void mdlOutputs(SimStruct *S, int_T tid)
532-
{
533-
568+
{
569+
534570
real_T* output;
535571
double* dWorkVector;
536572
int i;
@@ -555,8 +591,8 @@ static void mdlOutputs(SimStruct *S, int_T tid)
555591
*/
556592
static void mdlUpdate(SimStruct *S, int_T tid)
557593
{
558-
/* send update inputs to JSBSimInterface, run one cycle,
559-
retrieve state vector, and update sim state vector
594+
/* send update inputs to JSBSimInterface, run one cycle,
595+
retrieve state vector, and update sim state vector
560596
*/
561597

562598
JSBSimInterface* JII = (JSBSimInterface*) ssGetPWork(S)[0];
@@ -569,7 +605,7 @@ static void mdlUpdate(SimStruct *S, int_T tid)
569605
ctrlVec[i] = (double) *ctrlCmdInput[i];
570606
dWorkCtrlCmdIn[i] = *ctrlCmdInput[i];
571607
}
572-
608+
573609
if (!JII->CopyInputControlsToJSBSim(ctrlVec)) {
574610
ssSetErrorStatus(S, "Issue copying control inputs to JSBSim.\n");
575611
return;
@@ -591,7 +627,7 @@ static void mdlUpdate(SimStruct *S, int_T tid)
591627
}
592628

593629
JII->Update();
594-
630+
595631
double *dWorkVector;
596632
for (i = 0; i < numOutputs; i++) {
597633
dWorkVector = (double *) ssGetDWork(S,i+1);
@@ -608,7 +644,7 @@ static void mdlUpdate(SimStruct *S, int_T tid)
608644
*/
609645
static void mdlTerminate(SimStruct *S)
610646
{
611-
647+
612648
JSBSimInterface *JII = (JSBSimInterface *) ssGetPWork(S)[0];
613649
delete JII;
614650

src/input_output/FGLog.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class JSBSIM_API FGLogConsole : public FGLogger
162162
void Flush(void) override;
163163
~FGLogConsole() override { Flush(); }
164164

165-
private:
165+
protected:
166166
std::string buffer;
167167
LogLevel min_level = LogLevel::BULK;
168168
};

0 commit comments

Comments
 (0)