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

    function genfiles = generateAllConversionFcns(msgTypeList, model, modelTypesHdr, destDir)
%This function is for internal use only. It may be removed in the future.

%generateAllConversionFcns - Generate & save C++ code for ROS<->Bus conversions
%
%   GEN = generateAllConversionFcns(MSGLST, MODEL, HDR, DESTDIR) generates
%   and saves C++ code for converting a set of ROS message types to
%   Simulink buses and vice versa. If a ROS message type has nested
%   messages, the conversion code is generated for nested message types as
%   well. It is not necessary for the ROS message types to actually be used
%   in the model (the C++ code will be generated if they are not used).
%
%    Inputs
%      MSGLST : List of ROS message types (string or cell array of strings)
%      MODEL  : Name of Simulink model
%      HDR    : Name of C++ header file (generated by Simulink) that has
%               declarations of the Simulink Bus data types
%      DESTDIR: Directory to save the generated C++ files to.
%
%    Outputs
%      GEN    : A struct with fields 'HeaderFiles' and 'SourceFiles', which
%               are cell arrays with full pathnames of the generated files.
%
%   Example:
%     robotics.slros.internal.cgen.generateAllConversionFunctions(...
%        {'calibration_msgs/RobotMeasurement', 'std_msgs/Int64'}, ...
%        'codegentest', 'codegentest_types.h', pwd)

%   Copyright 2014-2015 The MathWorks, Inc.

validateattributes('msgTypeList', {'char', 'cell'}, {});
validateattributes('model', {'char'}, {});
validateattributes('modelTypesHdr', {'char'}, {});
validateattributes('destDir', {'char'}, {});

cgenConstants = robotics.slros.internal.cgen.Constants;
convCodeHeaderFile = cgenConstants.ConversionCode.HeaderFile;
convCodeSourceFile = cgenConstants.ConversionCode.SourceFile;
convUtilsHeaderFile = cgenConstants.PredefinedCode.ConversionUtilsHeaderFile;

msgTypeList = cellstr(msgTypeList);

% General approach
%  1) Generate the conversion functions for each message type (and its nested
%     messages). 
%  2) Ensure that the final generated C++ code has only one set of
%     conversion functions for each message type (e.g., if multiple message
%     types all have std_msgs/Header). 
%  3) Create a master set of function defintions and declarations across
%     all message  types. Each map entry is a struct with the following
%     fields: 
%       FcnSignature  - StringWriter
%       FcnBody       - StringWriter
%       CppRosClass   - string
%       SLBusName     - string

bus2cppMasterMap = []; 
cpp2busMasterMap = [];

for i=1:numel(msgTypeList)
    emptyRosMsg = rosmessage(msgTypeList{i});
    % Note that the two maps are guaranteed to have the same set of keys
    [bus2cppFcnMap, cpp2busFcnMap] = robotics.slros.internal.cgen.getBusToCppConversionFcns(emptyRosMsg, model);
    if isempty(bus2cppMasterMap)
        % initialize the master maps
        bus2cppMasterMap = bus2cppFcnMap;
        cpp2busMasterMap = cpp2busFcnMap;
    else
        % Merge the new sets into the master map.
        newKeys = keys(bus2cppFcnMap);
        for k=1:numel(newKeys)
            if ~isKey(bus2cppMasterMap, newKeys{k})
                bus2cppMasterMap(newKeys{k}) = bus2cppFcnMap(newKeys{k}); %#ok<*AGROW>
                cpp2busMasterMap(newKeys{k}) = cpp2busFcnMap(newKeys{k});
            end
        end
    end
end

if isnumeric(bus2cppMasterMap) && isempty(bus2cppMasterMap)
    % msgTypeList was empty. Set the master maps to empty as well
    bus2cppMasterMap = containers.Map;
    cpp2busMasterMap = containers.Map;
end

% Combine the generated code into a header file & a source file

hdrFileIncludesSection = StringWriter;
hdrFileFcnDeclarations = StringWriter;
srcFileFcnDefinitions = StringWriter;

hdrFileIncludesSection.addcr('#include <ros/ros.h>');

srcFileFcnDefinitions.addcr(['#include "' convCodeHeaderFile '"']);
srcFileFcnDefinitions.addcr;

keylist = keys(bus2cppMasterMap);
for i=1:numel(keylist)
    bus2cppFcnInfo = bus2cppMasterMap(keylist{i});
    cpp2busFcnInfo = cpp2busMasterMap(keylist{i});
    
    commentStr = robotics.slros.internal.cgen.Util.cleanupUnicodeAndWhitespace(...
        sprintf('Conversions between %s and %s', ...
        bus2cppFcnInfo.SLBusName, bus2cppFcnInfo.CppRosClass));
    
    % Use '//' instead of /* ... */ for the comment as the latter would 
    % require checking for, and removing, any "*/" sequences 
    srcFileFcnDefinitions.craddcr(['// ' commentStr]);
        
    if any(strcmpi(bus2cppFcnInfo.CppRosClass, {'ros::Time', 'ros::Duration'}))
        % ros::Time and ros::Duration map to ros/time.h and ros/duration.h    
        cppROSClass = lower(bus2cppFcnInfo.CppRosClass);
    else
        cppROSClass = bus2cppFcnInfo.CppRosClass;
    end    
    headerName = robotics.slros.internal.cgen.Util.rosCppClassToCppMsgHeader(cppROSClass);
    hdrFileIncludesSection.addcr(['#include <' headerName '>']);
    
    hdrFileFcnDeclarations.add( bus2cppFcnInfo.FcnSignature );
    hdrFileFcnDeclarations.addcr(';');    
    
    hdrFileFcnDeclarations.add( cpp2busFcnInfo.FcnSignature );
    hdrFileFcnDeclarations.addcr(';');
    
    hdrFileFcnDeclarations.addcr;
    
    srcFileFcnDefinitions.craddcr( bus2cppFcnInfo.FcnSignature );
    srcFileFcnDefinitions.add( bus2cppFcnInfo.FcnBody );    
    
    srcFileFcnDefinitions.craddcr( cpp2busFcnInfo.FcnSignature );
    srcFileFcnDefinitions.add( cpp2busFcnInfo.FcnBody );    
    
    srcFileFcnDefinitions.addcr;
end

if ~isempty(modelTypesHdr)
    hdrFileIncludesSection.addcr(['#include "' modelTypesHdr '"']);
end

hdrFileIncludesSection.addcr(['#include "' convUtilsHeaderFile '"']);
hdrFileIncludesSection.addcr;

headerFile = StringWriter;
headerFile.add(hdrFileIncludesSection);
headerFile.addcr;
headerFile.add(hdrFileFcnDeclarations);
robotics.slros.internal.cgen.insertHeaderGuards(headerFile, convCodeHeaderFile);

headerFileFullName = fullfile(destDir, convCodeHeaderFile);
headerFile.write(headerFileFullName);

sourceFileFullName = fullfile(destDir, convCodeSourceFile);
srcFileFcnDefinitions.write(sourceFileFullName);

genfiles.HeaderFiles = { convCodeHeaderFile };
genfiles.SourceFiles = { convCodeSourceFile };