function [nlobj,numParas,egoParas,blkDataType,blkObsDim,blkObsMat] = ...
    vppblock_MaskInitFcn(blk,p,Ts,...
    wheelbase,egoLength,egoWidth,dist2Center,minDist,...
    obsMat,numObs,v_range,steer_range,maxiter)
% Mask initialization function for Vehicle Path Planner (VPP) block using
% multistage nonlinear MPC. 
%
% The output from the VPP block is a path of dimension (p+1)-by-3. Each row
% corresponds to the pose (x,y,yaw) of ego vehicle at k*Ts (k = 0,1,...p).
%

% Copyright 2021-2022 The MathWorks, Inc.

%%
% set block data type
blkDataType = 'double'; 
% set block ports
hasObs = (numObs>0);
updateOptionalPorts(blk,blkDataType,hasObs);
% check parameter validity
vppblock_utilParameterCheck(blk);

% set dummy block dimensions/parameters 
egoParas = zeros(1,1);
blkObsMat = zeros(1,5); 
blkObsDim = size(blkObsMat);
if strcmp(get_param(blk,'v_ext'),'on')
    v_range = zeros(1,2); 
end
if strcmp(get_param(blk,'steer_ext'),'on')
    steer_range = zeros(1,2); 
end

% set valid block dimensions/parameters
if hasObs
    blkObsDim = [numObs,5];
    egoParas = [egoLength;egoWidth;dist2Center;minDist];
end
if hasObs && strcmp(get_param(blk,'obs_ext'),'off')
    blkObsMat = obsMat;
end

% create MPC planner
obsParasNum = numObs*size(obsMat,2);
stateParameters = wheelbase;
numStateParas = numel(stateParameters);
numParas = numel(egoParas)+obsParasNum;
nlobj = vppblock_CreateNonlinearMPC(p,Ts,v_range,steer_range,...
    numStateParas,hasObs,numParas);
% use suboptimal solution for MPC
if strcmp(get_param(blk,'suboptimal'),'on')
    nlobj.Optimization.UseSuboptimalSolution = true;
    nlobj.Optimization.SolverOptions.MaxIterations = maxiter;
end



%% ========== local functions ==========

% Update mask inports/outports
function updateOptionalPorts(blk,DataType,hasObs)
% Update optional inports and outports
inport_names = {'Obstacles',...  
                'Velocity range',...
                'Steering angle range'};
outport_names = {'Exitflag'};
AvailableBlocks = get_param(blk,'Blocks');
% what exists in the block (old)
type_in_block = ismember(inport_names,AvailableBlocks);
type_out_block = ismember(outport_names,AvailableBlocks);
% what is specified in the dialog (new)
type_in_mask = [...
    strcmp(get_param(blk,'obs_ext'),'on') && hasObs, ...
    strcmp(get_param(blk,'v_ext'),'on'), ...
    strcmp(get_param(blk,'steer_ext'),'on'), ...
    ];
type_out_mask = strcmp(get_param(blk,'output_exitflag'),'on');
% Update Inport
port = 3;
port = adasblocks_utilUpdateInport(blk,'SignalSpecObs',AvailableBlocks,type_in_mask,type_in_block,1,inport_names{1},port,1,'obsMat',DataType);
port = adasblocks_utilUpdateInport(blk,'SignalSpecVel',AvailableBlocks,type_in_mask,type_in_block,2,inport_names{2},port,1,'v_range',DataType);
port = adasblocks_utilUpdateInport(blk,'SignalSpecSteer',AvailableBlocks,type_in_mask,type_in_block,3,inport_names{3},port,1,'steer_range',DataType);
nextOutport = 2;
nextOutport = adasblocks_utilUpdateOutport(blk,'PathPlanner',AvailableBlocks,type_out_mask,type_out_block,1,'Exitflag',nextOutport,2);



