www.pudn.com > truetime-1.2-compiled.zip > callblocksystem.cpp


#ifndef CALL_BLOCK_SYSTEM
#define CALL_BLOCK_SYSTEM

#include "getnode.cpp"

void ttCallBlockSystem(int nOutp, double *outp, int nInp, double *inp, char *blockName) {
  
  mxArray *simsetRHS[8];
  mxArray *simRHS[4];
  mxArray *simLHS[3];
  mxArray *options[1];
  mxArray *states;
  double *values;
  double *state_values;
  int i, j, n;

  DataNode* dn;
  Blockdata *bd;

  // Make sure that the Simulink block exists in Matlab path
  mxArray *lhs[1];
  mxArray *rhs[1];
  rhs[0] = mxCreateString(blockName);
  mexCallMATLAB(1, lhs, 1, rhs, "exist");
  int number = (int) *mxGetPr(lhs[0]);
  if (number == 0) {
    MEX_ERROR("ttCallBlockSystem: Simulink block not in path!");
    for (j=0; j < nOutp; j++) {
      outp[j] = 0.0;
    }
    return;
  }

  Task* task = rtsys->running;
  dn = (DataNode*) getNode(blockName, task->blockList);

  if (dn==NULL) {
    // Not found, create options mxArray (Matlab struct) 

    bd = new Blockdata(blockName);
    
    simsetRHS[0] = mxCreateString("Solver");
    simsetRHS[1] = mxCreateString("FixedStepDiscrete");
    simsetRHS[2] = mxCreateString("FixedStep");
    simsetRHS[3] = mxCreateScalarDouble(1.0);
    simsetRHS[4] = mxCreateString("MaxDataPoints");
    simsetRHS[5] = mxCreateScalarDouble(2.0);
    simsetRHS[6] = mxCreateString("OutputVariables");
    simsetRHS[7] = mxCreateString("xy");
    
    mexCallMATLAB(1, options, 8, simsetRHS, "simset");
    
    bd->options = options[0];
    mexMakeArrayPersistent(bd->options);
    
    for (i=0; i<8; i++) {
      mxDestroyArray(simsetRHS[i]);
    }
    task->blockList->appendNode(new DataNode(bd, bd->blockName));
  } else {
    bd = (Blockdata*) dn->data;
  }

  // [t,x,outp] = sim(blockName,1,options,[0 inp]) 

  simRHS[0] = mxCreateString(blockName);
  simRHS[1] = mxCreateScalarDouble(1.0);
  simRHS[2] = bd->options;
  simRHS[3] = mxCreateDoubleMatrix(1, nInp+1, mxREAL);
  values = mxGetPr(simRHS[3]);
  values[0] = 0.0;
  for (j=0; j < nInp; j++) {
    values[j+1] = inp[j];
  }

  i = mexCallMATLAB(3, simLHS, 4, simRHS, "sim");

  mxDestroyArray(simRHS[0]);
  mxDestroyArray(simRHS[1]);
  mxDestroyArray(simRHS[3]);

  if (i==0) { // Successful
    // Update options mxArray with last row of returned state matrix 
    n = mxGetN(simLHS[1]); // Number of cols of state matrix 
    
    states = mxCreateDoubleMatrix(1, n, mxREAL);

    values = mxGetPr(simLHS[1]);
    state_values = mxGetPr(states);
    
    // Transfer values 
    for (j=0; j < n; j++) {
      state_values[j] = values[2*j+1]; // second row elements
    }

    mxArray* oldstates = mxGetField(bd->options, 0, "InitialState");
    mxDestroyArray(oldstates);
    mxSetField(bd->options, 0, "InitialState", states);
    
    // Return the output of the simulation, first row of returned output matrix 
    values = mxGetPr(simLHS[2]);
    for (j=0; j < nOutp; j++) {
      outp[j] = values[2*j];          // first row elements
    }

    mxDestroyArray(simLHS[0]);
    mxDestroyArray(simLHS[1]);
    mxDestroyArray(simLHS[2]);

  } else {

    MEX_ERROR("ttCallBlockSystem: Simulation failed!");
    for (j=0; j < nOutp; j++) {
      outp[j] = 0.0;
    }
  }
}

#endif