.

     

MPI Application Template
template.c
 

pt1.c -- Simple motion path generation, specified by position/time points.
/* pt1.c */

/* Copyright(c) 1991-2006 by Motion Engineering, Inc.  All rights reserved.
 *
 * This software  contains proprietary and  confidential information  of
 * Motion Engineering Inc., and its suppliers.  Except as may be set forth
 * in the license agreement under which  this software is supplied, use,
 * disclosure, or  reproduction is prohibited without the prior express
 * written consent of Motion Engineering, Inc.
 */

/*

:Simple motion path generation, specified by position/time points.

This sample code demonstrates the motion type, MPIMotionTypePT and
 MPIMotionType BSpline.  A simple trapezoidal velocity profile
 points list is created, and downloaded to the controller.  The
 time delta between each position is constant and the positions
 are spaced to generate an acceleration, constant velocity,
 and deceleration profile to the final position.

Several motion parameters must be initialized for the PT motion type:

 params.pt.pointCount - Specifies the number of points (position/time).

 params.pt.position - Pointer to a position[...] array.  There is one
    position value per point, per axis.  The length of the array must be
    equal to pointCount multiplied by the number of axes.  The positions
    are interleaved in the array by the axis index.

    For example, a three axis system would have:
        position[0] = position for axis 0
        position[1] = position for axis 1
        position[2] = position for axis 2
        position[3] = position for axis 0
        position[4] = position for axis 1
        etc.

 params.pt.time - Pointer to a time[...] array.  There is one time value
    per point.  The time specifies the number of seconds between the previous 
    position (point) and the specified position.  The length of the time array 
    must be equal to the pointCount.

 params.pt.point.retain - Specifies whether the MPI and XMP should buffer the
    points after they have executed.  If retain = 0, the buffer will destroy
    the points after they have executed.  If retain = 1, the buffer will keep the
    points after they have executed.  This parameter is useful for future backup
    on path capability.

 params.pt.point.final - Specifies if more points will be loaded.  If final = 1,
    no more points will be loaded.  If final = 0, more points can be loaded
    with mpiMotionModify(...) using the APPEND attribute.

 params.pt.point.emptyCount - Specifies how many points the XMP-Series
    controller must have in it's buffer.  If the XMP's point buffer falls
    below the emptyCount, an E-Stop event will be generated by the motion
    supervisor, decelerating all the associated axes to a stop.

 BSpline motion is virtually identical programatically. The function
   startPointList() has an argument that creates either a PT move
   or a BSpline move to highlight the differences between the two.

When the points are passed to mpiMotionStart(...), the MPI calculates
 constant velocity segments to fit exactly through the specified positions at
 the specified times.  The MPI library automatically handles buffering points
 lists that are larger than the XMP's buffer.  Presently, the XMP-Series
 controller can store 128 Frames per axis.  Each point requires one Frame
 per axis.

Special Considerations:

It is not necesary to specify the initial command position as the first
 position point.  The time[...] values can be constant or vary for each point.
 Constant time[...] values make the programmer's calculations easier.  For
 optimum performance, the number of points can be reduced, with no loss of
 resolution, by replacing the constant velocity sections with longer
 time[...] values.

When creating points lists longer than 64 points, you must create an Event
 Manager.  The Event Manager handles point buffering between the MPI and the XMP
 controller.

For Acceleration/Jerk fits through a points list, use the motion type,
 MPIMotionTypePVT. In this case, position/velocity/time points are specified.


Warning!  This is a sample program to assist in the integration of the
 XMP motion controller with your application.  It may not contain all
 of the logic and safety features that your application requires.

*/

#include <stdlib.h>
#include <stdio.h>

#include "stdmpi.h"
#include "stdmei.h"

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    pt1Main

argMainRENAME(main, pt1)
#endif

#define MAX_POINT_COUNT (1000)    /* Number of points in trajectory */
#define POINT_COUNT     (25)
#define TIME            (.1)    /* Time between points (seconds) */
#define BSPLINE_ON (FALSE)

