Converting from D-H notation to URDF files
----------------------


This file converts files in format of Markdown table into a URDF (universal robot description format) file representing of kinematic chain.
Tables should have a format of, with R being whether a joint is Rotational (true| false). Header is not nessessary.

| theta | d | a | alpha |R  |
|-------|---|---|-------|---|
|       |   |   |       |   |
|       |   |   |       |   |
|       |   |   |       |   |

Generally as this notation translates into series of transformations Rot(z,theta)Trans(z,d)Trans(x,a)Rot(x,alpha) two joints -- active and fixed are needed
for each row of the table. 
    
    window.DH_converter = window.DH_converter||{};    

    class window.Robot_Maker
        
        constructor: (@table) ->
            @parser= new DOMParser();
            @robot_dom= @parser.parseFromString(@robot_xml,"text/xml");
            @robot_dom_modified= @parser.parseFromString(@robot_xml_modified,"text/xml");
            @urdf=@convert_text_table(@table)
        robot_xml : "<robot name='example_robot'>
            <link name='link0_passive'><visual>
            <material name='blue'><color rgba='0 0 .8 1'/></material>
            <geometry> <origin xyz='0 0 0' rpy='0 0 0'/>
            
            <cylinder length='0.0' radius='0.0'/></geometry></visual></link>
            
            <link name='link0_x_axis'><visual>
             <material name='red'><color rgba='1 0 0 1'/></material>
            <geometry> <origin xyz='0 0 0' rpy='0 0 0'/>
            <cylinder length='0.0' radius='0.0'/></geometry></visual></link>
            <joint name='q0_x' type='fixed'>
            <origin xyz='0 0 0' rpy='0 1.571 0'/>
            <parent link='link0_passive' />
            <child link='link0_x_axis' />
            </joint>
            
            </robot> ";
        robot_xml_modified : "<robot name='example_robot'>
            <link name='link0'><visual>
            <material name='blue'><color rgba='0 0 .8 1'/></material>
            <geometry> <origin xyz='0 0 0' rpy='0 0 0'/>
            
            <cylinder length='0.6' radius='0.1'/></geometry></visual></link>
            
            
            </robot> ";

A Moustache template is prepared to put the adequate values from the row od DH table

        row_template_insert:"
        <link name='link{{name}}'></link>
        <link name='link{{name}}_x_axis'><visual><origin xyz='0 0 0.25' rpy='0 0 0'/> <material name='red' /><geometry><cylinder length='0.5' radius='0.05'/></geometry></visual></link>
        
    
        <joint name='q{{name}}' type='{{type}}'>
        <origin xyz='0 0 {{d}}' rpy='0 0 {{th}}'/>
        <parent link='link{{previous_name}}_passive' />
        <child link='link{{name}}' />
        <axis xyz='0 0 1'/>
        </joint>
        
        
        <joint name='q{{row_no}}_passive' type='fixed'>
        <origin xyz='{{a}} 0 0' rpy='{{alpha}} 0 0'/>
        <parent link='link{{name}}' />
        <child link='link{{name}}_passive' />
        </joint>";
        row_template_add_x:"<link name='link{{name}}_passive'><visual> <origin xyz='0 0 0.25' rpy='0 0 0'/><material name='blue' /><geometry><cylinder length='0.5' radius='0.05'/></geometry></visual></link>
        <joint name='q{{row_no}}_x' type='fixed'>
        <origin xyz='0 0 0' rpy='0 1.571 0'/>
        <parent link='link{{name}}_passive' />
        <child link='link{{name}}_x_axis' />
        </joint>
        ";
        modified_dh_row_template_insert:"<link name='link{{name}}'>
        <visual><origin xyz='0 0 0.25' rpy='0 0 0'/> <material name='red' />
        <geometry><cylinder length='0.5' radius='0.05'/></geometry></visual></link>
        
        <joint name='q{{name}}' type='{{type}}'>
        <origin xyz='{{a}} {{dy}} {{dz}}' rpy='{{alpha}} 0 {{th}}'/>
        <parent link='link{{previous_name}}' />
        <child link='link{{name}}' />
        <axis xyz='0 0 1'/>
        </joint>
        
        
        
        "    


Using regex, we parse rows of table, starting from 2nd row. Regex looks for floating values for every but last column, we convert last column to boolean value.
Then, each row is passed to DH_row_to_links function

        convert_text_table: (table) ->
    
            ### function converts markdown table into nodes, we assume that table has header (two lines)
            ###




            table=table.replace(/(\t| )/g, '');
	


            window.table=table;
            lines_of_text=table.split('\n');
            robot_dict={}
            
