Control System Code Generator

I am working on a code generator for control systems.

    -----------------------------------------------------
    If there's enough interest in the rtai/rtlinux/comedi
    community I would create a small homepage, upload the
    source etc. and distribute it under GPL or BSD license.
    ----------------------------------------------------

It boils down to a python script which reads in a
directory containing templates for operators e.g.
DAC/ADC (comedi templates), Digital transfers function,
PID controller, RT-Linux main program template and/or
a user space main program template.
These templates contain c-code which embedds python code
for glue code generation.
(similar to perl/python apache-web-server modules)

The templates are then used to create operators
which override some/all default values.

The operators are then connected so that they
represent e.g. a closed-loop system.

Finally c-code is generated which can be used to
simulate the system in user-space or control
a real system with rtlinux&comedi.


Ciao,
   Dominic

P.S. I am tired, so here is an early example:



###########################################################

Example model & generated c-code:

An example-model would be:

---------------------------------------------------------------

# Create Step function
# _M(0) makes the parameter tuneable, otherwise it would be
# hardcoded
# tuneable parameters can be changed by a kernel-memory-patch script

in1=t_step.Create(trigger=_M(0),amplitude=_M(1))

# Simple user-space printf output
out1=t_dump.Create()

# Digital transfer function
plant1=t_plant.Create(order=3,osize=3,a=[1,-0.3,0.5],b=[0,0,1])

# Start a tree
tree=TreeNode(in1)

# The user-space main program template, get's control function tree as
# parameter
rt1=t_main.Create(t=tree)

# Connect step-function with digital transfer function to output
tree.Link([in1],[plant1])
tree.Link([plant1],[out1])

# Setup various data structures
tree.WalkTree()

# Generate user-space main program
source=rt1.Gen('main')

# Print Code
PrettyPrint(source)
-------------------------------------------------------------------------

The generated c-source:

/* rt1 section main */
/* in1 has no section include */
/* plant1 has no section include */
/* out1 has no section include */
#include <stdio.h>
#include <stdlib.h>
/* in1 section data */
double in1[3];
double in1_trigger = 0;
double in1_amplitude = 1;
/* plant1 section data */
double plant1_a[3];
double plant1_b[3];
double plant1[3];
/* out1 section data */
void
init ()
{
    /* in1 section init */
    memset (in1, 0, sizeof (double) * 3);
/* plant1 section init */
    plant1_a[0] = 1;
    plant1_a[1] = -0.3;
    plant1_a[2] = 0.5;
    plant1_b[0] = 0;
    plant1_b[1] = 0;
    plant1_b[2] = 1;
    memset (plant1, 0, sizeof (double) * 3);
/* out1 section init */
}
struct arg_register_t
{
    char name[20];
    double *value;
};
double z = 123;
struct arg_register_t arg_register[] = {
    {"1979", (double *) 0},
    {"index", ((double *) &arg_register)},
    /* in1 section register */
    {"in1_trigger", &in1_trigger},
    {"in1_amplitude", &in1_amplitude},
/* plant1 section register */
/* out1 section register */
    {"", NULL}
};
struct arg_register_t *
arg_register_find (char *name)
{
    struct arg_register_t *reg = arg_register;
    while ((*reg++).value != NULL)
      {
        if (strcmp (name, (*reg).name) == 0)
	{
	  return reg;
	}
      }
    return NULL;
}

int
arg_register_get (char *name, double *value)
{
    struct arg_register_t *reg;
    reg = arg_register_find (name);
    if (reg)
      {
        *value = *((*reg).value);
        return 1;
      }
    else
      {
        return -1;
      }
}
int
arg_register_set (char *name, double value)
{
    struct arg_register_t *reg;
    reg = arg_register_find (name);
    if (reg)
      {
        *((*reg).value) = value;
        return 1;
      }
    else
      {
        return -1;
      }
}
int
main ()
{
    double t;
    init ();
    arg_register[0].value = (double *) 0x7766;
    for (t = 0; t <= 2.5; t += 0.05)
      {
        {
/* in1 section update */
	memmove (in1 + 1, in1, sizeof (double) * (2));
	{
	  static int in1_counter = 0;
	  in1_counter++;
	  if (in1_counter >= in1_trigger)
	    {
	      in1[0] = in1_amplitude;
	    }
	  else
	    {
	      in1[0] = 0;
	    }
	}
        }
        {
/* plant1 section update */
	memmove (plant1 + 1, plant1, sizeof (double) * (2));
	{
	  int i;
	  double sum = 0.0;
	  for (i = 0; i < 3; i++)
	    {
	      sum += in1[i] * plant1_b[i];
	    }
	  for (i = 1; i < 3; i++)
	    {
	      sum -= plant1[i] * plant1_a[i];

	    }
	  plant1[0] = sum / plant1_a[0];
	}
        }
        {
/* out1 section update */
	printf ("%g %g\n", t, plant1[0]);
        }
        /* in1 has no section updateState */
/* plant1 has no section updateState */
/* out1 has no section updateState */
      }

    printf ("You might want to try patch.py :-)\n");
    getchar ();

    arg_register[0].value = (double *) 0x0;
    return EXIT_SUCCESS;
}

------------------------------------------

Received on 2002-09-08Z19:38:22