base class for modular simulation components.
base class for modular simulation components.Simuation components perform a variety of functions: for example, a d2kComponent might be a controller, a payload, a terrain models, or a timer that triggers a callback function, among other things.
d2kComponents can be explicitly created by user-defined code, or can be created dynamically via a parameter file. When a d2kSimulator parses a p-file, it looks for sections starting with
* * #component0 * char classname[80] = "sriController"; * char label[80] = "myController"; * int enabled = 1; * ... * #component1 * char classname[80] = "relativePath"; * char label[80] = "path0"; * int enabled = 0; * ... * *and so on. Each of these sections specifies a different d2kComponent, with the given classname and label. The 'enabled' variable indicates whether the d2kComponent for the section should be created at all.d2kComponents interact with configurations in different ways. Some, like a controller, may be associated only with a single configuration, while others (e.g. a terrain model) may be associated with all configurations. Part of the process of parsing a p-file is to correctly associate configurations with d2kComponents. There are several different ways to do this:
- If there's only one configuration, and all of the d2kComponents can work with only one configuration, then nothing special is required in the p-file; all of the d2kComponents will automatically end up being associated with the configuration.
- If there are multiple configurations, and all d2kComponents can either work with exactly that number of configurations, or if they all don't care how many configurations there are, then again, nothing special is required.
- Otherwise, certain configurations need to be associated with certain d2kComponents, but not with others. This is accomplished by specifying a label for each configuration in the p-file, and then specifying which configurations are used for some or all of the d2kComponents. A configuration label is specified in the following manner:
* * #cfg0 * char label[80] = "rover"; * ... * * #cfg1 * char label[80] = "arm"; * ... * *Thus, the first configuration will be called 'rover' and the second 'arm'. Then, suppose there are two controllers. The configurations would be associated by:#component0 char classname[80] = "roverController"; char cfg0[80] = "rover"; ...
#component0 char classname[80] = "sriController"; char cfg0[80] = "arm";
The above p-file segment assumes that the roverController and sriController class don't define specific configuration names. For example, if a certain multi-robot controller has a leader configuration and a follower configuration, then it'd be easier to have the configuration variable names "leader" and "follower" rather than trying to remember whether "cfg0" is the leader and "cfg1" is the follower, or vice-versa. In this case, the p-file section for the controller might look like this:
* * #component0 * char classname[80] = "multicontroller"; * char leader[80] = "rover"; * char follower[80] = "walker"; * ... * *Or, if you're sure that the first and second configurations should be associated with the first and second configuration variables of the multicontroller (or if the multicontroller didn't care which configuration was which), then you could just eliminate the 'leader' and 'follower' p-file variables. But different d2kComponents expect different numbers of configurations, and sometimes in different orders, so this may not always work.
d2kComponents that can work with any number of configurations must either have no configurations explicitly identified, or must have the "numConfigurations" variable specified, in which case the values for the configuration variables from 0 to numConfigurations-1 will be read from the p-file. (Otherwise, there's no way of knowing how many variables to try to read.) It is up to each d2kComponent class to define the behavior of one or more of the variables are not specified; it may be okay for some, but not for others.
Finally, while it's a good idea to know the specific behavior of the d2kComponents you're using, there are two general rules to keep in mind:
- When in doubt, be maximally specific with configuration variables
- If there's only one configuration, you probably don't need the configuration variables
* * #cfg0 * char label[80] = "configurationA"; * ... * #component0 * char classname[80] = "myComponent"; * char roverCfg[80] = "configurationA"; * *If getCfgName() is not overridden by a derived class, then the variable name would be cfg0 instead of roverCfg. cfg0, cfg1, ... can always be used, regardless of whether getCfgName() is overridden.
If no configurations are explicitly specified in the component section of the p-file, then the list of configurations will be used as-is from the evaluator.
Finally, getCfgName may return a pointer to a static array, so do not expect the contents of the string pointed to by getCfgName() to remain unchanged over multiple calls.
#d2kComponent{int} char class[80] = "{classname}"; char label[80] = "{your_label}"; int enabled = 1; ...Setting enabled to '0' will cause the entire section to be ignored. Any class-specific parameters follow the header given above. Derived classes can override this method, but should call their parent class's method in their own implementation.
The order in which setVariables() is called for all d2kComponents is the same as the order in which the d2kComponents occur in the p-file.
The order in which setVariables() is called for all d2kComponents is the same as the order in which the d2kComponents occur in the p-file.
The order in which simInit() is called for all d2kComponents is the same as the order in which the d2kComponents occur in the p-file.
The following descriptiong of configuration association may be a bit unclear, but the guiding principle is this: allow a minimum of specification information if it's possible to do an obvious 'right thing', but also allow full specification if the user so desires. Keeping this in mind is probably more useful than understanding all the details.
After a derived class calls d2kComponent::init, cfgLabels will be initialized to contain cfgLabelRecords for those configurations that were explicitly associated with the d2kComponent. The 'cfg' entry of each cfgLabelRecord will be set to point to the configuration with label matching the value of 'label', and the record's argNum will be set to indicate which configuration variable was set. However, if there was an error of any sort (as evidenced by a return value of zero), then cfgLabels may not have been properly initialized.
Additionally, if any configurations were explicitly associated with the d2kComponent, then 'cfgs' will contain pointers to only those configurations. Otherwise, cfgLabels.n will be zero and 'cfgs' will contain all of the configurations known to the d2kSimulator. If there is a single, non-ambiguous configuration, then it will be assigned to 'cfg'.
if the derived class's forceCfgResoultion method returns 1, then all configuration associations must be resolved in d2kComponent::init(); if d2kComponent::init() can't figure out which configurations are associated with the component, then an error will occur and the method will return 0.
If there is a known error condition, such as fewer than minCfgs() configurations passed by the d2kSimulator or a bad valued for a cfgLabel was specifiedc, then an error message will be printed and 0 will be returned.
In the case that two configuration variables have the same value (e.g. the same configuration has been associated with multiple cfgLabels), cfgs will not contain any duplicate entries
Alphabetic index HTML hierarchy of classes or Java