www.gusucode.com > robotsimulink 工具箱 matlab源码程序 > robotsimulink/robotslros/+robotics/+codertarget/+internal/loadCommand.m

    function loadCommand(modelName,varargin)
%This function is for internal use only. It may be removed in the future.

%LOADCOMMAND Executes as the load command for ROS model build.
%   At this point, the source code archive and the build shell script are
%   both available.
%   The load command will copy these files to the ROS device, build the ROS
%   node there, and (optionally) run the ROS node.
%   Note that this function is not called if the user selected the 
%   "Code Generation Only" checkbox.

%   Copyright 2014-2016 The MathWorks, Inc.

expectedTargetHardware = robotics.slros.internal.Constants.TargetHardware;

% Get all config set data
data = codertarget.data.getData(getActiveConfigSet(modelName));
if ~isequal(data.TargetHardware, expectedTargetHardware)
    error(message('robotics:robotslros:deploy:UnknownTargetHardware', expectedTargetHardware, data.TargetHardware));
end

% Retrieve build action. This can either be "None", "Build and load", or "Build and run"
buildAction = data.Runtime.BuildAction;
if ~string(buildAction).startsWith('build', 'IgnoreCase', true)
    % If the user did not request a build, do not connect to the ROS
    % device. The final artifacts are the tgz and sh files.
    return;
end

% Verify connection settings
[validHost, validSSH, validUser, validPassword, validCatkin] = ...
    verifyConnectionSettings(modelName, buildAction);

% Open new stage in diagnostic viewer and close it when function exits or
% if an error occurs
buildStage = sldiagviewer.createStage(buildAction, 'ModelName', modelName);
stageCleanup = onCleanup(@() delete(buildStage));

% Load and run if necessary
disp(message('robotics:robotslros:deploy:ConnectToDevice', validHost).getString);
rosTarget = rosdevice(validHost, validUser, validPassword, validSSH);

disp(message('robotics:robotslros:deploy:UseCatkin', validCatkin).getString);
rosTarget.CatkinWorkspace = validCatkin;

disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator);

% We need to first kill any instance(s) of the ROS node with
% the same name before building. Otherwise the executable will be
% locked.
archiveName = [modelName '.tgz'];
archivePath = '..';

if isNodeRunning(rosTarget, modelName)
    disp(message('robotics:robotslros:deploy:StopRunningNode', modelName).getString);
    disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator);
    
    try
        stopNode(rosTarget, modelName);
    catch
    end
end


% 1. Transfer build script and the Simulink model to the Catkin workspace
% 2. Build Simulink node
% If the "rosTarget.CatkinWorkspace" folder contains spaces, they are
% already escaped, so I can simply concatenate it with our file names.

% Transfer build scripts 
disp(message('robotics:robotslros:deploy:TransferCode', modelName).getString);
shellScriptWildcard = 'deploy_*.sh';
backgroundScript = [rosTarget.CatkinWorkspace '/deploy_background_build.sh'];
buildScript = [rosTarget.CatkinWorkspace '/deploy_build_ros_model.sh'];

buildScripts = fullfile(toolboxdir('robotics'), 'robotsimulink',...
    'robotslros', 'src', shellScriptWildcard);
putFile(rosTarget, buildScripts, rosTarget.CatkinWorkspace);

% Make the shell scripts executable
system(rosTarget, ['chmod u+x ' rosTarget.CatkinWorkspace '/' shellScriptWildcard]);

% Transfer Simulink model
putFile(rosTarget, fullfile(archivePath, archiveName), rosTarget.CatkinWorkspace);

% Start build process and get the pid
buildLog = [rosTarget.CatkinWorkspace '/' modelName '_build.log'];
buildStat = [rosTarget.CatkinWorkspace '/' modelName '_build.stat'];

% Without redirecting stdout and stderr to /dev/null, 
% the command does not return
disp(message('robotics:robotslros:deploy:StartBuild').getString);
disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator);

pid = system(rosTarget, [backgroundScript ' ' buildScript ' ' ...
    [rosTarget.CatkinWorkspace '/' modelName] ' ' validCatkin ' &>/dev/null & echo $!']);
