Search STEP Tools Web Support

Programming STEP Applications

Early use of the STEP application protocols was mostly centered on geometry exchange, and the use of an EXPRESS compiler to generate C++ or Java classes has been a very useful technique for working with STEP geometry and topology. The ROSE C++ and Java libraries, as well as the SDAI C library, all follow this architecture and have been used to build geometry interfaces for many CAD systems.

More recent STEP application protocols have added more concepts layered on top of the EXPRESS. These concepts, sometimes called application objects or ARM objects, are described using mapping tables within the standard that specify the arrangement of a collection of underlying EXPRESS objects.

Working with these higher-level concepts is possible with the ROSE library, and many applications have done so, but it requires an intimate knowledge of the standard and the mapping tables. This knowledge takes time to acquire and must be transferred into a substantial amount of somewhat tedious code.

The problem has been compounded in recent years because the newer STEP standards have focused on many of the manufacturing properties and other non-geometric aspects of the product data, so the number of these conceptual ARM objects has grown.

In response to these factors, we have designed a programming interface that works at the conceptual ARM level, and incorporates the information in the AP mapping tables to simplify programming. This new interface is a layer above the EXPRESS classes of the existing ROSE C++ library, so the new interface functions simplify work with ARM concepts, while the EXPRESS-level functions are still available to manipulate data at the detailed geometry and topology level. .

The first AP to go through this process was AP-238. STEP Tools is using it with considerable success to create applications for the new AP-238 protocol for CNC machining data (milling, turning, cutting etc.). Since we were developing the application protocol at the time, this served two purposes. Compiling the mapping tables provided a good quality check, while the resulting library enabled quick testing of the standard.

To completely cover other APs will require a project to go through the mappings of that AP, but because of the overlap between common concepts like geometric dimensioning and tolerancing (GD&T) and manufacturing features, partial libraries are available for a number of APs.

Programming the STEP manufacturing attributes is complex using the methods developed for exchanging geometry information. Each feature in the AP-224 model has about six properties and each of these properties translates into about 6 entities in the STEP life cycle model. The result is a combinatorial explosion of 36 entities that must be correctly defined and linked in order to fully represent the feature. Creating all of these entities is very frustrating for programmers.

An Example

Create a position tolerance.

RoseDesign * d;
Datum_reference *datum_a;
Datum_reference *datum_b;
Datum_reference *datum_c;
stp_shape_aspect * sa;

Position_tolerance * pt = Position_tolerance::newInstance(d);

pt->put_tolerance_value (make_inch_quantity (d, 0.0001, "position"));

pt->add_reference_datum (datum_a->getRoot());
pt->add_reference_datum (datum_b->getRoot());
pt->add_reference_datum (datum_c->getRoot());

pt->put_applied_to (sa);

stp_advanced_face * face;

Datum_feature_face *ff = Datum_feature_face::newInstance (d);
ff->add_its_face (adf); 

Datum_defined_by_feature *df = Datum_defined_by_feature::newInstance (d);
df->put_datum_name ("A");
df->put_defined_by (ff->getRoot());

Datum_reference *dat = Datum_reference::newInstance (d);
dat->put_precedence (0);
dat->put_referenced_datum (df->getRoot());

Compiling and Linking

When you compile your programs, you will need the usual include paths for the ROSE library and class library, plus includes for the ARM classes, and base ARM engine library. You may also need the include path for the STIX AIM helper functions. The STEP ARM classes are in the "stp_arm" include directory. Add the following to your C++ project settings

-I"$(ROSE_INCLUDE)"\stmodule
-I"$(ROSE_INCLUDE)"\stp_arm
-I"$(ROSE_INCLUDE)"\stp_aim
-I"$(ROSE_INCLUDE)"\stix
-I"$(ROSE_INCLUDE)"

When you link your programs, configure your C++ project settings as usual, but add the ARM class library and ARM engine library to your link input. We also need the STIX AP Utilities and the ROSE Math utilities.

# on windows systems
stp_arm.lib stix.lib stp_aim.lib stmodule.lib rosemath.lib rose.lib

# on unix systems
-lstp_arm -lstix -lstp_aim -lstmodule -lrosemath -lrose  

In your main, include classes for your ARM objects. Including ARM.h will bring in all arm classes. If you do not need arm classes in your main, but want to set things up for other source files, you can just include STModule.h.

In your main, call:

stplib_init();
ST_MODULE_FORCE_LOAD();

After you read your file, you can call the ARMPopulate() function to compute all of the backpointers and annotate AIM objects with ARM components.

