コード例 #1
0
        public void WrapActionSections(string type)
        {
            string wrapperName = inFileName + "Action" + type + MsgAutoGenUtilities.ActionClassSuffix;
            string msgName     = inFileName + type + MsgAutoGenUtilities.ActionClassSuffix;

            string outPath = Path.Combine(this.outPath, wrapperName + ".cs");

            string imports =
                "using System.Collections.Generic;\n" +
                "using Unity.Robotics.ROSTCPConnector.MessageGeneration;\n" +
                "using RosMessageTypes.Std;\n" +
                "using RosMessageTypes.Actionlib;\n\n";

            symbolTable = new Dictionary <string, string>();

            using (StreamWriter writer = new StreamWriter(outPath, false))
            {
                // Write imports
                writer.Write(imports);

                // Write namespace
                writer.Write(
                    "namespace RosMessageTypes." + MsgAutoGenUtilities.ResolvePackageName(rosPackageName) + "\n" +
                    "{\n"
                    );

                // Write class declaration
                writer.Write(
                    ONE_TAB + "public class " + wrapperName + " : Action" + type + "<" + msgName + ">\n" +
                    ONE_TAB + "{\n"
                    );

                // Write ROS package name
                writer.Write(
                    TWO_TABS + "public const string k_RosMessageName = \"" + rosPackageName + "/" + inFileName + "Action" + type + "\";\n" +
                    TWO_TABS + "public override string RosMessageName => k_RosMessageName;\n\n"
                    );

                // Record goal/result/feedback declaration
                symbolTable.Add(MsgAutoGenUtilities.LowerFirstLetter(type), msgName);

                writer.Write("\n");

                // Write default value constructor
                writer.Write(GenerateDefaultValueConstructor(wrapperName) + "\n");

                // Write parameterized constructor
                writer.Write(GenerateParameterizedConstructor(wrapperName, type));

                writer.Write(GenerateDeserializerConstructor(wrapperName));

                writer.Write(GenerateSerializationStatements(type));

                // Close class
                writer.Write(ONE_TAB + "}\n");
                // Close namespace
                writer.Write("}\n");
            }
        }
コード例 #2
0
        public static List <string> GenerateSingleAction(string inPath, string outPath, string rosPackageName = "", bool verbose = false)
        {
            // If no ROS package name is provided, extract from path
            if (rosPackageName.Equals(""))
            {
                string[] hierarchy = inPath.Split(new char[] { '/', '\\' });
                rosPackageName = hierarchy[hierarchy.Length - 3];
            }

            outPath = Path.Combine(outPath, MsgAutoGenUtilities.ResolvePackageName(rosPackageName));

            string inFileName = Path.GetFileNameWithoutExtension(inPath);

            if (verbose)
            {
                Console.WriteLine("Parsing: " + inPath);
                Console.WriteLine("Output Location: " + outPath);
            }

            MessageTokenizer            tokenizer     = new MessageTokenizer(inPath, new HashSet <string>(MsgAutoGenUtilities.builtInTypesMapping.Keys));
            List <List <MessageToken> > listsOfTokens = tokenizer.Tokenize();

            if (listsOfTokens.Count != 3)
            {
                throw new MessageParserException("Unexpected number of sections. Action should have 3 sections.");
            }

            List <string> warnings = new List <string>();

            ActionWrapper actionWrapper = new ActionWrapper(inPath, rosPackageName, outPath);

            for (int i = 0; i < listsOfTokens.Count; i++)
            {
                List <MessageToken> tokens = listsOfTokens[i];

                // Action is made up of goal, result, feedback
                string className = inFileName + types[i];

                // Parse and generate goal, result, feedback messages
                MessageParser parser = new MessageParser(tokens, outPath, rosPackageName, "action", MsgAutoGenUtilities.builtInTypesMapping, MsgAutoGenUtilities.builtInTypesDefaultInitialValues, MsgAutoGenUtilities.numericTypeDeserializationFunctions, MsgAutoGenUtilities.numericTypeByteSize, className);
                parser.Parse();
                warnings.AddRange(parser.GetWarnings());

                // Generate action section wrapper messages
                actionWrapper.WrapActionSections(types[i]);
            }

            // Generate action wrapper
            actionWrapper.WrapAction();

            return(warnings);
        }
