This is just a request for comment, and specifically neither a promise to perform any particular action nor a requirement that others do so. It is especially not a flame targeted at anyone.
I was reading an interesting page http://www.joelonsoftware.com/uibook/fog0000000249.html talking about user interfaces. Before it delves into a bunch of details not really pertinent to Orbiter, it makes an observation which is stated elsewhere as "The Law of Least Astonishment". This law is basically that a program should act as the user intuitively expects it to, or in other words, in the way that astonishes the user the least.
In the GUI world that the page originally references, minimum astonishment is usually accomplished by doing things the way all the other programs do. In a sense it boils down to Follow Microsoft (in Windows) or Apple (on a Mac), not because they are biggest, and certainly not because they are best, but just because almost all users have their intuition trained by using the Big Guys' programs.
In the Unix model, programs are as small and simple as possible, do precisely one thing, and interact with other programs easily. It is said that "Those that do not learn the Unix model are doomed to re-implement it... poorly."
But what about MFDs? To addon developers, Orbiter and its library is the operating system, just as Windows is for Word, Mac OSX is for ITunes, and Firefox is for web pages and Javascript therein.
I bring all this up because of the Interplanetary MFD. The large community here that swears by it testifies to its utility, but I don't use it. For simpler tasks, I use TransX, and for more complicated ones, I either write a tool myself, or fly it by the seat of my pants (at much reduced accuracy) just because I can't learn how to use IMFD. And that's not from lack of trying.
As an example: A while back I asked about how to use IMFD to plan a course correction for a direct lunar-impact mission such as the old Rangers and Surveyors. These missions are launched into a trajectory which directly results in a near-vertical lunar impact without any lunar orbit insertion or powered descent. Ranger just snapped pictures through to impact, while Surveyor used a braking rocket 25 seconds before impact to start a soft-landing sequence.
I wanted to not just hit the moon, but do so at the historical time and place appropriate to the mission. Also, my launch vehicle puts the spacecraft on a lunar impact trajectory directly from the ground, so there is never a parking orbit, and therefore no time or place to set up the transfer.
The documentation for IMFD is out of date, and furthermore is more of a reference than a user guide or tutorial. This is the kind of documentation which is easy for the developer to write, and is useful to those who already know the basics of the program.
There are many tutorials out there, but the majority of them are also out of date, and all of them seem to be complete missions from launch to landing. I don't want to use IMFD for launch, because as I said my launch vehicle does it for me automatically.
I suspect that there is a way for IMFD to do what I ask of it, but I don't know how to find out. I think BaseApproach is related to the answer, but I don't know if the BaseApproach MFD is still needed, still current, or incorporated into the latest version of IMFD.
If I seem unduly harsh on IMFD, it is only because I wish to provoke a response. I learned TransX years ago, and I am quite adept with it now, but I remember that it was quite a steep learning curve for me also. I have just gotten used to it, and it astonishes me the least now. TransX shaped my user model, because I learned it first.
I am quite sure that my own MFDs have been headaches for other users, just because I don't follow the user model they learned. I try to follow the model of TransX "with improvements" in my MFDs. This resulted in the interface for PEGAutopilot. The "improvements" I thought I would make are to show more numbers at once to improve reading speed and to have a big change set of buttons and a small change set.
Now in some ways PEGAutopilot is a simple MFD. It is designed somewhat in the Unix model to solve one problem extremely well. This problem is launch from the surface of the Earth to some specified target orbit. The variables you can set are the target orbit parameters, directly in the form PEGAutopilot expects. I wrote it with basic functionality in mind, and only one user in mind, a user who has intimate knowledge of how PEG works. That user is of course myself, and PEGAutopilot astonishes me very little. However, I can imagine that many people don't even know what TPEGStart means and what are the intelligent choices for it.
PEG really is simple. Disregard the 2500 lines of code that backs it up. It just takes a target horizontal speed, vertical speed, and altitude at burnout and attemts to hit those targets. Except...
...The document I based PEG on was designed to guide a launch vehicle all the way from second stage start to a lunar impact trajectory as described above, so of course I wrote the program to do that mission also.
...You can't use PEG all the way from the ground, so I inculded a first-stage guidance program.
...You can't use PEG all the way to orbit, you must cut off guidance several seconds before you cut off the engines.
So, I included a bunch of tuning parameters that allowed a knowledgable user (myself) to take care of all the exceptions.
My point is that PEGAutopilot solves a much smaller set of problems than either TransX or IMFD, and it is still too complicated. I am posting PEGAutopilot as a BAD example, of the kind of thing I am trying to fix.
My simplest MFD is the Accelerometer. It approaches the "Dilbert Ideal" user interface in that it has only one button, and I pushed it before I published it.
My most popular MFD is BurnTimeCalc, which I can't take credit for, but likewise can't disclaim blame for. It was originally written by someone else, but after I was done with it, I had modified it beyond recognition.
I have written many MFDs that I haven't even published, to solve one or another problem that I had. It's not the Unix ideal, because the MFDs don't interact with eachother (you can't form pipelines) but at least they are small sharp tools that do one thing well.
Also, many MFDs exist because it's the easiest way to write an autopilot. Should this be? Should Orbiter support the concept of an autopilot completely distinct from an MFD?
So, what do I propose?
One way to do it now is:
1. Clean break between MFD and Autopilot
This one is pretty easy, and probably doable already with Orbiter '06. It's just that no one does it, and if an autopilot has no MFD, it has no user interface at all. So, we just need a convention that when you make an autopilot, you don't make an MFD to go with it, you use the standard Terminal MFD for your interface (see below). We will call either an MFD or an autopilot a Plugin.
2. Pipelining
Each plugin has a method called receiveCommand() which takes a commanding plugin identifier and a string command of arbitrary length. Strings for flexibility, but each receiving plugin gets to define its own protocol on top of it. Maybe after using this model for some time, a standard protocol evolve. Each plugin would have to document well its own interface, in human-readable form. There also needs to be a way to find out if BurnTimeCalc is loaded, load it if needed and available, and complain if it is not. Maybe some plugins would continue to work with some functions not available, but probably most would refuse to run if its dependencies were not met. This refusal to run would need to be handled in a clean non-CTD manner also.
3. Standard library
The library plugins would be like 'ls' and 'cat' in Unix. As an example, the lowest level plugin might take a steering command and translate it into a combination of engine steering, RCS jet firing, or control surface setting to implement the steering. This might be a function of the vessel rather than any plugin. The next level would take a requested attitude and attitude rate and use the lower level to steer to it. Higher level things like TransX would request their burn attitude from the mid-level attitude autopilot rather than displaying a manual vector plot and having the (human) pilot steer to it. Also, a standard MFD would be a terminal, which just takes commands and prints them out (and perhaps logs them) and perhaps enables command-line strings to be sent to an arbitrary plugin.
So, in the example:
In order to be successful, this system needs to be supported and mandated by Orbiter itself. This way every vessel and plugin is required to play nicely with every other.
This needs to be mandated from the top. The counter-example is CVE, the Common Vessel Extensions. This library extended the functionality of vessels, and allowed vessels to interact with each other and be stacked. It proved to be too heavy and no one used it, so CVELite was developed in response. It still wasn't used. Instead, the Attachment API was added to Orbiter and vessels which wanted to interact were required to use it. Attachment largely made CVE obsolete.
I have no illusions that anything I propose will be implemented in Orbiter '09, or even ever. It would require cooperation from Martin, and perhaps breaking all existing MFDs, autopilots, and vessels.
So, what do you all think? Is this interaction model any good? Would anyone like to propose an alternative?
I was reading an interesting page http://www.joelonsoftware.com/uibook/fog0000000249.html talking about user interfaces. Before it delves into a bunch of details not really pertinent to Orbiter, it makes an observation which is stated elsewhere as "The Law of Least Astonishment". This law is basically that a program should act as the user intuitively expects it to, or in other words, in the way that astonishes the user the least.
In the GUI world that the page originally references, minimum astonishment is usually accomplished by doing things the way all the other programs do. In a sense it boils down to Follow Microsoft (in Windows) or Apple (on a Mac), not because they are biggest, and certainly not because they are best, but just because almost all users have their intuition trained by using the Big Guys' programs.
In the Unix model, programs are as small and simple as possible, do precisely one thing, and interact with other programs easily. It is said that "Those that do not learn the Unix model are doomed to re-implement it... poorly."
But what about MFDs? To addon developers, Orbiter and its library is the operating system, just as Windows is for Word, Mac OSX is for ITunes, and Firefox is for web pages and Javascript therein.
I bring all this up because of the Interplanetary MFD. The large community here that swears by it testifies to its utility, but I don't use it. For simpler tasks, I use TransX, and for more complicated ones, I either write a tool myself, or fly it by the seat of my pants (at much reduced accuracy) just because I can't learn how to use IMFD. And that's not from lack of trying.
As an example: A while back I asked about how to use IMFD to plan a course correction for a direct lunar-impact mission such as the old Rangers and Surveyors. These missions are launched into a trajectory which directly results in a near-vertical lunar impact without any lunar orbit insertion or powered descent. Ranger just snapped pictures through to impact, while Surveyor used a braking rocket 25 seconds before impact to start a soft-landing sequence.
I wanted to not just hit the moon, but do so at the historical time and place appropriate to the mission. Also, my launch vehicle puts the spacecraft on a lunar impact trajectory directly from the ground, so there is never a parking orbit, and therefore no time or place to set up the transfer.
The documentation for IMFD is out of date, and furthermore is more of a reference than a user guide or tutorial. This is the kind of documentation which is easy for the developer to write, and is useful to those who already know the basics of the program.
There are many tutorials out there, but the majority of them are also out of date, and all of them seem to be complete missions from launch to landing. I don't want to use IMFD for launch, because as I said my launch vehicle does it for me automatically.
I suspect that there is a way for IMFD to do what I ask of it, but I don't know how to find out. I think BaseApproach is related to the answer, but I don't know if the BaseApproach MFD is still needed, still current, or incorporated into the latest version of IMFD.
If I seem unduly harsh on IMFD, it is only because I wish to provoke a response. I learned TransX years ago, and I am quite adept with it now, but I remember that it was quite a steep learning curve for me also. I have just gotten used to it, and it astonishes me the least now. TransX shaped my user model, because I learned it first.
I am quite sure that my own MFDs have been headaches for other users, just because I don't follow the user model they learned. I try to follow the model of TransX "with improvements" in my MFDs. This resulted in the interface for PEGAutopilot. The "improvements" I thought I would make are to show more numbers at once to improve reading speed and to have a big change set of buttons and a small change set.
Now in some ways PEGAutopilot is a simple MFD. It is designed somewhat in the Unix model to solve one problem extremely well. This problem is launch from the surface of the Earth to some specified target orbit. The variables you can set are the target orbit parameters, directly in the form PEGAutopilot expects. I wrote it with basic functionality in mind, and only one user in mind, a user who has intimate knowledge of how PEG works. That user is of course myself, and PEGAutopilot astonishes me very little. However, I can imagine that many people don't even know what TPEGStart means and what are the intelligent choices for it.
PEG really is simple. Disregard the 2500 lines of code that backs it up. It just takes a target horizontal speed, vertical speed, and altitude at burnout and attemts to hit those targets. Except...
...The document I based PEG on was designed to guide a launch vehicle all the way from second stage start to a lunar impact trajectory as described above, so of course I wrote the program to do that mission also.
...You can't use PEG all the way from the ground, so I inculded a first-stage guidance program.
...You can't use PEG all the way to orbit, you must cut off guidance several seconds before you cut off the engines.
So, I included a bunch of tuning parameters that allowed a knowledgable user (myself) to take care of all the exceptions.
My point is that PEGAutopilot solves a much smaller set of problems than either TransX or IMFD, and it is still too complicated. I am posting PEGAutopilot as a BAD example, of the kind of thing I am trying to fix.
My simplest MFD is the Accelerometer. It approaches the "Dilbert Ideal" user interface in that it has only one button, and I pushed it before I published it.
My most popular MFD is BurnTimeCalc, which I can't take credit for, but likewise can't disclaim blame for. It was originally written by someone else, but after I was done with it, I had modified it beyond recognition.
I have written many MFDs that I haven't even published, to solve one or another problem that I had. It's not the Unix ideal, because the MFDs don't interact with eachother (you can't form pipelines) but at least they are small sharp tools that do one thing well.
Also, many MFDs exist because it's the easiest way to write an autopilot. Should this be? Should Orbiter support the concept of an autopilot completely distinct from an MFD?
So, what do I propose?
- A clean break between MFDs and autopilots. Most Autopilot MFDs are written this way anyway so that they can continue to operate when the MFD is not visible.
- A way for MFD/Autopilots to pipeline. This involves a way to transfer information from one to another, and a way for an MFD or autopilot to depend on another (start it as needed, complain if the dependency is not met, etc). In the Unix model this is done by the system supporting piping text from one process to another, by the shell making it easy to create pipes, and by having a large set of standard tools.
- A standard set of autopilots in a pipeline.
- Breaking up complicated MFDs or autopilots into many smaller pieces that interact well with eachother.
One way to do it now is:
- Calculate the departure hyperbola we want in TransX. This then reports a time to eject and a DeltaV.
- Manually copy those numbers into BurnTimeCalc. The time one is especially hard because it depends on pushing a button manually at just the right time.
- Before the burn, turn to prograde using the [ autopilot key.
- Let BurnTimeCalc control the burn with the main engine throttle, and let the prograde autopilot maintain attitude
- It is a new feature, so that old-timers like me don't use it.
- TransX and IMFD both had to write one, even though BurnTimeCalc predated the autoburn in both (in fact, BurnTimeCalc was written precisely to fill this hole in TransX, long long ago.)
1. Clean break between MFD and Autopilot
This one is pretty easy, and probably doable already with Orbiter '06. It's just that no one does it, and if an autopilot has no MFD, it has no user interface at all. So, we just need a convention that when you make an autopilot, you don't make an MFD to go with it, you use the standard Terminal MFD for your interface (see below). We will call either an MFD or an autopilot a Plugin.
2. Pipelining
Each plugin has a method called receiveCommand() which takes a commanding plugin identifier and a string command of arbitrary length. Strings for flexibility, but each receiving plugin gets to define its own protocol on top of it. Maybe after using this model for some time, a standard protocol evolve. Each plugin would have to document well its own interface, in human-readable form. There also needs to be a way to find out if BurnTimeCalc is loaded, load it if needed and available, and complain if it is not. Maybe some plugins would continue to work with some functions not available, but probably most would refuse to run if its dependencies were not met. This refusal to run would need to be handled in a clean non-CTD manner also.
3. Standard library
The library plugins would be like 'ls' and 'cat' in Unix. As an example, the lowest level plugin might take a steering command and translate it into a combination of engine steering, RCS jet firing, or control surface setting to implement the steering. This might be a function of the vessel rather than any plugin. The next level would take a requested attitude and attitude rate and use the lower level to steer to it. Higher level things like TransX would request their burn attitude from the mid-level attitude autopilot rather than displaying a manual vector plot and having the (human) pilot steer to it. Also, a standard MFD would be a terminal, which just takes commands and prints them out (and perhaps logs them) and perhaps enables command-line strings to be sent to an arbitrary plugin.
So, in the example:
- Calculate the departure hyperbola we want in TransX, as before, then press 'Execute'.
- TransX commands a BurnTime library autopilot to burn so much DeltaV centered on a particular time.
- TransX commands the Attitude library autopilot to point at the average prograde vector during the burn
- BurnTime commands the main engines to start and stop at the right time, and reports to TransX when done.
In order to be successful, this system needs to be supported and mandated by Orbiter itself. This way every vessel and plugin is required to play nicely with every other.
This needs to be mandated from the top. The counter-example is CVE, the Common Vessel Extensions. This library extended the functionality of vessels, and allowed vessels to interact with each other and be stacked. It proved to be too heavy and no one used it, so CVELite was developed in response. It still wasn't used. Instead, the Attachment API was added to Orbiter and vessels which wanted to interact were required to use it. Attachment largely made CVE obsolete.
I have no illusions that anything I propose will be implemented in Orbiter '09, or even ever. It would require cooperation from Martin, and perhaps breaking all existing MFDs, autopilots, and vessels.
So, what do you all think? Is this interaction model any good? Would anyone like to propose an alternative?