RoseDesign * design = ROSE.findDesign ("filename");
ARMPopulate (design);

ARMCursor cur;
cur.traverse(des);
cur.domain(Project::type());

printf ("Looking for project\n");

Project * proj = ARM_CAST(Project, cur.next());

if (!proj) {
    ARMpopulate(des);

    cur.traverse(des);
    proj = ARM_CAST(Project, cur.next());
    
    if (!proj) {
        printf ("No project found\n");
        return;
    }
} 

Interface Classes vs Implementation Classes

For an application that creates new data, you must use the Implementation classes. For applications that read and process data, you are better off using interface classes because they allow you to have more generality and take advantage of inheritance on the ARM level.

Structure of a STEP Application Protocol

STEP is being developed incrementally. Whenever a new protocol is defined its future extensions cannot be predicted. Therefore, STEP uses a two level approach in its data modeling.

On the first level an Application Requirements Model (ARM) is developed to capture the concepts and associated information for a specific application domain. The model is developed in enough detail to allow testing.

The second level of modeling maps the information requirements determined by the ARM into the STEP life cycle entities. This requires each ARM entity to be broken down into its constituent life cycle entities. The entities are linked together by rules described in a mapping table.

The result of the mapping is a new model called the Application Interpreted Model or AIM. The AIM defines the standard that is to be used for data exchange. The ARM is for information only. The goal of the AIM is to harmonize all of the STEP Application Protocols by allowing properties to be dynamically added and removed from a product object as it moves through the product life cycle. To date more than 40 protocols have been developed so it has been successful at the modeling level (see Appendix).

However, the following aspects of the mappings cause controversy:

The definition of tolerances for the AP-238 ARM model given in ISO 14649-10 illustrates how the information is expanded. Consider the following definitions for a tolerance and its usage in a round_hole.

TYPE toleranced_length_measure = length_measure;
END_TYPE;

ENTITY round_hole
SUBTYPE OF (machining_feature);
   diameter:		toleranced_length_measure;
   change_in_diameter: 	OPTIONAL taper_select;
   bottom_condition: 	hole_bottom_condition;
END_ENTITY;

When this definition is mapped into the integrated definitions it is necessary to consider three weaknesses.

First there is no definition for the upper and lower limits of the tolerance. A full definition is given in the integrated resources.

Second, there is no definition for the tolerance for the position of the hole. This is more difficult because the location of the hole is inherited from one of the super-types. Such "misplaced values" occur quite frequently in ARM models because the developers are considering the information requirements from one perspective. In this case the machining perspective where for ease of modeling it is desirable for a common super-type to model the location of all the features at the top of the stock. However, from the tolerance perspective each of the different features may need a different kind of tolerance and this becomes difficult if the features inherit the location from a common super-type.

Third in design applications a generic positional tolerance is modeled with respect to three datum faces. These faces will be on another part of the model and probably define another manufacturing feature as illustrated in Figure 1. However, it is also quite possible for them to belong to something else such as a fixture.

All of these requirements were enabled when the AP-238 model was mapped to the integrated resources but at the cost of converting the single entity definition for a hole shown into about 36 entity definitions in the life cycle integrated resources. This makes programming a round-hole a formidable task that is not made easier by the terse notation used in the mapping tables.

However, there may also be an implementation problem. Figure 2 illustrates the implementation problem by showing how a manufacturing feature is defined across the life cycle. On the left of the figure the feature first gains identity as a shape aspect that has geometry and tolerances. In the middle of the figure the feature is classified as a hole by a production planner and is given appropriate parameters. On the right of the figure a manufacturing method is defined for the hole and it gains further properties that define how it will be machined.

When the hole is first characterized in the design phase it could be a round pocket or a hole. Therefore, it does not have any process specific parameters at this stage. When the planner classifies the feature some parameters are set but others are still unknown because the final manufacturing order has not been set. Finally at the manufacturing level the order has been set and the volume of material that must be removed by each operation can be computed in the context of the chosen sequence.

The second row of Figure 2 shows the object properties just discussed. In practice, many more properties must be defined to fully describe the round hole from each design perspective. In general the hole grows more properties as it moves through the life cycle. However, this is not always the case. For example, depending on the application, the tolerance data defined in the design stage may be ignored at the machining stage. On the other hand if the next stage is CMM inspection then this data will become important again and some of the manufacturing and planning attributes may become optional.

The third row of the figure illustrates the impact of these changes on the AIM. As shown on the left before the feature is classified it only has one type (shape_aspect). After it has been classified it gets two new types. The first is generic to all manufacturing features (instanced_feature). The second is specific to this kind of feature.