/* Simple trapezoidal profile velocity path */
double point[POINT_COUNT] = {
    0.0,
    10.0,       /* Acceleration */
    30.0,
    60.0,
    100.0,
    150.0,
    210.0,
    280.0,
    360.0,
    450.0,
    550.0,
    650.0,      /* Constant vel */
    750.0,
    850.0,
    950.0,
    1050.0,
    1140.0,     /* Deceleration */
    1220.0,
    1290.0,
    1350.0,
    1400.0,
    1440.0,
    1470.0,
    1490.0,
    1500.0 };



/* Command line arguments and defaults */
long motionNumber = 0;
long axisNumber = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber, },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Perform basic command line parsing. (-control -server -port -trace) */
void basicParsing(int                    argc,
                  char                  *argv[],
                  MPIControlType        *controlType,
                  MPIControlAddress     *controlAddress)
{
   long argIndex;

   /* Parse command line for Control type and address */
    argIndex =
        argControl(argc,
      argv,
      controlType,
      controlAddress);

    /* Parse command line for application-specific arguments */
    while (argIndex < argc) {
        long    argIndexNew;

        argIndexNew = argSet(argList, argIndex, argc, argv);

        if (argIndexNew <= argIndex) {
            argIndex = argIndexNew;
            break;
        }
        else {
            argIndex = argIndexNew;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber > (MPIXmpMAX_Axes - 1)) ||
        (motionNumber  >= MPIXmpMAX_MSs)) {
        mpiPlatformConsole("usage: %s %s\n"
         "\t\t[-axis # (0 .. %d)]\n"
         "\t\t[-motion # (0 .. %d)]\n",
         argv[0],
         ArgUSAGE,
         MPIXmpMAX_Axes - 1,
         MPIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }
}

void programInit(MPIControl         *control,
             MPIControlType      controlType,
                 MPIControlAddress  *controlAddress,
                 MPIMotion       *motion,
             long          motionNum,
             MPIAxis       *axis,
             long          axisNum,
             MPINotify        *notify,
             MPIEventMgr      *eventMgr,
             Service       *service)
{
   MPIEventMask eventMask;
   long returnValue;

   /* Obtain a Control handle */
    *control =
        mpiControlCreate(controlType,
      controlAddress);
    msgCHECK(mpiControlValidate(*control));

    /* Initialize the controller */
    returnValue = mpiControlInit(*control);
    msgCHECK(returnValue);

    /* Create Axis objects */
    *axis = mpiAxisCreate(*control,
      axisNum);
   msgCHECK(mpiAxisValidate(*axis));


    /* Create motion object */
    *motion =
        mpiMotionCreate(*control,
      motionNum,
      *axis);
    msgCHECK(mpiMotionValidate(*motion));

      /* Request notification of all events from motion */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    returnValue =
        mpiMotionEventNotifySet(*motion,
      eventMask,
      NULL);
    msgCHECK(returnValue);

    /* Create event notification object for motion */
    *notify =
        mpiNotifyCreate(eventMask,
      *motion);
    msgCHECK(mpiNotifyValidate(*notify));

    /* Create event manager object */
    *eventMgr = mpiEventMgrCreate(*control);
    msgCHECK(mpiEventMgrValidate(*eventMgr));

    /* Add notify to event manager's list */
    returnValue =
        mpiEventMgrNotifyAppend(*eventMgr,
      *notify);
    msgCHECK(returnValue);

    /* Create service thread */
    *service =
        serviceCreate(*eventMgr,
      -1,   /* Default (max) priority */
      -1);  /* Default sleep (msec) */
    mpiAssert(*service != NULL);

}

void deleteObjects(MPIControl control, MPIAxis axis,
               MPIMotion motion, MPINotify notify,
               MPIEventMgr eventMgr, Service service)
{
   long returnValue;

   /* Delete Objects */
    returnValue = serviceDelete(service);
    msgCHECK(returnValue);

    returnValue = mpiEventMgrDelete(eventMgr);
    msgCHECK(returnValue);

    returnValue = mpiNotifyDelete(notify);
    msgCHECK(returnValue);

    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axis);
    msgCHECK(returnValue);

    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);
}

