ibisjoe Posted January 23, 2012 Posted January 23, 2012 what is the recommended method for accessing Coordinate Systems and the related Q-Variables from a CPLC program?
Sina.Sattari Posted January 23, 2012 Posted January 23, 2012 ibisjoe, You can use the following API calls: /// Get the Pmac value of a symbol variable or a structure variable /// /// The input string is converted from symbolic to PMAC variables before calling the GetPmacNativeVar() function. /// For CsGlobal variable precede it with "&n" where "n" is the CS # /// \param[in] *pinstr - ptr to input string with symbol name that is converted to a PMAC variable /// \param[out] *pdata - ptr for returned data /// \return 0 == OK, - == error number int GetPmacVar( char *pinstr, double *pdata); /// Set a Pmac symbol variable = data /// /// The input string is converted from symbolic to a PMAC variable before calling the SetPmacNativeVar() function. /// For CsGlobal variable precede it with "&n" where "n" is the CS # /// \param[in] *pinstr - ptr to input string with symbol name that is converted to a PMAC variable /// \param[in] data - assigned data /// \return 0 == OK, - == error number int SetPmacVar( char *pinstr, double data); /// Get a Pmac Native Variable(I,M,P,Q, Motor[1].Servo.Kp, etc) /// /// The input string Pmac Variable or Structure which require no symbolic name replacement /// For Q variable precede it with "&n" where "n" is the CS # /// \param[in] *pinstr - ptr to input string that is a PMAC variable or structure /// \param[out] *pdata - ptr for returned data /// \return 0 == OK, - == error number int GetPmacNativeVar( char *pinstr, double *pdata); /// Set a Pmac Native Variable(I,M,P,Q, Motor[1].Servo.Kp, etc) = data /// /// The input string Pmac Variable or Structure which require no symbolic name replacement /// For Q variable precede it with "&n" where "n" is the CS # /// \param[in] *pinstr - ptr to input string that is a PMAC variable or structure /// \param[in] data - assigned data /// \return 0 == OK, - == error number int SetPmacNativeVar( char *pinstr, double data); All of these API calls and their descriptions are available under ftp://{YourPowerPMACIP}/ppmaclibs/libppmac/gplib.h
ibisjoe Posted January 23, 2012 Author Posted January 23, 2012 I know about those calls but they appear to be rather "fatty" to me: shouldn't I be able to set the C.S. system ONCE and use some sort of more direct access (more like a Script PLC)?
bradp Posted January 24, 2012 Posted January 24, 2012 in a new project in global definitions.pmh make this definition csglobal mycsvar1; Then build and download. Then look at the file pp_proj.h under the include directory in the IDE project explorer. In here you find 3 sections. In the script mode section you find a #define for the variable you just created. This shows you the sysntax to use a pointer for the CS vars. In this case you get. #define mycsvar1(i) pshm->Coord[i%MAX_COORDS].Q[1024]
michaelthompson Posted January 24, 2012 Posted January 24, 2012 Sina, Joe's particular question might be better stated this way: Most of our application is being written using CPLCs. We have found that we can avoid all Script PLCs. However, in order to execute motions, we are still assuming that the recommended method is to start up a motion program to perform the motion. If that is the case, then we need to communicate with the motion program through its coordinate system variables. It would be preferred to do that without having to form a string which represents the Q variable of interest only to have the Power PMAC library functions undo the format to obtain the Q variable index. So, the question can be broken down into two parts: 1. Is there a C library function that can be used to build a motion trajectory in a given coordinate system and execute it without requiring the use of a motion program? If so, can you point us to an example? For example, our motion program will perform an F(velocity) along with TA(acceleration) and then an X(position). Can we do this all from C? 2. If not and motion programs are still required, how can we communicate with the motion program without building up Q variable strings?
curtwilson Posted January 25, 2012 Posted January 25, 2012 If you want to command a single move of one or more axes without using a real motion program, you can utilize the "one-line/one-shot" motion program of the "cpx" command. For example, if you sent a command like: &1 cpx linear abs F20 ta100 X15 Power PMAC's CS1 would execute this just as if it had been a single-line motion program. (Try it from the terminal in the IDE!) So in your C program, you could use the sprintf function to assemble the string -- with three formatted variables in your example. Then you could use the "command" function out of our gplib.h to send this string to the command parser [of form: int Command (char *pinstr), where pinstr is the pointer to the string]. If you need to execute a motion program that cannot be expressed in a single line, the best way to set Q-variable values as "arguments" to the motion program is to use the following structure: pshm->Coord[x].Q For example: pshm->Coord[1].Q[100] = 20; pshm->Coord[1].Q[101] = 100; pshm->Coord[1].Q[102] = 15; could set the parameters in the motion program line; linear abs F(Q100) ta(Q101) X(Q102);
michaelthompson Posted January 25, 2012 Posted January 25, 2012 Brad, Thanks. That works. We also found the SetCSGlobalVar and GetCSGlobalVar macros. Curt, We are not interested in using the sprintf and command functions to fire off a one line motion program. We are already doing that to fire off the full motion program using a B{constant}R command and it works fine, but we would prefer to avoid the motion program altogether and simply build up the motion commands directly from within our C PLC (with no conversions to/from ASCII and no need to invoke anything but C API calls/macros provided by Delta Tau or encoded by us). Although there are no real problems with the motion program approach, it seems to me to be unnecessary to have to interface through a motion program when the motion program must eventually call some (probably hidden) API to build up the queue of motion commands to execute. If hidden, why can't that API be exposed? If not hidden, all we need is someone to point us to it with an example. What you describe in your final example is basically what we are doing (sometimes with multiple moves). However, as presented above, we would have no need for the Q variables or the motion program if we instead had C calls that allowed us to perform the same functions. Using your example, a simplistic C version might look something like this: int cs=3; CS_setLinear(cs); CS_setAbs(cs); CS_setF(cs,20); CS_setTA(cs,100); CS_moveX(cs,15); // builds up the move and adds it to the move buffer If (or when) DeltaTau supports C++ in its CPLCs, that same example might look something like this: CoordData* cs=&pshm->Coord[3]; cs->setLinear(); cs->setAbs(); cs->setF(20); cs->setTA(100); cs->moveX(15); In either case, there would be no need to invoke either Q variables or a motion program. We are finding that we can code virtually everything in CPLCs and C applications (and we are really liking that approach). The only things we use that are still not possible to encode in C are: -- global variable definitions (which is OK, the approach taken seems to work fine) -- motion programs (unless someone tells us how to interface to the motion buffers) -- any run-time / ad-hoc commands/settings/requests that we might encode in script language and/or import from an ASCII file (i.e. patches, overrides, etc.) For the last item, we have found some pretty powerful ways to use the toolsets provided. For example, suppose I want to load machine-specific settings, tuning parameters, etc. from a patch file that is executed at run-time. We simply have our startup PLC execute: system("gpascii -2 < mypatches.plc 1>mypatches.out 2>mypatches.err"); The system command runs the gpascii command which reads and interprets our patches. The stdout (1) stream is redirected to mypatches.out and stderr (2) stream is redirected to mypatches.err. Those files can then be read or tested to determine if any errors occurred while loading the patches. This is all really powerful stuff and is exactly why we want to do the bulk of our coding in C (or C++ if Delta Tau someday makes that option available to us).
curtwilson Posted January 25, 2012 Posted January 25, 2012 We looked seriously at methods of commanding motion without going through the Script language and the command parser. There were several reasons we did not implement such a method. One is the complexity of a general-purpose solution. A cs_moveX() function seems simple, but there are 32 single axis possibilities, about 500 two-axis possibilities, and I don't even want to think about how many 3-axis and higher possibilities there are. Obviously, we couldn't have a separate function for each possibility, or even for each number of axes, so now we have a very complex function requiring you to specify the number of axes, which axes, etc. We judged this to be more complex for the user than assembling a command string limited to his particular subset of desired functionality. Another issue is that the Script interpreter, especially its sequencing engine, performs a lot of under-the-hood tasks for motion that are not very well handled in C, managing the pipelining and blending of moves. The pipelining can go seven stages deep, with each stage handshaking with the next to keep the pipeline full, as necessary (with many special cases). A general-purpose solution in C would force these into the user application; we know from those controllers that have attempted this in the past for anything sophisticated that this is very difficult and confusing, even for sophisticated software people. You can set many of the move parameters directly from C: pshm->Coord[x].Ta // Accel time pshm->Coord[x].Ts // S-curve time pshm->Coord[x].Tm // Move time (if > 0); feedrate (if < 0) pshm->Coord[x].IncAxes // Bit field of incremental mode bits for axes The action of the Script text commands TA, TS, TM, F, ABS, and INC is simply to set the values of these parameters, which are then used in the computation of subsequent commanded moves.
michaelthompson Posted January 26, 2012 Posted January 26, 2012 Curt, I believe that Delta Tau looked seriously at the possibility of building the C API interface for its motion programs. However, I have a difficult time accepting that what I specify via a motion program is really that much harder to do in C. Perhaps I've just been programming for too long (going on about 32 years now). At some level, the processing you describe all eventually has to be done. The real question then is about the data structures used to direct/control that processing and what sorts of interfaces you allow to manipulate those data structures. Even if you were to tell me that the internal data structures are ASCII streams and you interpret them on the fly, there are still ways that you can improve the way that a C programmer interfaces to the motion programs. I would assume that (somewhere internally) each motion program eventually becomes a linked list (or stream/array) of motion statements. And each motion statement is a linked list (or stream/array) of motion parameters (where TA, TS, F, X, Y, Z, etc. are parameters where some, like TA, TS, and F modify states). Running a motion program then is simply a matter of executing those linked lists, and creating a motion program should simply be a matter of building them. With the motion programs architected as linked lists of linked lists of linked lists (or even streams/arrays), it should be possible to do some interesting things like on-the-fly replacement of a program, statement, or parameter with another one (obviously, with proper controls to avoid collisions with the motion program executor). In any case, we can work with the existing architecture and interface. My post was really meant to probe the design space and get you guys thinking about different perspectives that different customers might have. I appreciate you taking time to entertain the discussion.
curtwilson Posted January 26, 2012 Posted January 26, 2012 Michael, Thanks for your interest. As I said, we spent a lot of time looking at these issues in setting up our architecture, as you are not the only user (or even more importantly, non-user!) desiring a more "pure" C-based approach. But in the end, we did not see that it would add real utility to people in most cases. However, I think you gloss over the key issue, what you call the "proper controls to avaoid collisions with the motion program executor". This, in my view, is the very difficult part, what I refer to as the "sequencing" issue. We have spent 25 years honing our internal sequencing engine to make it as powerful, flexible, and easy to use as possible. The user would have to take over much of this complexity in a C-based application if he wanted to do sophisticated motion trajectories. There are a couple of points in the process where it would not be too difficult to open it up to the user with an API. One is the end stage. The end result of all of our processing is a series of motion segments of the cubic polynomial form. The user could feed the queue of these segments with the cubic coefficients P0, V0, A0, and J, plus the time T for each segment. Mathematically, this is just one simple step removed from our PVT move description. There is a controller out there for which this is the main interface to the internal motion engine. People find it very difficult to use, as it pushes most of the complexity that we handle automatically into the user application. At the other end, if we limit ourselves to RAPID mode moves, which have virtually none of the difficult sequencing issues, it would not be too difficult to supply an API to permit "direct" commanding of moves from C without assembling a string. You may have noticed that this is the only move mode that we permit to be commanded directly from our Script PLCs -- this is because of the absence of most sequencing issues here. You could even break into an executing move at the instant of the command with a new move (distinct from blending at the end of the move as in other modes). However, the API function call here would be of a similar level of complexity to the sprintf/Command method you already have available. The question now comes whether it is worth implementing, testing, documenting, and supporting two ways of doing the same thing.
michaelthompson Posted January 26, 2012 Posted January 26, 2012 Curt, The user would have to take over much of this complexity in a C-based application if he wanted to do sophisticated motion trajectories. Not as I see it. The C programmer simply builds up a linked list structure using a Delta Tau API so that it looks like an encoded motion program (not the trajectories) and then tells it to run. It's just a different (and potentially more flexible and powerful) way of creating the motion program, not an elimination or replacement for them. Delta Tau still maintains and controls all of the motion program logic (both create and execute). I'm not sure if you are familiar with C++, but I'm going to give this example in C++ because it reads nicer (and more closely to the motion program syntax). Just keep in mind that all of this can be done in C (just with lots of pointer passing). One really nice thing about C++ is that I can have my methods return a reference to the object (i.e. return *this). This sort of coding style allows you to concatenate successive calls to the same object which is nice in a situation like this where you are appending statements to a motion program. int cs=3; // coordinate system MotionProgram myProgram(cs); myProgram .linear() .abs() .F(20) .TA(100) .X(50).Y(80).Z(30).endl() .run(); In the above example, endl() is the statement end (like the newline character in your motion program). I didn't put it on each of the earlier lines so the above program is actually a one-line motion program. However, there is no reason why I couldn't do the following: myProgram .N(100).linear().endl() .N(110).abs().endl() .N(120).F(20).endl() .N(130).TA(100).endl() .N(140).X(50).Y(80).Z(30).endl() .N(150).X(20).endl() .N(160).F(10).Y(20).endl() .run(); Now, my motion program has statement numbers and some more variety. And I could even do neat things like this: printf("%s",myProgram.toASCII()); // write out as ASCII string or int cs=3; // coordinate system MotionProgram p1(cs); p1.import("xyz.pmc").run(); The above snippet would allow me to load a motion program from a file and then run it. I can think of lots of other powerful ways to utilize a MotionProgram class in C++ or data structure in C. The user could feed the queue of these segments with the cubic coefficients P0, V0, A0, and J, plus the time T for each segment. This would be useful in some situations, but could possibly be accomplished with the motion program model described above. int cs=3; // coordinate system MotionProgram trajectory(cs); trajectory.P0(3).V0(2).A0(9).J(6).T(4).run(); The question now comes whether it is worth implementing, testing, documenting, and supporting two ways of doing the same thing. That is of course a valid question, particularly with the work load your developers are already under. Perhaps it is not worth reconsidering your decision, and that is OK. We certainly require no new functionality. But again I am only trying to bring different perspectives into your thought process. The Power PMAC hardware, firmware, and software are already pretty darn powerful, but there is nothing wrong with making the environment even more powerful should the opportunity or motivation arise.
Recommended Posts