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 };