Clearly the properties of the ARM object and its root AIM entity grow and shrink over time. This is the source of the programming difficulty. In effect proper programming of the round_hole object requires a form of very late binding where new properties can be added as attributes as it moves through the life cycle. If all design objects took the same path to manufacturing then this could be done using conventional object technology, but this is not the case. How a design property gets classified as a manufacturing feature is at the discretion of the planner, and how it gets machined on a CNC is at the discretion of a machinist. Each decision affects the properties that must be added or subtracted at that stage.

The New Implementation Method

Figure 3 further illustrates the mapping problem by showing the AIM life cycle entities used to define the depth of a pocket.

There are three parts to this mapping. On the left the entities belonging to the feature are shown. There are two entities. This first entity has multiple types as per the EXPRESS information model. This entity is the root of the feature and is the entity that represents the object for three stages of the life cycle (design, planning and manufacturing). The second entity is called product_definition_shape. A STEP modeling convention requires any geometric property of a feature be connected to the product_definition_shape. If more properties were shown then more entities would be connected to this product_definition_shape.

Figure 3. Life Cycle entities for a feature property.

On the right, the entities define a depth parameter. Other parameters will define the location and diameter of the hole, the design tolerances, and the manufacturing requirements. The representation item shown defines the depth value using references to other entities that are not shown. A representation entity is a bag that defines the units for a set of items. These items can define many parameters for many features.

STEP lets features and feature properties exist in the model before they are connected. When the two are connected this is done via the entity in the middle of the figure called a shape_definition_representation.

The figure shows that the minimum number of entities that must be created to represent the depth of a parameter is one: the shape_definition_representation entity. This is the case when both the feature and the depth parameter already exist. If the depth is new however then at least three entities must be created and 6 or more entities may be necessary if there is no product_definition_shape yet or new units must be defined for the representation. In practice the programmer must consider all these cases and code must be written to make or find all the entities as necessary.

For one property this is not so difficult, but it must be repeated for the more than 6 properties allowed for the pocket feature and then again for the twelve or so feature types allowed in the AP-224 model. The result is a combinatorial explosion rather similar to the coding explosion that occurs when programmers must write their program in assembler instead of a high level programming language.

Approach used in the new Method

All of the requirements that must be met by the data are defined in the Application Protocol. Traditionally, the EXPRESS part of these requirements was compiled into code, but the mapping tables were ignored because:

These reasons convinced STEP Tools to invest in replacing the mapping tables with EXPRESS-X. However, when it began working on AP-238 it was realized EXPRESS-X was not going to be a solution because it was too hard to compile into modifiable C++ or Java code.

Therefore, STEP Tools began working on a new compiler for the STEP mapping tables. This compiler generates C++ code for the Application Objects and their properties. The generated code makes all of the entities required for each path similar to the one shown in Figure 3. The code understands what needs to be shared and created to make each path unique and conformant to the standard. It allows the programmer to not worry about these details in normal circumstances, but if there is an exception, the programmer can access the data at the underlying entity level just like a C programmer can exit into assembler when necessary. This is another critical difference between the new approach and the EXPRESS-X approach tried previously.

In addition the generated code includes:

  1. Functions to create a new mapping path.
  2. Functions to find a mapping path already in the data
  3. Functions to set the value at the end of a path (e.g. the depth of a pocket)
  4. Functions to delete a path
  5. Functions to write a persistent representation of the path to a STEP file.

In the C++ terms the functions are member functions of a class that represents the Application Object. The Application Object is a lightweight class that is rooted on the root entity of the object.

In essence the new compiler allows the programmer to program at the ARM level instead of the AIM level. This means that to make six properties for an ARM object the programmer can make 6 functions calls instead of 36 and in consequence the programmer is far more productive and the problem of programming the complete STEP life cycle is made much easier.

Summary

Table I summarizes the four methods that have been tried to make STEP programming easier. The first three methods had other goals as well as making programming easier, but if the table is correct the Mapping Table compilation is by far the most effective.

The conclusions of the table will be proven or dis-proven over the next five years. If AP-238 is deployed as a new standard for defining the interface between CAM and CNC systems, then it will be because the new compilation techniques were effective. If ISO 14649 is deployed then it will be because they were insufficient to enable practical programming.

Of course there are other phases to the product life cycle such as early design, maintenance and disposal. These phases share the manufacturing problem of requiring more complex product attributes to be defined than required for the detailed design phase supported by AP-203. However, they may have additional problems so success for the new compilation technique in manufacturing may or may not be sufficient to allow the other phases to become successful as well.

