2017-10-24 3 views
0

Simulink 내의 Matlab Level-2 S 함수에서 객체를 가져올 수 있는지 궁금합니다.Simulink에서 Matlab Level 2 S 함수의 Matlab 객체 가져 오기

이전에는 Matlab의 동적 모델에 강화 학습을 적용했습니다. 결과적으로 정책 생성 및 업데이트를 다루는 클래스를 만들었습니다. 이제는 더 복잡한 동적 시스템을 가지고 있으므로 Simulink로 이동해야합니다. 저는 C S- 함수에 익숙하지만, 이미 두 클래스의 Matlab 코드를 가지고 있기 때문에 이러한 객체를 사용하는 Matlab S 함수를 사용하려고 생각하고있었습니다.

내 작업 흐름은 다음과 같습니다. 정책 개체가 초기화되는 주 Matlab 함수는 동적 모델로 Simulink 파일을 호출합니다. S- 기능에서, 정책 객체는 액션 (컨트롤 시스템의 출력)을 선택하라는 호출입니다. Simulink 파일을 여러 번 시뮬레이션 한 후에 정책 객체 (실제로는 가중치)가 Matlab 함수에서 업데이트됩니다.

따라서 Simulink의 Matlab S-function에서 policy 개체를 가져 오는 방법이 필요합니다. 매개 변수로 가져 오기를 시도했지만 숫자 값만 허용됩니다. 기본 Matlab 스크립트의 가중치를 업데이트해야하기 때문에 S 함수 내에서만 객체를 유지할 수 없습니다 (따라서 초기화 함수 내에서 객체 초기화).

이것이 가능합니까? 어떤 제안이라도 대단히 감사하겠습니다! 다음과 같이

정책 클래스의 예는 다음과 같습니다

classdef Policy 
    %% Accessible properties: 
    properties 
     a;     % selected action index 
     actions;   % actions list 
     basis;    % type of basis function 
     centres;   % list of centres of the RBFs 
     exploration_rate; % exploration rate 
     mu;     % width of each RBF 
     nbasis;    % no. basis functions overall 
     states;    % list of discrete states 
     weights;   % weights of the linear function approximation 
    end 

    %% Protected properties: 
    properties (Access = protected) 
     na;     % no. actions 
     ns;     % no. discrete states 
     nrbf;    % no. radial basis functions per action 
     state;    % current state 
     Q;     % Q value for each action-state pair 
    end 

    %% Accessible methods: 
    methods %(Access = protected) 
     %% Initialization function: 
     function obj = Policy(actions,states,epsilon,basis,mu) 
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
      % Input: 
      % actions: actions list 
      % states: states list or centres of the RBFs 
      % epsilon: initial exploration rate 
      % delta: discount factor 
      % basis: type of basis functions 
      % mu:  width of each RBF 
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

      if nargin<4 
       basis = 'basis_exact'; 
      end 

      obj.actions = actions; 
      obj.states = states; 
      obj.exploration_rate = epsilon; 

      switch basis 
       case 'basis_exact' 
        obj.basis = basis; 
        obj.states = states; 
        obj.ns = size(states,1); 
       case 'basis_rbf' 
        obj.basis = basis; 
        obj.centres = states; 
        obj.mu = mu; 
        obj.nrbf = size(states,1); 
       otherwise 
        error(['Only exact and radial basis functions',... 
        'supported']); 
      end 
     end 

     %% Setter function for the features' weights: 
     function obj = set_weights(obj,weights) 
      obj.weights = weights; 
     end 

     %% Update the exploration rate with the given rate: 
     function obj = update_epsilon(obj,rate) 
      obj.exploration_rate = obj.exploration_rate*rate; 
     end 

     %% Select an action: 
     function obj = select_action(obj,state)    
      % Store the current state: 
      obj.state = state; 
      % Compute the state-action values for the current state: 
      obj = obj.qvalues(); 
      % Get the current action with an epsilon-greedy policy: 
      obj.a = obj.eGreedy(); 
     end 

     %% Evaluate the features: 
     function phi = get_features(obj,state,action) 
      % Store the current state: 
      obj.state = state; 
      % Get the features: 
      phi = feval(obj.basis,action); 
     end 
    end 

    %% Protected methods: 
    methods (Access=protected) 
     %% Find the discrete state: 
     function s = discretizeState(obj,x)    
      % Copy the row vector entries (continuous states) to all rows: 
      x = repmat(x,obj.ns,1); 
      % Select the row using the minimum Eucledian distance: 
      [~,s] = min(sum((obj.states-x).^2,2).^0.5); 
     end 

     %% Get the Q-value function for current state and action: 
     function q = qvalue(obj,action) 
      phi = feval(obj.basis,action); 
      q = phi' * obj.weights; 
     end 

     %% Get the Q-value functions for the current state: 
     function obj = qvalues(obj)    
      % Initialize the Q-values for the current state: 
      obj.Q = zeros(obj.na,1); 
      % Calculate the state-action values for the current state: 
      for a=1:obj.na 
       obj.Q(a) = obj.qvalue(a); 
      end 
     end 

     %% Get an action with an epsilon-greedy exploration policy: 
     function a = eGreedy(obj) 
      % Generate a random number: 
      r = rand; 

      % Select the action that maximises Q(s) 
      if (r>obj.exploration_rate)    
       [~,a] = max(obj.Q); % value, action 
      % Choose a random action: 
      else      
       a = randi(obj.na); % random integer based on a uniform 
      end      % distribution 
     end 

     %% Find the features for the exact basis functions: 
     function phi = basis_exact(obj,action) 
      %Initialize the features: 
      phi = zeros(obj.nbasis,1); 

      % Find the current discrete state: 
      s = discretizeState(obj.state); 

      % Find the starting position of the block: 
      base = (action-1) * obj.ns; 

      % Set the indicator: 
      phi(base+s) = 1; 
     end 

     %% Find the features for the radial basis functions: 
     function phi = basis_rbf(obj, action) 
      %Initialize the features: 
      phi = zeros(obj.nbasis,1); 

      % Find the starting position: 
      base = (action-1) * (obj.nbasis/obj.na); 
      % This is because the matrix Theta is converted into a line 
      % vector 

      % Compute the RBFs: 
      for i=1:obj.nrbf 
       phi(base+i) = exp(-norm(obj.state-obj.centres(i,:))^2/... 
        (2*obj.mu)); 
      end 
      % ... and the constant: 
      phi(base+obj.nrbf+1) = 1; 
     end 
    end 