コード例 #3
0
        public static List <string> GenerateSingleService(string inPath, string outPath, string rosPackageName = "", bool verbose = false)
        {
            // If no ROS package name is provided, extract from path
            if (rosPackageName.Equals(""))
            {
                string[] hierarchy = inPath.Split(new char[] { '/', '\\' });
                rosPackageName = hierarchy[hierarchy.Length - 3];
            }

            outPath = Path.Combine(outPath, MsgAutoGenUtilities.ResolvePackageName(rosPackageName));

            string inFileName = Path.GetFileNameWithoutExtension(inPath);

            if (verbose)
            {
                Console.WriteLine("Parsing: " + inPath);
                Console.WriteLine("Output Location: " + outPath);
            }

            MessageTokenizer            tokenizer     = new MessageTokenizer(inPath, new HashSet <string>(MsgAutoGenUtilities.builtInTypesMapping.Keys));
            List <List <MessageToken> > listsOfTokens = tokenizer.Tokenize();

            if (listsOfTokens.Count != 2)
            {
                throw new MessageParserException("Unexpected number of sections. Service should have 2 sections.");
            }

            List <string> warnings = new List <string>();

            for (int i = 0; i < listsOfTokens.Count; i++)
            {
                List <MessageToken> tokens = listsOfTokens[i];

                // Service is made up of request and response
                string className = inFileName + MsgAutoGenUtilities.ServiceClassSuffix + types[i];

                MessageParser parser = new MessageParser(
                    tokens,
                    outPath,
                    rosPackageName,
                    "srv",
                    MsgAutoGenUtilities.builtInTypesMapping,
                    MsgAutoGenUtilities.builtInTypesDefaultInitialValues,
                    className,
                    subtopic: i == 0 ? MessageSubtopic.Default : MessageSubtopic.Response);
                parser.Parse();
                warnings.AddRange(parser.GetWarnings());
            }
            return(warnings);
        }
コード例 #4
0
        public MessageParser(List <MessageToken> tokens, string outPath, string rosPackageName, string type, Dictionary <string, string> builtInTypeMapping, Dictionary <string, string> builtInTypesDefaultInitialValues, string className = "", string rosMsgName = "", MessageSubtopic subtopic = MessageSubtopic.Default)
        {
            this.tokens = tokens;

            this.inFilePath = tokens[0].content;
            this.inFileName = Path.GetFileNameWithoutExtension(inFilePath);

            this.rosPackageName      = rosPackageName;
            this.rosPackageNamespace = MsgAutoGenUtilities.ResolvePackageName(rosPackageName);

            this.subtopic = subtopic;

            if (className.Equals(""))
            {
                this.className = MsgAutoGenUtilities.CapitalizeFirstLetter(inFileName) + MsgAutoGenUtilities.MessageClassSuffix;
            }
            else
            {
                this.className = className;
            }

            if (rosMsgName.Equals(""))
            {
                if (Char.IsLower(inFileName[0]))
                {
                    Debug.LogWarningFormat("File {0} starts with a lowercase character. Message file names should be PascalCased (see : http://wiki.ros.org/ROS/Patterns/Conventions#line-38)", inFileName);
                }
                this.rosMsgName = inFileName;
            }
            else
            {
                this.rosMsgName = rosMsgName;
            }


            this.outPath     = outPath;
            this.outFilePath = Path.Combine(outPath, type);

            this.tokens.RemoveAt(0);

            this.builtInTypeMapping = builtInTypeMapping;
            this.builtInTypesDefaultInitialValues = builtInTypesDefaultInitialValues;
        }