void waitForMotionDone(MPINotify notify)
{
   /* Collect motion events */
    long motionDone = FALSE;
   long returnValue;

    while (motionDone != TRUE)
   {

        MPIEventStatus  eventStatus;

        returnValue =
            mpiNotifyEventWait(notify,
         &eventStatus,
         MPIWaitFOREVER);

        switch(eventStatus.type)
      {

      case MPIEventTypeMOTION_DONE:
         {
                motionDone = TRUE;
                break;
            }
      default:
         {
                break;
            }
        }

        fprintf(stderr,
         "mpiNotifyEventWait() returns 0x%x\n"
         "\teventStatus: type %d source 0x%x info 0x%x\n",
         returnValue,
         eventStatus.type,
         eventStatus.source,
         eventStatus.info[0]);
        msgCHECK(returnValue);

    }

}

void startPointList(MPIMotion motion, MPIAxis axis,
               double points[], long pointCount,
               MPI_BOOL spline, double timeSlice)
{
    MPIMotionParams params; /* MPI motion parameters */
   long returnValue;
   long pointIndex;
    double initialPosition;
   double position[MAX_POINT_COUNT];
   double ptime[MAX_POINT_COUNT];


   /* Read initial command position */
    returnValue =
        mpiAxisCommandPositionGet(axis,
      &initialPosition);
    msgCHECK(returnValue);


   if(spline != FALSE)
   {
      /* Initialize motion params structure */
      params.bspline.pointCount = pointCount;
      params.bspline.position = position;
      params.bspline.time = ptime;
      params.bspline.point.retain = 0;     /* Flush frame buffer after execution */
      params.bspline.point.final = 1;      /* Last point */
      params.bspline.point.emptyCount = 5; /* Start E-Stop if frames left to execute
                                 is less than this limit. -1 disables */
   }
   else
   {
      /* Initialize motion params structure */
      params.pt.pointCount = pointCount;
      params.pt.position = position;
      params.pt.time = ptime;
      params.pt.point.retain = 0;     /* Flush frame buffer after execution */
      params.pt.point.final = 1;      /* Last point */
      params.pt.point.emptyCount = 5; /* Start E-Stop if frames left to execute
                                 is less than this limit. -1 disables */
   }

    /* Create points */
    for (pointIndex = 0; pointIndex < pointCount; pointIndex++) {

        ptime[pointIndex] = timeSlice;   /* Delta time between points */

        /* Position at point */
        position[pointIndex] =
            point[pointIndex] + initialPosition;
    }

    /* Start motion */
    returnValue = mpiMotionStart(motion,
      spline?MPIMotionTypeBSPLINE:MPIMotionTypePT, // spline or PT move?
      &params);
    msgCHECK(returnValue);
}

void main(int    argc,
         char   *argv[])
{
    MPIControl      control;            /* Control object */
    MPIAxis         axis;           /* Axis object */
    MPIMotion       motion;             /* Motion object */
    MPINotify       notify;             /* Event notification handle */
    MPIEventMgr     eventMgr;           /* Event manager handle */
   MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    Service         service;            /* Event manager service handle */


   /* Perform basic command line parsing. (-control -server -port -trace) */
    basicParsing(argc,
      argv,
      &controlType,
      &controlAddress);

   /* Create and initialize MPI objects */
    programInit(&control,
      controlType,
      &controlAddress,
      &motion,
      motionNumber,
      &axis,
      axisNumber,
      &notify,
      &eventMgr,
      &service);

   /* Create a PT or BSpline move */
   startPointList(motion, axis, point, (long)POINT_COUNT, FALSE, TIME);

    /* Wait for it to finish */
   waitForMotionDone(notify);

   /* Clean up */
   deleteObjects(control,
      axis,
      motion,
      notify,
      eventMgr,
      service);
}


      
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2009 Motion Engineering