end 
+0

MATLAB 명령 프롬프트에서'sfundemos'를 입력하십시오. 좋은 예를 찾아 볼 수 있습니다. 'msfuntmpl'과'msfuntmpl_basic'과 같은 템플릿도 있습니다. 이 둘을 입력하고 Ctrl + D를 누릅니다. 일반적으로 레벨 2 MATLAB-S-Function에서 모든 MATLAB Object를 사용할 수 있습니다. 소스 파일이 MATLAB 경로에 있는지 확인하십시오. –

+0

고맙습니다! 따라서 주 파일과 Matlab S 함수에서 동일한 Matlab 객체를 사용하려면 매개 변수로 가져올 필요가 없습니다. –

+0

이것이 까다로워지고 더 이상 확실하지 않습니다. 변수를'global'으로 선언 할 수도 있고, S-Function 내부에서'obj = evalin ('base', 'OBJ')'를 통해 기본 작업 공간에서 객체를 가져 와서 작업 할 수도 있고'assignin ('base' 'OBJ', obj)'. 이 코드가 MATLAB-Script를 가지고 있고 Simulink-Model이 메모리의 같은 개체를 참조하기에 충분한 지 모르겠습니다.시도해보십시오! ... –

답변

0

이 좋아, 일부 실험 후, 나는 마침내 가장 좋은 방법은 글로벌로 객체를 설정, 즉 전역 변수를 사용하는 것이 실제로 것으로 나타났습니다 메인 Matlab 스크립트와 레벨 2 S- 기능 모두.

여기서 간단한 예제를 볼 수 있습니다.이 예제는 작업 시간을 줄이는 데 도움이 될 것입니다.

Test.m 클래스 :

classdef Test 
    properties 
     a; 
     b; 
    end 

    methods 
     function obj = Test(a,b) 
      obj.a = a; 
      obj.b = b; 
     end 

     function obj = change_a(obj,c) 
      obj.a = obj.a + c; 
     end 

     function c = get_c(obj) 
      c = obj.a*obj.b; 
     end 
    end 
end 

홈페이지 matlab에 스크립트 - trial.m :

clear; 
close all; 

global test; 

test = Test(0,1); 

% Simulink file: 
sfile = 't1'; 
% Load the Simulink file: 
load_system(sfile); 

% Run the simulation: 
sout = sim(sfile,'StopTime','5.0'); 

% Plot data: 
t = sout.tout; 
c = sout.get('logsout').getElement('c').Values.Data; 
figure; 
plot(t,c); 

t1.slx 시뮬링크 파일 : <code>t1.slx</code> Simulink file test_class.m 레벨 2 matlab에 S-기능 :

function test_class(block) 
% rl_control.m  [email protected]  23/10/2017 
    setup(block); 
end 

%% Set up the block: 
function setup(block) 
% % Register number of dialog parameters: 
% block.NumDialogPrms = 3; 

    % Register number of input and output ports: 
    block.NumInputPorts = 1; 
    block.NumOutputPorts = 1; 

    % Set up functional port properties to dynamically inherited: 
    block.SetPreCompInpPortInfoToDynamic; 
    block.SetPreCompOutPortInfoToDynamic; 

    % Set up the input ports: 
    block.InputPort(1).Dimensions  = 1;   
    block.InputPort(1).DirectFeedthrough = true; 

    % Set up the output port: 
    block.OutputPort(1).Dimensions  = 1;   

    % Set block sample time to continuous: 
    block.SampleTimes = [0 0]; 

%  % Setup Dwork: 
%  block.NumContStates = 1; 

    % Set the block simStateCompliance to default: 
    block.SimStateCompliance = 'DefaultSimState'; 

    % Register methods: 
%  block.RegBlockMethod('InitializeConditions', @InitConditions); 
    block.RegBlockMethod('Outputs',     @Output); 
%  block.RegBlockMethod('Derivatives',    @Derivative); 
end 

% %% Initial conditions: 
% function InitConditions(block) 
%  % Initialize Dwork: 
%  block.ContStates.Data = block.DialogPrm(3).Data; 
% end 

%% Set up the output: 
function Output(block) 
    global test; 
    test = test.change_a(block.InputPort(1).Data); 
    c = test.get_c(); 
    block.OutputPort(1).Data = c; 
end 

테스트를 마쳤으며 작동하는지 확인했습니다. 전역 변수를 사용하면 같은 객체를 사용하여 원하는대로 변경할 수 있습니다.