コード例 #5
0
        // Declaration -> BuiltInType Identifier | BuiltInType Identifier ConstantDeclaration | BuiltInType ArrayDeclaration Identifier
        // Declaration -> DefinedType Identifier | DefinedType ArrayDeclaration Identifier
        // Declaration -> Header Identifier
        private void Declaration()
        {
            string declaration = "";
            // Type
            MessageToken peeked           = Peek();
            string       type             = "";
            bool         canHaveConstDecl = false;

            declaration += MsgAutoGenUtilities.TWO_TABS + "public ";
            if (PeekType(MessageTokenType.BuiltInType))
            {
                type = builtInTypeMapping[MatchByType(MessageTokenType.BuiltInType)];
                if (type == "TimeMsg" || type == "DurationMsg")
                {
                    // Need to import BuiltinInterfaces
                    imports.Add("BuiltinInterfaces");
                }
                else
                {
                    // Time and Duration can't have constant declaration
                    // See <wiki.ros.org/msg>
                    canHaveConstDecl = true;
                }
            }
            else if (PeekType(MessageTokenType.DefinedType))
            {
                type = MatchByType(MessageTokenType.DefinedType);
                string[] hierarchy = type.Split(new char[] { '/', '\\' });
                // Assume type can only be either:
                // Type
                // package/Type
                switch (hierarchy.Length)
                {
                case 1:
                    type = type + MsgAutoGenUtilities.MessageClassSuffix;
                    break;

                case 2:
                    if (hierarchy[0].Equals("") || hierarchy[1].Equals(""))
                    {
                        throw new MessageParserException(
                                  "Invalid field type '" + type + "'. + " +
                                  "(" + inFilePath + ":" + lineNum + ")");
                    }
                    string package = MsgAutoGenUtilities.ResolvePackageName(hierarchy[0]);
                    // Do not add package name if exists in current namespace
                    type = package.Equals(rosPackageNamespace) ? hierarchy[1] + MsgAutoGenUtilities.MessageClassSuffix :
                           package + "." + hierarchy[1] + MsgAutoGenUtilities.MessageClassSuffix;
                    break;

                default:
                    throw new MessageParserException(
                              "Invalid field type '" + type + "'. + " +
                              "(" + inFilePath + ":" + lineNum + ")");
                }
            }
            else
            {
                type = MatchByType(MessageTokenType.Header) + MsgAutoGenUtilities.MessageClassSuffix;
                if (PeekType(MessageTokenType.FixedSizeArray) || PeekType(MessageTokenType.VariableSizeArray))
                {
                    Warn(
                        "By convention, there is only one header for each message." +
                        "(" + inFilePath + ":" + lineNum + ")");
                }
                if (PeekType(MessageTokenType.Identifier) && !Peek().content.Equals("header"))
                {
                    Warn(
                        "By convention, a ros message Header will be named 'header'. '"
                        + Peek().content + "'. (" + inFilePath + ":" + lineNum + ")");
                }
                imports.Add("Std");
            }

            // Array Declaration
            int arraySize = -1;

            if (PeekType(MessageTokenType.FixedSizeArray))
            {
                type            += "[]";
                canHaveConstDecl = false;
                arraySize        = int.Parse(MatchByType(MessageTokenType.FixedSizeArray));
            }
            if (PeekType(MessageTokenType.VariableSizeArray))
            {
                type            += "[]";
                canHaveConstDecl = false;
                MatchByType(MessageTokenType.VariableSizeArray);
                arraySize = 0;
            }

            // Identifier
            string identifier = MatchByType(MessageTokenType.Identifier);

            // Check for duplicate declaration
            if (symbolTable.ContainsKey(identifier))
            {
                throw new MessageParserException(
                          "Field '" + identifier +
                          "' at " + inFilePath + ":" + lineNum +
                          " already declared!");
            }
            // Check if identifier is a ROS message built-in type
            if (builtInTypeMapping.ContainsKey(identifier))
            {
                throw new MessageParserException(
                          "Invalid field identifier '" + identifier +
                          "' at " + inFilePath + ":" + lineNum +
                          ". '" + identifier + "' is a ROS message built-in type.");
            }

            // Check if identifier is a C# keyword
            if (MsgAutoGenUtilities.k_CSharpKeywords.Contains(identifier))
            {
                Warn(
                    "'" + identifier + "' is a C# keyword. It can be accessed under the name @" + identifier + "." +
                    "(" + inFilePath + ":" + lineNum + ")");
                identifier = "@" + identifier;
            }

            symbolTable.Add(identifier, type);

            // Array declaration table
            if (arraySize > -1)
            {
                arraySizes.Add(identifier, arraySize);
            }

            // Constant Declaration
            if (PeekType(MessageTokenType.ConstantDeclaration))
            {
                if (canHaveConstDecl)
                {
                    declaration += "const " + type + " " + identifier + " = ";
                    declaration += ConstantDeclaration(type);
                    constants.Add(identifier);
                }
                else
                {
                    throw new MessageParserException(
                              "Type " + type +
                              "' at " + inFilePath + ":" + lineNum +
                              " cannot have constant declaration");
                }
            }
            else if (PeekType(MessageTokenType.DefaultValueDeclaration))
            {
                declaration += $"{type} {identifier} = {DefaultValueDeclaration(type)}";
                defaultValues.Add(identifier);
            }
            else
            {
                declaration += type + " " + identifier + ";\n";
            }
            body += declaration;
        }
