3

I have some problems using git with my KRL projects and want to know if there are some workarounds to improve my workflow.

KRL is the programming language for industiral KUKA robots. It has a Basic-/Pascal-like syntax. A program consists of one or multiple modules. A module consists of two textfiles, one for the source code (.src) and one for declarations and definitions (.dat).

My first problem is that in each file the first lines build the header which looks like this:

&ACCESS RVO
&REL 175

Each header line starts with a & and has absolutely no meaning for the code. The worst part is this header changes constantly. So when I copy a file back from the robot controller into my repo git states that the file changed even though the source code is the same.

So my first question: Is there a way with filters or hooks to ignore all lines starting with a &?

My second problem is that the *.dat files are not only for declarations and definitions like header files in C-like languages, but also a storage for the values. This looks like this:

DECL E6POS XP1={X 319.710815,Y -488.601227,Z 1364.72363,A -73.5368805,B 88.6439896,C 10.5155058,S 6,T 26,E1 0.0,E2 0.0,E3 0.0,E4 0.0,E5 0.0,E6 0.0}
INT counter=123
REAL offset=0.123

I depend on the values because they store the positions and counters that need to stay persistent, but I don't care about them in my repo. Well not completely, they have to be in the files and in my repo but git shouldn't look for diffs in these lines.

So lets say I created a module in my repo and copy this module to the robot. Now I execute this module with the robot and have to overwrite a position value. This changes the value in the corresponding *.dat file. Everything works fine and after a few days I want to implement a counter. I can't just put a new integer definition into the locally available *.dat file, because this way I would overwrite the position value on the robot. So I have to copy the *.dat file from the robot controller into my repo first and define the new variable there. But of course git shows me that the file changed not only in the new line but also on the lines where the robot changed the values like the position. This makes reviews way harder, because I have lots of measurement and counter values that change constantly.

So to my second question: Is there a way to ignore everything after the = but only in *.dat files? This should work the same as with the & from the headers, so the values should be in the repo but I don't care about any diffs on these values.

ascaron37
  • 33
  • 3
  • 1
    Not an answer to your question, but I would like to mention that I have developed a tool to convert the WorkVisual .wvs files to text files, and reverse. I've been using it for over five years to source control WorkVisual files and it proved to be very stable. If there's interest, I could open-source it. – Daniel Gehriger May 02 '22 at 09:17
  • @DanielGehriger this is a great idea! I'd love to see your tool. – ascaron37 May 04 '22 at 05:12

3 Answers3

3

Welcome ascaron37!

For your first question, The header values prefixed with '&' are auto-generated by the KSS, a behavior that cannot be deactivated or modified. The headers have no effect on code execution and so can be deleted at anytime; however, the KSS will just auto-generate them again at some point.

My solution to this was to create a "KRL-Git cleaner" tool in C# WPF that scrubs any auto-generated lines from any file within the Workvisual repository folder, usually in "C:\Users"username"\Documents\WorkVisual 6.0\Repositories".

my workflow is like this:

  1. Write code on robot or WorkVisual
  2. Run my KRL-Git cleaner to delete any auto-generated lines from the repository
  3. make a git commit

I cannot share the project because of company policy, but I can provide a snippet with an example of how i scrub the lines:

        using System;
        using System.IO;
        using System.Windows;
        using System.Windows.Input;

        /// <summary>
        /// Delete deletable lines withing directory and children
        /// </summary>
        /// <param name="parentDirectory"></param>
        /// <returns></returns>
        private int DeleteAllChildren(DirectoryInfo parentDirectory)
        {

            int deletables = 0;

            foreach (var childDirectory in parentDirectory.GetDirectories())
            {
                deletables += DeleteAllChildren(childDirectory);
            }

            foreach (var childFile in parentDirectory.GetFiles())
            {
                if (childFile.Extension == ".src" || childFile.Extension == ".dat" || childFile.Extension == ".sub")
                {
                    var tempFile = Path.GetTempFileName();
                    using (StreamWriter sw = new StreamWriter(tempFile))
                    {
                        using (StreamReader sr = new StreamReader(childFile.FullName))
                        {
                            var inLine = "";
                            while (!sr.EndOfStream && !inLine.Contains("DEF"))
                            {
                                inLine = sr.ReadLine();

                                if (!inLine.Contains("&REL") && !inLine.Contains("&ACCESS"))
                                {
                                    sw.WriteLine(inLine);
                                }
                                else
                                {
                                    deletables += 1;
                                }

                            }
                            while (!sr.EndOfStream)
                            {
                                sw.WriteLine(sr.ReadLine());
                            }

                            sr.Close();
                        }
                        sw.Close();
                    }

                    File.Delete(childFile.FullName);
                    File.Move(tempFile, childFile.FullName);
                }
            }

            return deletables;
        }