logSize = 0;
done = false;
while ~done
    try
        % Kill -0 checks for existence of the process ID (it does not do
        % any killing)
        system(rosTarget, ['kill -0 ' pid]);
    catch
        % The process does not exist anymore
        done = true;
    end
    
    try
        % Get the output of the buildLog (this is executed continuously)
        output = system(rosTarget, ['stat --format=%s ' buildLog]);
    catch
        % Log file is deleted
        continue;
    end
    
    % Display running log in the diagnostic viewer
    currLogSize = str2double(output);
    if ~isnan(currLogSize) && (currLogSize > logSize)
        try
            % Print out new characters output to the log file since last
            % visit
            logOut = system(rosTarget,sprintf('tail -c +%d %s',logSize,buildLog));
            logSize = logSize + numel(logOut);
            disp(logOut);
        catch
        end
    end
    
    % Update build status every second
    pause(1);
end

try 
    status = str2double(system(rosTarget,['cat ' buildStat]));
catch
    % Something went seriously wrong if the buildStat file does not exist
    status = 1;
end

% Delete the build scripts
i_systemNoEX(rosTarget, ['rm -f ' backgroundScript ' ' buildScript ' ' buildLog ' ' buildStat]);

if ~isnan(status) && (status ~= 0)
    error(message('robotics:robotslros:deploy:BuildError', modelName))
end

if ~isempty(strfind(buildAction, 'run'))
    disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator);
    disp(message('robotics:robotslros:deploy:RunNode').getString);
    
    % Run Simulink node. Set MasterURI automatically for now
    rosMasterURI = robotics.slros.internal.sim.defaultSimMasterURI(rosTarget.DeviceAddress);
    
    disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator);
    disp(message('robotics:robotslros:deploy:NodeMasterHostConnection', ...
        rosMasterURI, rosTarget.DeviceAddress).getString);
    disp(message('robotics:robotslros:deploy:UseRosdevice').getString);
    runNode(rosTarget, modelName, rosMasterURI);
end

end



function [validHost, validSSH, validUser, validPassword, validCatkin] = ...
    verifyConnectionSettings(modelName, buildAction)
%verifyConnectionSettings Verify the connection settings to the ROS device
%   Return valid settings that can be used for the actual deployment step.

% Get the latest parameters from MATLAB preferences
deviceParams = robotics.codertarget.internal.DeviceParameters;
[hostname, sshPort, username, password, ~, catkinWs, rosFolder] = deviceParams.getDeviceParameters;

% Run the diagnostics in build mode. Each high-priority warning will result
% in an error.
diag = robotics.slros.internal.diag.DeviceDiagnostics(modelName);
switch lower(buildAction)
    case 'build and load'
        diag.RunMode = 'build';
    case 'build and run'
        % The user explicitly requested to run the resulting ROS node
        diag.RunMode = 'buildrun';
    otherwise
        % By default, stick with the build mode
        diag.RunMode = 'build';
end

% Now run a loop until we have valid connection settings.
% If there are problems, display the connection dialog and let the user
% make adjustments to the settings.

notDone = true;
while notDone
    
    % Run the diagnostics
    hasError = diag.runDiagnostics(hostname, sshPort, username, password, rosFolder, catkinWs);
    if ~hasError
        % If diagnostics run without problems, get out of this loop
        break;
    end
    
    % If there are diagnostic errors, pop up the settings dialog and let
    % the user make adjustments.
    % This call is blocking until the user closes the dialog.
    userDlg = robotics.slros.internal.dlg.DeviceParameterSpecifier;
    userDlg.ModelName = modelName;
    [isAccepted, hostname, sshPort, username, password, rosFolder, catkinWs] = ...
        userDlg.openDialogAndWait;
    
    if ~isAccepted
        % If the user hit "Cancel" or closed the dialog, abort the build.
        error(message('robotics:robotslros:deploy:NoValidSettings', hostname, modelName))
    end
    
    % Retry the settings that the user made in the next loop iteration
    notDone = hasError;
end

% Initial settings have been validated. Store them.
validHost = hostname;
validSSH = sshPort;
validUser = username;
validPassword = password;
validCatkin = diag.handleSpaces(catkinWs);

end


%--------------------------------------------------------------------------
function output = i_systemNoEX(hw,cmd,varargin)
try
    output = system(hw,cmd,varargin{:});
catch
end
end