コード例 #6
0
 public static string GetMessageOutFolder(string outPath, string rosPackageName)
 {
     return(Path.Combine(outPath, MsgAutoGenUtilities.ResolvePackageName(rosPackageName)));
 }
コード例 #7
0
        public void WrapAction()
        {
            string msgNamePrefix = inFileName + MsgAutoGenUtilities.ActionClassSuffix;
            string className     = msgNamePrefix + "Action";
            string type          = "wrapper";

            string outPath = Path.Combine(this.outPath, className + ".cs");

            string imports =
                "using System.Collections.Generic;\n" +
                "using Unity.Robotics.ROSTCPConnector.MessageGeneration;\n" +
                "\n\n";

            symbolTable = new Dictionary <string, string>();

            using (StreamWriter writer = new StreamWriter(outPath, false))
            {
                // Write imports
                writer.Write(imports);

                // Write namespace
                writer.Write(
                    "namespace RosMessageTypes." + MsgAutoGenUtilities.ResolvePackageName(rosPackageName) + "\n" +
                    "{\n"
                    );

                // Write class declaration
                string[] genericParams = new string[] {
                    msgNamePrefix + "ActionGoal",
                    msgNamePrefix + "ActionResult",
                    msgNamePrefix + "ActionFeedback",
                    msgNamePrefix + "Goal",
                    msgNamePrefix + "Result",
                    msgNamePrefix + "Feedback"
                };
                writer.Write(
                    ONE_TAB + "public class " + className + " : Action<" + string.Join(", ", genericParams) + ">\n" +
                    ONE_TAB + "{\n"
                    );

                // Write ROS package name
                writer.Write(
                    TWO_TABS + "public const string k_RosMessageName = \"" + rosPackageName + "/" + inFileName + "Action" + "\";\n" +
                    TWO_TABS + "public override string RosMessageName => k_RosMessageName;\n\n"
                    );

                // Record variables
                // Action Goal
                symbolTable.Add("action_goal", className + "Goal");
                // Action Result
                symbolTable.Add("action_result", className + "Result");
                //Action Feedback
                symbolTable.Add("action_feedback", className + "Feedback");

                // Write default value constructor
                writer.Write("\n");
                writer.Write(GenerateDefaultValueConstructor(className) + "\n");
                writer.Write(GenerateDeserializerConstructor(className, false) + "\n");

                writer.Write(GenerateSerializationStatements(type));

                // Close class
                writer.Write(ONE_TAB + "}\n");
                // Close namespace
                writer.Write("}\n");
            }
        }