After a Building Block is modeled with the relevant variability types, we need to describe how these variabilities relate. This can be done by the DVG models presented here.
When the DVG model is finished, the variability solver can be generated. Since the Building Block model is the trigger for that you need to switch to the associated Building Block model and add the reference to this model in case you have not specified this reference at the very beginning:
BuildingBlockDescription <NameOfTheAssociatedBuildingBlockModel> dvg <TheDVGModelYouJustFinished> { ... }
For more information see Details on the Building Block Feature
A simple DVG example at a task level where a service robot must collect a box from a specific station and deliver it to another station. A non-functional requirement in this example is a maximum time limit indicating when the Transportation task should be finished. The associated Building Block model is explained here and the complete project can be found here.
DVG Transportation outputName ConstrainedTransportationTime {
We define a DVG named Transportation and specify ConstrainedTransportationTime as the outputName. The outputName specifies the name of the output port for which the solver should show the output. You typically enter the desired name after the DVG model is finished and all output ports and their names are defined. You will see the definition of the ConstrainedTransportationTime port later in this example.
INIT INITFetchStation { InitPort FetchStation => "Transportation.Seq_CollectBox.C1.GotoLocation.M1.GoalPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Interface INTERNAL ComplexVSPInit { [ Element x RealInit [ -12330.0 ], Element y RealInit [ 12460.0 ] ] } } } INIT INITDeliverStation { InitPort DeliverStation => "Transportation.Seq_CollectBox.C1.GotoLocation.M1.GoalPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Interface INTERNAL ComplexVSPInit { [ Element x RealInit [ 2670.0 ], Element y RealInit [ 5900.0 ] ] } } } INIT INITStartPosition { InitPort StartPosition => "Transportation.Seq_CollectBox.C1.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Interface INTERNAL ComplexVSPInit { [ Element x RealInit [ 7.0 ], Element y RealInit [ 989.0 ] ] } } }
We define three ports in different INIT patterns that initialize three different locations: FetchStation (where the box should be collected), DeliverStation (where the box should be delivered to) and StartPosition (where the robot currently is when the Transportation task is commanded).
All three have an ABSOLUTE representation because we initialize them according to their underlying data structure which is a combination of a x and a y value.
All three are of CONSTANT variability because they exactly specify one value instance as the variability space (one combination of x and y).
The specification of the Interface is optional for a INIT pattern and if it is not specified it is treated as INTERNAL. INTERNAL as the default case means that we use the data that is initialized in the INIT pattern, so the values you can see above.
Do not be confused about the referenced variability entities of the three InitPorts. In general, every output port (a InitPort is a output port) must specify a reference to a corresponding variability entity of the associated Building Block model. The main purpose is to get and check the associated DataObject of this referenced variability entity and NOT to have an exact mapping between port entities (in the DVG model) and the variability entities (in the Building Block model) as this is not always possible and not intended with the current implementation. For example DeliverStation is mapped to GoalPosition of the GotoLocation instance of CollectBox because it is a variability entity with a matching DataObject. This does NOT mean that DeliverStation is now the input for the GoalPosition of the GotoLocation instance of CollectBox. That would also not be correct since it is actually the input for the GoalPosition of the GotoLocation instance of DeliverBox and not CollectBox (as you will see later as this is the job of the DVG model). However, we have only one definition of GotoLocation (as child of CollectBox) and can therefore only reference the elements from there. A solution is to specificy a BuildingBlockInst in the Container C1 of DeliverBox and to reference the GotoLocation definition from CollectBox. Then it is possible to specify an additional reference to this BuildingBlockInst in InitPort DeliverStation to indicate that it refers to the GoalPosition of the second GotoLocation instance. However, this additional modeling effort has currently no effect at all because again: The main purpose of the reference to a variability entity is to get and check the associated DataObject. That means, we could also map all the three InitPorts above to GoalPosition of GotoLocation of CollectBox and this would also work because the associated DataObject is a location and all three ports initialize a corresponding location.
INIT INITVelocity1 { InitPort Velocity1 => "Transportation.Seq_CollectBox.C1.GotoLocation.Velocity" { VariabilityType ACTIVE RepresentationType ABSOLUTE RealVSPInit [ 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0 ] } } INIT INITVelocity2 { InitPort Velocity2 => "Transportation.Seq_CollectBox.C1.GotoLocation.Velocity" { VariabilityType ACTIVE RepresentationType ABSOLUTE Description RealVSPInit [ 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0 ] } }
We initialize two ACTIVE velocities with a variability space in the range [100.0, 1000.0] mm/s using a discretization of 100.0 mm/s for the two instances of GotoLocation. They are associated with the Velocity Parameter of GotoLocation. Again, both reference Velocity of the first GotoLocation instance (child of CollectBox), although Velocity2 is actually relevant for the second GotoLocation instance (child of DeliverBox). However this is allowed and makes no difference as these references are only required to get and check the associated DataObjects and in this case the DataObject is the same for both InitPorts.
APRO Goto1Time { OutputPort Goto1Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "INITVelocity1.Velocity1", InputPort I2 => "INITStartPosition.StartPosition", InputPort I3 => "INITFetchStation.FetchStation" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto1Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } } APRO Goto2Time { OutputPort Goto2Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "INITVelocity2.Velocity2", InputPort I2 => "INITFetchStation.FetchStation", InputPort I3 => "INITDeliverStation.DeliverStation" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto2Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } }
We define the required Time of the two GotoLocation instances by defining an optimistic estimation function that calculates the straight line distance between the start and goal locations divided by the velocity. The output ports for this Time Property are ACTIVE because the patterns depend on INITVelocity1.Velocity1 and INITVelocity2.Velocity2 respectively which are ACTIVE. In other words: The robot can influence the Time Property of the GotoLocation instances actively by choosing the velocities.
INIT INITDockToStationTime { InitPort DockToStationTime => "Transportation.Seq_CollectBox.C2.DockToStation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 11.0 ] } } INIT INITUndockFromStationTime { InitPort UndockFromStationTime => "Transportation.Seq_CollectBox.C4.UndockFromStation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 3.0 ] } } INIT INITLoadFromStationTime { InitPort LoadFromStationTime => "Transportation.Seq_CollectBox.C3.LoadFromStation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 6.0 ] } } INIT INITUnloadToStationTime { InitPort UnloadToStationTime => "Transportation.Seq_DeliverBox.C3.UnloadToStation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 6.0 ] } }
We initialize the Times of DockToStation, UndockFromStation, LoadFromStation and UnloadToStation by CONSTANT values.
SAPRO SAPROCollectBoxTime { OutputPort CollectBoxTime => "Transportation.Seq_Transportation.C1.CollectBox.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "Goto1Time.Goto1Time", InputPort I2 => "INITDockToStationTime.DockToStationTime", InputPort I3 => "INITLoadFromStationTime.LoadFromStationTime", InputPort I4 => "INITUndockFromStationTime.UndockFromStationTime" O=f(I): "double $OUT$ = $I1$+$I2$+$I3$+$I4$;" }
We define the Time of CollectBox as the sum of Goto2Time, DockToStationTime, LoadFromStationTime and UndockFromStationTime because of the Sequential decomposition of the corresponding Building Blocks. The output port CollectBoxTime is ACTIVE because Goto1Time is ACTIVE. That means: The robot can influence the Time property of the CollectBox Building Block actively by varying the Time Property of the first GotoLocation instance and this happens by choosing its velocities.
SAPRO SAPRODeliverBoxTime { OutputPort DeliverBoxTime => "Transportation.Seq_Transportation.C2.DeliverBox.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "Goto2Time.Goto2Time", InputPort I2 => "INITDockToStationTime.DockToStationTime", InputPort I3 => "INITUnloadToStationTime.UnloadToStationTime", InputPort I4 => "INITUndockFromStationTime.UndockFromStationTime" O=f(I): "double $OUT$ = $I1$+$I2$+$I3$+$I4$;" }
We define the Time of DeliverBox as the sum of Goto2Time, DockToStationTime, UnloadToStationTime and UndockFromStationTime because of the Sequential decomposition of the corresponding Building Blocks. The output port DeliverBoxTime is ACTIVE because Goto2Time is ACTIVE. That means: The robot can influence the Time Property of the DeliverBox Building Block actively by varying the Time Property of the second GotoLocation instance and this happens by choosing its velocities.
SAPRO SAPROTransportationTime { OutputPort TransportationTime => "Transportation.Transportation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "SAPROCollectBoxTime.CollectBoxTime", InputPort I2 => "SAPRODeliverBoxTime.DeliverBoxTime" O=f(I): "double $OUT$ = $I1$+$I2$;" }
The Time of Transportation is the sum of CollectBoxTime and DeliverBoxTime. The output is ACTIVE because CollectBoxTime and DeliverBoxTime are ACTIVE.
COMF COMFConstrainedTransportationTime { OutputPort ConstrainedTransportationTime => "Transportation.Transportation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "SAPROTransportationTime.TransportationTime" InputCPort I2 => "INITTimeConstraint.TimeConstraint" O=f(I): </<= (inclusive false) }
We define a filter for TransportationTime that removes all values that are above a specified threshold. That means ConstrainedTransportationTime will contain all the values that are below the specified threshold. This is the output we are interested in when executing the solver (hence this is the name we specified as outputName at the beginning of the model).
INIT INITTimeConstraint { InitCPort TimeConstraint => "Transportation.Transportation.Time" { VariabilityType CONSTANT Interface INTERNAL RealVSPInit [ 100.0 ] } } }
We initialize a constraining value of 100 seconds for the Time of Transportation as a requirement. This is the input for COMFConstrainedTransportationTime.
Executing the generated solver will list all the values of ACTIVE varibilities (Velocity1+Velocity2) for which Time of Transportation is below the demanded threshold of 100 seconds.
This ist the DVG model for the AllocSharedOrderPicking Building Block model. A special requirement of a DVG model that belongs to an ALLOCATABLE Building Block is that we need to explicate the interface to the DVG models of the allocationCandidates. This interface defines which data are required from the specified robot models for the evaluation of the DVG.
Note that the following model will reference some elements from another project (BBRepo) because we moved some definitions to a new place for simpler reuse.
The complete project can be found here.
DVG AllocSharedOrderPicking outputName SharedOrderPickingTime FinalOperation MIN {
We are interested in the Time of SharedOrderPicking. Since SharedOrderPickingTime represents the corresponding output port, as will be seen below, we specify this name as outputName. Furthermore, we define a MIN function. This means that the overall goal of the model is to find an allocation that minimizes Time of this task. Note that the specification of FinalOperation is optional. If it is not specified, a MAX function will be used by default.
DMAGR DMAGR_1 { DAGGR { OutputPort DAGGRVelocity => "BBRepo.GotoLocation.Velocity" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Velocity" } }, DAGGR { OutputPort DAGGRStartPosition => "BBRepo.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "StartPosition" } } }
A DMAGR defines a list of DAGGRs each containing an output port defining the data that is required from the robot models. The input ports in a DAGGR are unspecified because they depend on the number of specified allocationCandidates in the associated Building Block model and are dynamically created in the background. The required data in our example is denoted Velocity and CurrentPosition and refers to the maximum velocity a robot can drive and the current position of a robot when the evaluation is triggered. The maximum velocity of each robot (a CONSTANT) is sufficient in this model because its overall goal is to minimize Time.
INIT INITDockToRobotTime { InitPort DockToRobotTime => "AllocSharedOrderPicking.AllocSharedOrderPicking.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 29.0 ] } } INIT INITPickAndPlaceTime { InitPort PickAndPlaceTime => "AllocSharedOrderPicking.AllocSharedOrderPicking.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 16.0 ] } } INIT INITNumberObjects { InitPort NumberObjects => "AllocSharedOrderPicking.AllocSharedOrderPicking.M1.NumberObjects" { VariabilityType CONSTANT RepresentationType ABSOLUTE IntegerVSPInit [ 1 ] } }
Defining Time for DockToRobot and PickAndPlace as well as the number of objects to pick as CONSTANT values.
SAPRO SAPROPickAndPlaceTime { OutputPort OverallPickAndPlaceTime => "AllocSharedOrderPicking.AllocSharedOrderPicking.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "INITPickAndPlaceTime.PickAndPlaceTime", InputPort I2 => "INITNumberObjects.NumberObjects" O=f(I): "double $OUT$ = $I1$*$I2$;" } SAPRO SAPROParallelTime { OutputPort ParallelTime => "BBRepo.CollectBox.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "SAPROCollectBoxTime.CollectBoxTime", InputPort I2 => "SAPROApproachAndDetectTime.ApproachAndDetectTime" O=f(I): "double $OUT$ = Math.max($I1$,$I2$);" } SAPRO SAPROCollaborationTime { OutputPort CollaborationTime => "BBRepo.CollectBox.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "Goto3Time.Goto3Time", InputPort I2 => "INITDockToRobotTime.DockToRobotTime", InputPort I3 => "SAPROPickAndPlaceTime.OverallPickAndPlaceTime", InputPort I4 => "Goto4Time.Goto4Time" O=f(I): "double $OUT$ = $I1$+$I2$+$I3$+$I4$;" } SAPRO SAPROSharedOrderPickingTime { OutputPort SharedOrderPickingTime => "AllocSharedOrderPicking.AllocSharedOrderPicking.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "SAPROParallelTime.ParallelTime", InputPort I2 => "SAPROCollaborationTime.CollaborationTime" O=f(I): "double $OUT$ = $I1$+$I2$;" }
The composition of Time for different Building Blocks. The composition of Time of CollectBox and ApproachAndDetect is a max function because both Building Blocks must be executed in parallel by different allocationCandidates. SharedOrderPickingTime represents the total Time of the whole task and this name was specified as outputName at the beginning because this is what we are finally interested in and which we want to minimize.
BBContainer => "AllocSharedOrderPicking.Pa_SharedOrderPicking.C1" { SAPRO SAPROCollectBoxTime { OutputPort CollectBoxTime => "BBRepo.CollectBox.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "Goto1Time.Goto1Time", InputPort I2 => "BBRepo.INITDockToStationTime.DockToStationTime", InputPort I3 => "BBRepo.INITLoadFromStationTime.LoadFromStationTime", InputPort I4 => "BBRepo.INITUndockFromStationTime.UndockFromStationTime" O=f(I): "double $OUT$ = $I1$+$I2$+$I3$+$I4$;" } APRO Goto1Time { OutputPort Goto1Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "DMAGR_1.DAGGRVelocity", InputPort I2 => "DMAGR_1.DAGGRStartPosition", InputPort I3 => "BBRepo.INITFetchStation.FetchStation" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto1Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } } } BBContainer => "AllocSharedOrderPicking.Pa_SharedOrderPicking.C2" { INIT INITDetectObjectsTime { InitPort DetectObjectsTime => "AllocSharedOrderPicking.AllocSharedOrderPicking.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE RealVSPInit [ 11.0 ] } } APRO Goto2Time { OutputPort Goto2Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "DMAGR_1.DAGGRVelocity", InputPort I2 => "DMAGR_1.DAGGRStartPosition", InputPort I3 => "BBRepo.INITPickingPlace.PickingPlace" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto2Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } } SAPRO SAPROApproachAndDetectTime { OutputPort ApproachAndDetectTime => "BBRepo.CollectBox.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "Goto2Time.Goto2Time", InputPort I2 => "INITDetectObjectsTime.DetectObjectsTime" O=f(I): "double $OUT$ = $I1$+$I2$;" } } BBContainer => "AllocSharedOrderPicking.Seq_Collaboration.C1" { APRO Goto3Time { OutputPort Goto3Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "DMAGR_1.DAGGRVelocity", InputPort I2 => "BBRepo.INITFetchStation.FetchStation", InputPort I3 => "BBRepo.INITPickingPlace.PickingPlace" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto2Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } } } BBContainer => "AllocSharedOrderPicking.Seq_Collaboration.C4" { APRO Goto4Time { OutputPort Goto4Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } InputPort I1 => "DMAGR_1.DAGGRVelocity", InputPort I2 => "BBRepo.INITPickingPlace.PickingPlace", InputPort I3 => "BBRepo.INITDeliverStation.DeliverStation" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto2Time => "BBRepo.GotoLocation.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } } } }
As you can see above, it is possible to define patterns within a BBContainer that define a reference to a corresponding Container of the Building Block model. This can help to keep a better overview about which descriptions belong to which Building Block. However, in the cases above with shared resources and several resource groups and for the current implementation, it is even mandatory that the different APRO GotoXTime patterns depending on a DMAGR are defined in BBContainers referencing the corresponding Containers of the Building Block model. The reason is that the code generator requires these links in order to get the assigned resourcegroupids and with that information it is possible to get the correct references to the DVG models of the allocationCandidates that match for the respective resourcegroupid.
The complete project can be found here.
DVG Robotino { INIT INITRobotinoVelocity { InitPort RobotinoVelocity => "BBRepo.GotoLocation.Velocity" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Robotino:MaxVelocity (mm/s)" RealVSPInit [ 1200.0 ] } } INIT INITRobotinoStartPosition { InitPort RobotinoStartPosition => "BBRepo.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Robotino:CurrentPosition" ComplexVSPInit { [ Element x RealInit [ 0.0 ], Element y RealInit [ 1000.0 ] ] } } } }
The complete project can be found here.
DVG Larry { INIT INITLarryVelocity { InitPort LarryVelocity => "BBRepo.GotoLocation.Velocity" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Larry:MaxVelocity (mm/s)" RealVSPInit [ 1000.0 ] } } INIT INITLarryStartPosition { InitPort LarryStartPosition => "BBRepo.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Larry:CurrentPosition" ComplexVSPInit { [ Element x RealInit [ -2500.0 ], Element y RealInit [ 1000.0 ] ] } } } }
The complete project can be found here.
DVG Macy { INIT INITMacyVelocity { InitPort MacyVelocity => "BBRepo.GotoLocation.Velocity" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Macy:MaxVelocity (mm/s)" RealVSPInit [ 1000.0 ] } } INIT INITMacyStartPosition { InitPort MacyStartPosition => "BBRepo.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Macy:CurrentPosition" ComplexVSPInit { [ Element x RealInit [ 7950.0 ], Element y RealInit [ 3710.0 ] ] } } } }
The complete project can be found here.
DVG Robotino_2 { INIT INITRobotinoVelocity { InitPort Robotino_2Velocity => "BBRepo.GotoLocation.Velocity" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Robotino_2:MaxVelocity (mm/s)" RealVSPInit [ 1200.0 ] } } INIT INITRobotinoStartPosition { InitPort Robotino_2StartPosition => "BBRepo.GotoLocation.CurrentPosition" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description "Robotino_2:CurrentPosition" ComplexVSPInit { [ Element x RealInit [ -784.0 ], Element y RealInit [ 8630.0 ] ] } } } }
The solver will evaluate the Time for each possible allocation of the allocationCandidates specified in the associated Building Block model by using the corresponding data from the DVG models of the allocationCandidates (Robotino, Larry, Macy, Robotino_2). Finally, the allocation with the minimum Time is determined.
If the associated building block model is a EQUF model of model then you need to define a corresponding structure in the DVG model. While the building block model defines a EquivalenceFork with a list of Containers that reference building blocks from other models (see this example), the DVG model has to specify a MAGR with a AGGR in which a list of input ports reference output ports of interest from the different DVG models that are associated with the referenced building blocks in the building block model. The current assumption in the implementation is that the i-th input port of an AGGR in the DVG model must be an output port of the DVG model of the i-th building block in the EquivalenceFork of the building block model. In other words: The BuildingBlockDescription of the i-th referenced building block in the EquivalenceFork references the DVG model in which the output port is defined that is referenced by the i-th input port of the AGGR of the MAGR.
This is the associated DVG EQUF model of models for this building block model. The complete project can be found here
DVG OrderPickingEQUF outputName OrderPickingEQUFTime FinalOperation MIN { MAGR OrderPickingVsSharedOrderPicking { AGGR { OutputPort OrderPickingEQUFTime => "AllocOrderPickingEQUF.AllocOrderPickingEQUF.Time" { VariabilityType CONSTANT RepresentationType ABSOLUTE Description Time } ExtInputPort I1 => "AllocOrderPicking.SAPROOrderPickingTime.OrderPickingTime" { RepresentationType ABSOLUTE DataObject UdoTime }, ExtInputPort I2 => "AllocSharedOrderPicking.SAPROSharedOrderPickingTime.SharedOrderPickingTime" { RepresentationType ABSOLUTE DataObject UdoTime } } } }
We want to know the Time of AllocOrderPicking and AllocSharedOrderPicking. It is important that AllocOrderPicking is the first input and AllocSharedOrderPicking the second input of the MAGR because in the associated building block model AllocOrderPicking is also the first input while AllocSharedOrderPicking is the second input of the EquivalenceFork.
This is the associated DVG parallel model of models for this building block model. The complete project can be found here.
DVG AllocProblem outputName AllocProblemTime FinalOperation MIN { SAPRO SAPROAllocProblemTime { OutputPort AllocProblemTime => "AllocProblem.AllocProblem.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE Description Time } ExtInputPort I1 => "AllocTransportation.SAPROTransportationTime.TransportationTime" { RepresentationType ABSOLUTE DataObject UdoTime }, ExtInputPort I2 => "OrderPickingEQUF.OrderPickingVsSharedOrderPicking.OrderPickingEQUFTime" { RepresentationType ABSOLUTE DataObject UdoTime } O=f(I): "double $OUT$ = Math.max($I1$, $I2$);" } }
Since, both building blocks will be executed in parallel and both must finish, the composition of Time is a max function. It is important that AllocTransportation is the first input and OrderPickingEQUF the second input of the APRO because in the associated building block model AllocTransportation is also the first input while OrderPickingEQUF is the second input of the Parallel decomposition.
Unfortunately the current implementation has some limitations. The following list tries to describe the most important ones:
The APRO is the most complex pattern and is currently the only pattern that can handle complex data object inputs. If you use APRO to process complex data objects you have to consider some conditions:
APRO Goto1Time { OutputPort Goto1Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } InputPort I1 => "INITVelocity1.Velocity1", InputPort I2 => "INITStartPosition.StartPosition", InputPort I3 => "INITFetchStation.FetchStation" Description { Core { InternalInputPort I1 => I1, InternalInputPort I2 => I2, InternalInputPort I3 => I3 InternalOutputPort InternalGoto1Time => "Transportation.Seq_CollectBox.C1.GotoLocation.Time" { VariabilityType ACTIVE RepresentationType ABSOLUTE } O=f(I): "double $OUT$ = 0.0; double tmp = Math.sqrt(Math.pow($I2[0]$-$I3[0]$,2)+Math.pow($I2[1]$-$I3[1]$,2)); $OUT$ = tmp/$I1$; " } } }
This is a valid example of an APRO processing both primitive and complex data objects and producing a primitive data object (Time). The first input Velocity1 is primitive and comes before the complex ones StartPosition and FetchStation (they are complex because they represent locations that have two elements x and y). Furthermore, the order of the references between the internal input ports and input ports matches (I1→I1, I2→I2 and I3→I3).
Currently no guarantee that preconditions work in combination with the processing of complex data objects.