I'm sorry if you were looking for a simpler method, but KUKA doesn't seem to care much about industry standard version control.

As for your second question, MY tactic would be to work in the functionality into my code snippet above, since I'm already using it to get rid of auto-generated lines. I bet some Git professionals would have a more elegant solution though.

Micahstuh
  • 443
  • 1
  • 5
  • 13
  • Can't you simply gitignore autogenerated files? In fact in other languages people usually ignore all generated files – slebetman Dec 23 '20 at 15:59
  • These aren't auto-generated files. They're auto-generated lines within the file. – Micahstuh Dec 23 '20 at 16:04
  • Hey @Micahstuh, thanks for sharing and the warmth welcome! I could swear my src und dat files were not recognized as modules without the header lines, but I will try again in two weeks since I don't have access to a robot until then. – ascaron37 Dec 23 '20 at 18:01
3

Using filters you can ignore those lines.

Lets say we have a filter on /scripts/krl_filter.sh:

sed -e '/\&ACCESS/d' -e '/\&REL/d' -e '/\&PARAM/d' -e '/\&COMMENT/d'

We set the filter into /.git/config

[filter "krl"]
  clean = $PWD/scripts/krl_filter.sh
  smudge = cat
  required = true

We apply it to the KRL-files .gitattributes

*.src filter=krl
*.dat filter=krl
*.sub filter=krl

Maybe you will see before commit the head lines as changed but once staged the changes or somehow else, the filter is applied

*for the .dat files you could use a filter like this:

sed -e 's/=[^=]*$/=/'

For more information about ignoring lines in git check this: How to tell git to ignore individual lines, i.e. gitignore for specific lines of code

  • 1
    Hey Daniel, thanks for the answer. I saw that thread already and it's not quite the behavior I want, at least on the dat files. I am still unsure if the modules are recognized without the header lines. If they are, it's perfect. For the dat files I have a sed -e "s/=[^=]*$//" to substitute everything after the assignment instead of deleting the whole line. But again I would like to keep those values around in the repo and rather ignore them while diffing. Maybe I have to rethink the way I am working with krl, therefore I would accept your answer. – ascaron37 Jan 03 '21 at 10:30
2

It is not completly correct, that the values behind the & in the Header are completly irrelevant. At least the 'V' flag behind the &ACCESS parameter ist usefull, do declare that these module and the call of these module-functions are visible or not at the SmartPad/SmartHmi. The other values (except the COMMENT, what is self-explanatory) are not used often, and are correctly added by the KRC.

Therefore I added a filter to ~/.git/config that deletes only the numbers in the &ACCESS line, and some other header-params.

[filter "krl"]
    clean = "sed -e 's/\(^&ACCESS [A-Z]*\).*$/\1/' -e '/\^&REL/d' -e '/\^&PARAM/d'"
    smudge = "sed -e 's/\(^&ACCESS [A-Z]*\).*$/\1/' -e '/\^&REL/d' -e '/\^&PARAM/d'"

You also have to apply these filters to the files in the .gitattributes

*.src filter=krl
*.dat filter=krl
*.sub filter=krl

The datas in the .dat files are a bigger problem. But if you dont need persistence (what you probably don't need, otherwise you maybe want to add it in the version control) you are able declare the variables in the .dat file with no assignment. Like:

DECL INT foo
DECL E6POS bar

In these case you need an assignment some value before reading, otherwise you get an error.

Or you add some sed commad to your git filter like

`sed -e 's/\(^ *DECL  *[A-Z]*  *[A-Za-z][A-Za-z0-9]* *=\).*\(;\\ignoreVersion\[\(.*\)\]\)/\1 \3 \2/'

With these you are able to add an comment behind the assignment like

DECL INT foo = 1234 ;ignoreVersion[12]

In these case the value of foo will be replaced with "12" on every commit.

kcinnaySte
  • 41
  • 4