First we look whether user is using DH parameters or modified DH parameters, what is the sequence of columns of the first row

            standard_dh=new RegExp(/\|(th|theta)\|d\|a\|alpha\|R\|/i)
            modifed_dh=new RegExp(/\|a\|alpha\|(th|theta)\|d\|R\|/i)
            
            
            
            is_standard=standard_dh.test(lines_of_text[0])
            is_modified=modifed_dh.test(lines_of_text[0])

            if is_standard
                sam_robot = @robot_dom.getElementsByTagName("robot")[0]
            else if is_modified
                sam_robot = @robot_dom_modified.getElementsByTagName("robot")[0]
            else
                                window.alert("Not a valid table. please use table header in form of |th|d|a|alpha|R| or |a|alpha|th|d|R|");
                                return null


                
                
A pattern is created to seek for valid DH values -- that is floating point numbers that are preeceeded by pipe |

            #pattern=/\|\W*?([-+]?[0-9]*\.?[0-9]+)\W*?\|\W*?([-+]?[0-9]*\.?[0-9]+)\W*?\|\W*?([-+]?[0-9]*\.?[0-9]+)\W*?\|\W*?([-+]?[0-9]*\.?[0-9]+)\W*?\|\W*?(\w+?)\W*?\|/;
            #regg=new RegExp(pattern)
We hardcode that every line from the 3rd is treated as a row containing DH-values

            for line_no in [2...lines_of_text.length]
                 robot_dict.row_no=line_no-1
                 
                 #przerob_linijke=lines_of_text[line_no].match(regg)

                 przerob_linijke=lines_of_text[line_no].split('|')
                 if lines_of_text[line_no].length==0
                     continue
                 if przerob_linijke==null or przerob_linijke.length<5
                     window.alert("line "+(line_no-1)+" is not valid") # TODO it should be some one nice alerting system
                     console.log("line "+(line_no-1)+" is not valid")
                     continue;
                 try
                     if is_standard    
                         robot_dict.th=math.eval(przerob_linijke[1])
                         robot_dict.d=math.eval(przerob_linijke[2])
                         robot_dict.a=math.eval(przerob_linijke[3])
                         robot_dict.alpha=math.eval(przerob_linijke[4])
                         robot_dict.R=przerob_linijke[5]=="true"
                     if is_modified
                         robot_dict.a=math.eval(przerob_linijke[1])    
                         robot_dict.alpha=math.eval(przerob_linijke[2])
                         robot_dict.th=math.eval(przerob_linijke[3])
                         robot_dict.d=math.eval(przerob_linijke[4])
                         robot_dict.modified_dh=true
                         robot_dict.R=przerob_linijke[5]=="true"
                     console.log(robot_dict)
                 catch e 
                     window.alert("line "+(line_no-1)+" is not valid") # TODO it should be some one nice alerting system
                     console.log("line "+(line_no-1)+" is not valid")
                     continue;
                 wynik=@DH_row_to_links(robot_dict)
                 
                 sam_robot.insertAdjacentHTML('beforeend',wynik)
                
            return vkbeautify.xml(sam_robot.outerHTML) #we beutify result using outside tool
            
Function below takes a dictionary of row values and converts it into xml code. 

    
        DH_row_to_links: (row_dict,add_x=true) ->
            ### function gets a dictionary representing row in DH table, returns xml node based on two links
            additional code representing x axis can be added if add_x is true
            ###
            
            row_no=row_dict.row_no
            row_dict.name=row_no
            row_dict.previous_name=row_no-1
            if row_dict.R
                row_dict.type="revolute"
            else
                row_dict.type="prismatic"
                
            template_xml=@row_template_insert
            
            if add_x
                template_xml=template_xml+@row_template_add_x
            
There is the option of using modified Denavit-Hartenberg parameters, where the sequence of transformations is different. 
Actually, this gives the opportunity to use only one link per row (while treating each row equally),
 but some math is needed to calculate the start translation between joints. 
That is we translation=[a;0;0]+ R[x,alpha] [0;0;d]

            if row_dict.modified_dh
                
                alpha=parseFloat(row_dict.alpha)
                d=parseFloat(row_dict.d)
                row_dict.dy=-Math.sin(alpha)*d
                row_dict.dz=Math.cos(alpha)*d
                console.log(row_dict.dy)
                console.log(row_dict.dz)
                template_xml=@modified_dh_row_template_insert
            
            
            row_xml=Mustache.render(template_xml,row_dict)
            return     row_xml
        


        
        
        
        
    
