Received: from ultb.isc.rit.edu by karazm.math.UH.EDU with SMTP id AA20066 (5.65c/IDA-1.4.4 for ); Thu, 31 Oct 1991 22:34:38 -0600 Received: by ultb.isc.rit.edu (5.57/5.3 (Postmaster DPMSYS)) id AA13870; Thu, 31 Oct 91 23:30:18 -0500 Received: from boron.CS (boron.ARPA) by junior.rit.edu (4.1/5.17) id AA03666; Thu, 31 Oct 91 23:18:09 EST From: jdb9608@cs.rit.edu (John D Beutel) Message-Id: <9111010418.AA03666@junior.rit.edu> Subject: glove interface standard To: glove-list@karazm.math.uh.edu Date: Thu, 31 Oct 91 23:32:52 EST X-Mailer: ELM [version 2.3 PL8] I hope there are at least a few people still interested in this. I'd like the standard to do as much as it possibly can. I suggest we make the glove interface standard complex and smart. Normally I would prefer something simple and elegant, but since we don't have diffinitive specs on the glove and we don't really know what we'll figure out how to make it do next, we shouldn't make a standard that will become obsolete in a few months. The key is to abstract the glove functionality, so what the glove does (and what the program expects it to do) is not linked to a particular method. Different machines and different schemes will use different methods, which will yield different capabilities, but if the standard can put those capabilities in abstract terms then the program can ask for what it needs and the interface can worry about how to do it. See how you like this for abstraction (any additions?): sample rate (Hz) x, y, z resolution each finger, w/ resolution response time (from physical sample to availability of data) synch glove to computer (or not) buttons, pad, and lo-res joystick data call a user function when data arrives (or not) It's not easy to know how the abstraction should be done. For example, should the X, Y, and Z values be handled seperately or together? Seperately makes more complexity, but e.g. if someone invents a way of getting better Z resolution than X & Y resolution then seperate would be better. It's not just a question of the absolute capabilities of the interface (software or hardware)---there are tradeoffs. For example, what if we find a way to turn off the fingers and get a faster sample rate? If the app just wants a 3D coordinate, then this is a good tradeoff. If the app needs the fingers too, then it isn't. This futuristic interface could do either faster sampling or finger data, but not both. So, it can't simply report its sampling rate or finger resolution because it depends. That's why I think a negotiation with the interface would be a great way to do it (as someone already suggested). Of course, it can't be too complicated, or who'd want to use it? One function call would be best. The application could give the interface its requirements for each abstraction: minimum acceptable value maximum acceptable value prefered value priority The interface resolves conflicts the best it can, making tradeoffs in order of priority, and returns what it can do. (E.g., you prefered a sample rate of 30 Hz but the best I can do is 17 Hz. It's within your acceptable range, so here it is.) If the application doesn't care about an abstraction (e.g., doesn't care what the X, Y, Z resolution is) it can say so (e.g., specify -1 as its value requirements). Likewise, if the app doesn't need an abstraction at all (e.g., doesn't want any lo-res data) then it can say so (e.g., specify 0 as its priority). The interface sorts the abstraction requirements in order of priority, and then attempts to grant each its prefered value. If that becomes impossible, then it tries to get it within the acceptable value range. If that is still impossible, then the interface could either do its best, or sort the requirements in a different order than their priority and try again. The prefered value of a high priority may make impossible the acceptable value of a lower priority, but if the lower priority is satisfied first then the higher priority may still be able to be within the acceptable range. For 7 abstractions, the 7! possible orders of priority are about 3000. For 9 abstractions, the 9! orders go up to the impractical area of 350,000. So, doing all possible orders of priority may be impossible, but it may be easy to swap a few of the ones that the standard knows will make a difference. Whether or not the interface implementation is smart enuf to do this doesn't really matter. If the interface doesn't try different orders, or if it does but it still can't satisfy the application's request, then it just returns what it can do. The skill of the tradeoffs that the interface makes---and its raw capability---will increase with time, but at least right now if the interface can't do it, it can say so thru the standard, and the app can decide for itself whether it's good enuf or not. If the interface can't satisfy the app's request, the app can always make another request with looser constraints. I doubt that app's will do this very often---that's the idea of specifying an acceptable range and priority; let the interface do all the work trying to get it right. In most cases, the app makes one call to the interface, and the it does the best that it can, (initializes the glove?), and returns what it's going to do (e.g., the finger data will range from 0 to 3). The app uses the return values (instead of constants) to interpret the data. So, if you wire your glove's fingers directly to an IO port to get faster sampling and better resolution, the interface you write returns that its finger data will range from 0 to 255, and the application that only needs 0 to 3 will work just as well with your better data. Passing the abstraction requests via dynamic means (i.e., "tags") also sounds like a good idea (someone else suggested earlier). That way, if other abstractions are added later (e.g., a glove with two X,Y,Z coordinates) then programs could request these new abstractions from old interfaces and still compile. If we put the standard names in a datastructure, then the compiler won't work with the older .h interface files, or the function call's arguments will be wrong. If we use "tags", then the interface can ignore the things it doesn't know, or act intelligently by telling the app that it can't do those things. The app can decide for itself whether it really needs that extra X,Y,Z coordinate or not. Some apps may really need it, and won't be written to be downwardly compatable. Other apps may not need it---it may be strictly an option or a fringe. For those apps, it would be a shame to not be able to use them with older interfaces or simpler hardware just because the names were hardcoded and the compiler won't compile the new names. Using tags will make the interface a little more complicated, but not significantly so, especially considering that the support functions only need to be written once. I wouldn't mind writing them for the ST, and they'd be practically the same on any computer. Here's an example of what the code might look like: -------------------------- in stdglove.h ------------------------- struct negotiate_glove { char *name; /* the tag, standardized */ long minimum, /* acceptable range, std bit length */ preference, /* prefered value */ maximum; /* acceptable range */ int priority; long offer; /* return value of what interface can do */ /* 0 == not available */ /* double the number of elements here to allow for signed ranges? */ /* e.g., -127..128 instead of just 255? */ } --------------------------- in app.c ------------------------------ struct negotiate_glove gn[6] = { {"rate", 1, 14, 30, 1, 0}, {"sync", 1, 1, 1, 2, 0}, {"xyz", 10, 255, 1000, 3, 0}, {"finger1", -1, -1, -1, 4, 0}, {"lores", 0, 0, 0, 0, 0}, /* actually, maybe for those */ /* things we don't want it would */ /* be easier to just not ask for */ /* them. */ {"end"} } main() { init_glove( gn); if( get_offer( gn, "rate") != 14) fprintf( stderr, "warning: optimum sample rate unavailable"); /* etc... */ } We could include an option to init_glove so that if it can't satisfy the app's request within the given acceptable values, then it prints a nice error message and aborts, so the app doesn't even have to worry about checking the return values if it doesn't want to. The tags do make the interface more complicated, but not significantly so. They will slow the initialization a little, but it's not noticable. They will slow the retrieval of the sample data a little, but only a few microseconds (unless someone can come up with a clever macro for this? I haven't thought much about it.) Milliseconds are significant, but what's a few microseconds at 30 Hz? Please think about whether a complex standard like this would be good for this glove environment, and express your opinion. -- J. David Beutel 11011011 jdb9608@cs.rit.edu "I am, therefore I am."