The future work for this project is to try to apply the same technique to the other Application Protocols. Each family of protocols has its own conventions. They all meet the standing guidelines required for all STEP protocols, but they vary with respect to how aggressively they make use of inheritance and where they put some of their optional classification information. Consequently, it is quite likely that each family will be best served by its own flavor of compiler.

If the new technique is very successful then the STEP implementation problems for data exchange will become a thing of the past. In this case new problems will arise, one of which will be how to manage very large data volumes representing complete models of complex products such as airplanes and automobiles.

Annotation Conventions

By default, when writing a data set as an ISO 10303-21 text file or an ISO 10303-28 XML file, the instance data is grouped by ARM concept with a comment that describes how the instances are arranged to describe the application object and associated parameters. The instances below represent a Milling_machine_functions application object.

/************************************************
 * Application object: MILLING_MACHINE_FUNCTIONS (#50)
 * THROUGH_SPINDLE_COOLANT: #50, #51, #52, #53, #54: [through spindle coolant off]
 * CHIP_REMOVAL: #50, #55, #56, #57, #58: [chip removal off]
 * COOLANT: #50, #59, #60, #61, #62: [coolant on]
 */
#50=MACHINING_FUNCTIONS('','milling',' ',' ');
 
#51=ACTION_PROPERTY('through spindle coolant','',#50);
#52=ACTION_PROPERTY_REPRESENTATION('','',#51,#53);
#53=REPRESENTATION('',(#54),#31);
#54=DESCRIPTIVE_REPRESENTATION_ITEM('constant','through spindle coolant off');
 
#55=ACTION_PROPERTY('chip removal','',#50);
#56=ACTION_PROPERTY_REPRESENTATION('','',#55,#57);
#57=REPRESENTATION('',(#58),#31);
#58=DESCRIPTIVE_REPRESENTATION_ITEM('constant','chip removal off');
 
#59=ACTION_PROPERTY('coolant','',#50);
#60=ACTION_PROPERTY_REPRESENTATION('','',#59,#61);
#61=REPRESENTATION('',(#62),#31);
#62=DESCRIPTIVE_REPRESENTATION_ITEM('constant','coolant on');

In the example above, the first line of the comment indicates that the instances describe a Milling_machine_functions application object. In parenthesis, instance #50 is identified as the AIM element for the application object and the starting instance for the reference paths given in the mapping tables.

The mapping table entry for Milling_machine_functions calls for an AIM element of type machining_functions and the reference path shown below:

machining_functions <=
action_method
{ action_method.description = `milling' }

Instance #50 is the machining_functions instance at the start of the reference path. The second line simply states that machining_functions is a subtype of action_method. The final line of the path states that the description attribute has the value "milling." In instance #50, the second attribute (which the description attribute in ISO 10303-21 syntax) is is indeed "milling."

The rest of the comment indicates application object parameters and AIM instances that form the reference path given in the mapping tables. Consider the Milling_machine_functions coolant parameter and the corresponding reference path:

machining_functions <=
action_method
characterized_action_definition = action_method
characterized_action_definition <-
action_property.definition 
{ action_property.name = `coolant' }
action_property <-
action_property_representation.property 
action_property_representation
action_property_representation.representation ->
representation
representation.items[i] -> 
representation_item =>
descriptive_representation_item
descriptive_representation_item.description
{ (descriptive_representation_item.description = `coolant on' )
  (descriptive_representation_item.description = `coolant off' ) }

The comment indicates that #50, #59, #60, #61, and #62 describe the coolant parameter. Instance #50 is the machining_functions instance at the start of the reference path. This is referred to by #59, an action property with a name of "coolant." This action_property is referred to by #60, which is an action_property_representation. This refers to #61, which is a representation that contains descriptive_representation_item #62 in its items set. The last lines of the reference path constrain the value of the description attribute to either "coolant on" or "coolant off." In instance #62, the value is "coolant on," which is also documented at the end of the comment. This can seem verbose, but implementation tests have shown that in normal use, almost all data in a file will be geometry instances that describe either workpiece shape or toolpath curves.

It is hoped that this annotation will assist implementors in understanding the use and structure of the application objects, mapping reference paths, and corresponding integrated representation for the examples that follow.

Hand-Populating ARM Objects

When you have an existing AIM data set and want to selectively create a few ARM objects, use newInstance(aim_obj) to create a new ARM object with a particular AIM root, and then call the populate() function.