Tuesday, August 25, 2009

Split function in SCL

VBA has a function called Split that is handy for parsing strings to an array based on some delimiter.  All you have to do is dim out an array variable and say:
ArrayVar = Split( "the,split,string" , "," ) and your ArrayVar will contain three strings, "the" , "split", and "string".
There is no in-built function in SCL to do this, so I have put together something that should work in a similar fashion.  I have named the function the same, though the difference here is because SCL's arrays are fixed in size, where with VBA you can dynamically size arrays.
To get around this, you must first declare a String array in the Var section of your calling procedure (or globally), and pass that into the Split function as the last argument.  You must also provide the upper bound of the array to the function.  This upper bound is not the highest index of the array (which is one minus the size of the array), but just the size of the array.  One easy way to use this information is to declare your arrays using Const's denoting the size of the array.  For example:
procedure some_proc()
Const
arr_size 10
Var
my_array : Array[ arr_size ] of String
........
So, in this case, if you wanted to split a string into my_array, you would do this:
num_elems = split( 'some delimited line' , ' ' , arr_size , my_array )
where num_elems is the number of chunks of text split into the array.  If there are more chunks than there are bins in your array, any trailing chunks will be ignored, and no error will be raised.
I have tested this routine a bit, so it should work fairly well, even with multi-character delimiters.  On a side note, you should put this routine into your always available routines in QUEST.

routine split( the_line : String ; the_delim : String ; max_elements : Integer ; Var the_array : Array[] of String ) : Integer
Var
write_idx , delim_idx : Integer
check_char : String
Begin
while( len( the_line ) > 0 ) do
if( write_idx < max_elements ) then
delim_idx = index( the_line , the_delim , 1 )
--write( 'delim_idx=' , delim_idx , cr )
if( delim_idx > 0 ) then
the_array[ write_idx ] = leftstr( the_line , delim_idx - 1 )
the_line = rightstr( the_line , len( the_line ) - delim_idx - len( the_delim ) + 1 )
else
-- no more delimeters left - write the last of the_line to the array
the_array[ write_idx ] = the_line
the_line
= '' -- empty the_line so we break from the while loop
endif
write_idx = write_idx + 1
else
the_line = '' -- empty the_line so we break from the while loop
endif
endwhile
return write_idx -- return number of pieces written to array
End

Tuesday, August 18, 2009

Evaluating string expressions in SCL

I have found a few cases where it would be better to allow a user to enter not just numbers, but some expression that can be evaluated to a number. An simple example of this is just evaluating calculations, like "10+2*(8/5)". Ordinarily, if someone entered this and you were expecting a number, you may have a real problem. But luckily QUEST provides a means for evaluating strings to Real values, or even to String values.

The method involves calling out to BCL to evaluate an SCL expression, returning either a String or Real value. The associated BCL commands are SCL_NUMERIC_EXPR and SCL_STRING. You just pass in the SCL expression and read the resulting BCL_MSG variable as the result.

Here are two SCL routines that make these BCL commands a bit easier to use:

BCL_VAR
bcl_msg : String
routine evaluate_scl_expr( the_string : String ) : Real
Var
bcl_err : Integer
Begin
bcl_err = bcl( "SCL_NUMERIC_EXPR('" + the_string + "')" )
return val( bcl_msg )
End

routine eval_scl_string( the_expr : String ) : String
Var
bcl_err : Integer
Begin
bcl_err = bcl( "SCL_STRING_EXPR('" + the_expr + "')" )
return bcl_msg
End

Tuesday, August 4, 2009

Quest_Geom

I've used the same solution Martin described, and clumsy is an understatement, but it has worked fairly well for me in the past.  From what I've seen of the format, it's similar to the wavefront obj format, if that helps...

 

Here's an overview of how a basic QUEST geometry file is laid out, just from my messing around with these files...I have no expertise in how the format works, this is all based on observation and guesses.

 

All these observations are based on a basic rectangular block I created in QUEST D5R18.

 

Basically the file starts with the number 12, probably a version number or something, then some vector transformation information, probably for locating and rotating the geometry, though I've never messed around with that.  After all this information there is an asterisk indicating the geometry section is beginning.  I've found that older geometry files don't have this asterisk to delineate between geometry sections.

 

For a basic rectangular box, there are 8 points, for each of the 8 corners on the box.

After the first asterisk, there is a number indicating the number of points in the geometry.  Points serve as vertices for lines.  After listing the number of vertices, you list out the xyz location of each vertex.

 

After the vertices you list out something, and I either never knew or forgot what it is, but the geometry I'm looking at now has a zero.

 

Next we indicate the number of and list out all the lines in the geometry.  So if we have a rectangular box we have a total of 12 lines, as you can see in the diagram below.

To describe a line, we have to provide the index of each of the two vertices in the line.  QUEST basically reads the initial list of points in as a zero-indexed array, which means the first entry is point number zero in the array.

In this case, line 1 is composed of points 1 and 2, so our first line is represented as "1 2"

Next we indicate the number of and list out all the polygon faces in the geometry.  So if we have a rectangular box we have a total of 6 faces, as you can see in the diagram below.

The definition of a polygon is simply a list of the line indices composing that face preceded by the number of lines composing the face.  The direction of the line makes a difference, here.  The lines of a polygon must all go in the same direction - either clockwise around the face or counter-clockwise.  So, if a line is defined backwards from the direction of the other lines in the polygon, you must place a minus sign before that line number, and QUEST will interpret that and represent the polygon properly.

The last section we'll discuss is text.  I'm not entirely sure where the text section goes, but with the simple polygon block example, it seems we can just put the text section after the polygon face section.

To define the text, you must first provide the number of text objects to place on the geometry.  Next, start listing out the text values.  The first line of a text definition is the text string value.  The next four lines after that represent the location/rotation transform for the text placement.  To be honest, I'm not really sure how to interpret this.  At some point I'll try to post some routines I built for reading and writing these rotation matrices, but in the mean time, to work with text, there is an easier way.  Basically, just build your basic geometry, and manually place the text, save that out, and copy the transform matrix and use that.

So what we end up with with all this information should be a simple plain text file that we can feed into QUEST to build some simple rectangular box.  Here it is:

 

I hope this has helped give some basic idea of how to build simple geometry files without using QUEST.  Leave a comment if you have any questions about QUEST geometry that you'd like to discuss.


Thursday, July 23, 2009

eVSM to QUEST demo video

Here's a youtube video showing the eVSM to QUEST tool I've been developing at the Connecticut Center for Advanced Technology (CCAT).
If you're a QUEST user and have the eVSM software, and would like to try this functionality out, visit http://modsim.ccat.us/eVSM_Utilities and let us know you're interested. I'll be in contact when the time comes.

Friday, July 10, 2009

IIE Annual Conference 2009 - Applied Solutions presentation

Here are the slides I presented this year at the IIE Annual Conference - Applied Solutions session. It shows some of the work I've been doing with bridging the eVSM Value Stream Mapping software with QUEST.

More to come later...


Wednesday, July 1, 2009

eVSM to QUEST Interface

eVSM to QUEST Interface

 

Overview

The CCAT eVSM Utilities tool with the DELMIA QUEST (http://3ds.com) option allows you to export Value Stream Map information to the DELMIA QUEST (QUeuing Event Simulation Tool).

 

CCAT has developed a set of Simulation Control Logic (SCL) macros in QUEST for importing plain text files in tab-delimited format, and transforming that data into QUEST modeling constructs.

 

The CCAT eVSM Utilities makes it very easy to generate the plain text files and automates the subsequent import within QUEST.

Terminology

  • QUEST - QUeuing Event Simulation Tool.  This is Discrete Event Simulation Software provided by Dassault Systemes, and is used for the modeling and simulation of stochastic manufacturing systems
  • eVSM - electronic Value Stream Mapping software (http://evsm.com).
  • NVU - Name-Value-Unit.  An NVU is a construct within eVSM for holding process data.  The Name portion describes the name of the data, the Value is simply the data value, and Unit is the name of the unit the Value is measured in

Format Overview

The overall format for importing to QUEST is as such:

  • Two rows of column header information
  • One row delineating units in columns
  • Process information in rows

 

Each row of simulation data represents a process in QUEST.  Each column holds different data about the process.

 

There are three pieces of required data for each process in eVSM:

  • Cycle Time - The processing time of the process
  • Workstation - The name of the machine resource where the process is completed.  This may also be a comma-delimited list of machines, each machine being capable of running the same process
  • Product - The name of the product part class of the process

Configuration Files

The eVSM->QUEST SCL macros were built to be flexible enough to import VSM data from eVSM using whatever standardized NVU names you want.  An eVSM->QUEST configuration file has a .esm file extension, and is simply a list of setting names and values, similar to a QUEST .inc file.

 

The CCAT eVSM Utilities come with a pre-configured configuration file called QUEST_DIRECT.esm, and is stored in the DATA folder of the QUEST library you install the macros to.  This file is used as the default configuration file for exporting directly from eVSM.

 

Aside from mapping NVU names to data fields the SCL builder macros need, there are also several high-level settings that can be used to control how the SCL builder macros run.  The following are descriptions of several of these settings:

  • CELL_DELIM - The delimiting character between columns in the input text file.  By default this is tab, but a comma can be used (and can be generated by MS Excel)
  • COMMENT_LINE - This character tells the SCL builder macros that a line is not to be read as a process.  The default value is the # character
  • Geo - These settings allow you to specify the default geometry for buffers and machines
  • Workcell spacing options - These settings allow you to specify the spacing from a machine where the input and output buffers are to be placed.  You may also offset the location of the machine labor point in the y-axis using the LABOR_Y_SPACING setting
  • Logic - These settings allow you to specify the logics to assign to various elements by default (in-buffer routing logic, process logic, etc...).  The SCL file in which the logics are located must be compiled before the build.  This can be done by listing your logic files in your configuration file with the variable name as SCL_FILE#, where # is a number between 1 and 5, and where no two listed logic files share the same number.  These files will be compiled before the SCL builder macros execute

Data Overview

As previously mentioned, there are three required pieces of information you must provide for a process in eVSM.  In reality, there are six pieces of data the SCL builder macros need in order to build a model; however, the following three pieces of data are automatically populated for you within eVSM :

  • Operation- The name of the process
  • Tag - A unique identifier for the process (no other process can have the same tag, but may have the same name)
  • Next Op - The Tag of the process downstream of the current process.  This is used for identifying process sequences and routings

In addition to this required information, there is a set of optional NVUs you may provide to the SCL builder macros:

  • Changeover Time - The time required to change a machine from one process to another - modeled as a setup process in QUEST, between each process on the machine
  • Load Time - The time required to load a part onto a machine before the cycle process begins.  This is modeled as a setup process and is executed when the same process is performed twice in a row.  This means the load time must be included in changeover time, as the first load time is not run
  • Operator - The name of the laborer class to be required on a process.  If a process has a changeover and/or load time assigned to it, the operator is assigned to the load/changeover process(es).  Otherwise the operator is assigned to the cycle process
  • Operators - Depending on the assign_all_operators_to_process setting in the configuration file used.  If the setting is 0, then the operators value represents the number of laborers in the labor class.  If the setting is 1, then that number of operators is assigned to the process the laborer is assigned to
  • Num Elements - The number of elements in the machine class
  • MTTR/MTBF/Uptime - This is machine reliability data commonly used in simulation. Two of the three listed NVUs must be present to properly assign QUEST failures to the machines.  If Uptime is provided, the NVU not present (MTTR or MTBF) is calculated based on the Uptime value and whatever value is present
  • Scrap - The rejection rate of the process.  The rejection rate tells QUEST what percentage of parts to scrap, which means the parts are destroyed, and not repaired.  The SCL builder macros do not currently support part repair
  • Geometry -  The display geometry file name for the listed Workstation.  This will override the configuration file level setting
  • TimeToNext - The time for the part to get to its next operation.  The time delay is executed on the output buffer of the machine which the process is run on, and is not resource-constrained.  The part enters the buffer, and after the TimeToNext is elapsed it moves on to the next process.  This may be used for modeling outside operations which are not being modeled.  This value may be provided as an SCL expression (meaning you may use build-in distribution functions)
  • Shifts - The number of shifts the listed Workstation of the process works.

Units

The builder assumes that the data file coming in was created using eVSM.  As of eVSM version 4, units are placed in the third row, and so the builder assumes row 3 of the data file it reads contains the units for all the NVU's.  The builder will look to these units to determine the units for: cycle time, setup time, load time, IAT, time to next operation, and Mean Time To Repair (MTTR).  If no units are found for a specific variable, default values are assumed (minutes for cycle, setup, and load times; hours for IAT & MTTR)

Location/Layout Information

The SCL builder macros need to know where to put the machines listed in the Workstation NVU of a process.  This can be provided multiple ways:

  • Shape of the Value Stream Map
  • Locations from an eVSM Spaghetti Chart
  • Manual location

When building from eVSM, you only have a choice between laying out machines in the shape of the VSM, or getting locations from an eVSM Spaghetti Chart. 

 

If you choose the shape of the VSM, the SCL builder macros will place a machine in the location of the first process that uses that machine in its Workstation NVU.  To locate based off an eVSM Spaghetti Chart, you must provide the name of the page the Spaghetti Chart is on, and the column from Excel corresponding to the place names set in the eVSM Spaghetti Chart.  For example, if you name all your Spaghetti Places based on the values from your Workstation NVUs, you would tell the builder interface in eVSM to use the Workstation column for locating machines.

CCAT eVSM Utilities interface to SCL Builder Macros

Layout Options

Select a radio button to tell the builder how to locate machines in QUEST.  Using "No layout" or "Layout file" will locate machines in the shape of the VSM.  Using "Layout from page" requires that you specify the name of the eVSM Spaghetti Chart page, and the name of the column in the eVSM Excel Calculator spreadsheet which matches up processes with the location names in your eVSM Spaghetti Chart

 

esm File

You may specify an esm configuration file, if you have a customized file you need to use for the export.  If left blank, the default QUEST_DIRECT.esm is used.

 

Pre- and Post-Build BCL Commands

You may specify a list of BCL commands to be executed before and after the SCL builder macros are executed.  You may wish to compile logic files before the build, or to run different SCL macros after the builder execution.

 

These commands should be stored in the eVSM Excel Calculator spreadsheet.  The worksheet the BCL commands are stored in should be named the same as the page your VSM is in, with "_BCL" appended on the end of the name.  The easiest way to set this up is to click the "Import BCL from Excel" button, and the worksheet will be created, if necessary.

 

You must specify which columns contain which commands, where Pre-build BCL commands must have " *--PRE_BUILD_BCL*" in the first row cell of the pre-build commands column.  " *--POST_BUILD_BCL*" must be in the first row cell of the post-build commands column.

 

Build Process

Once you have your settings complete in the CCAT eVSM Utilities, click the "Build" button.  This will execute the eVSM Calculator, after which the CCAT eVSM Utilities will export the machine locations to Excel, as well as the Next Op data for each process (based on the connections between processes in your VSM).  Finally, the CCAT eVSM Utilities will export your Excel data to a tab-delimited text file, and start QUEST and tell it to execute a BCL script generated with your pre- and post-build BCL commands, as well as commands to run the SCL builder macros.

 

The SCL builder macros begin by reading the spreadsheet data to an internal string array, and identifying all the column names, as well as reading units for different NVUs.  Next, the builder copies data it has mapped to specific fields to a different string array, and begins the build process.

 

The build process begins with building part classes based on the Product column, then it builds a process for each row in the data array.  Next, the process products and requirements are set based on the links between processes and their products.  For instance, if two processes both have a process with tag "B10", the builder will interpret the process as an assembly process, and will require one of each of the Product part classes from the feeding processes.  Then, based on the Product of the process, the process will be set to either pack one of the requirements into the other, or it will create a new part (if the product is not one of the requirements).

 

Next, shifts are added to machines based on the Shift data, if provided.  If a machine is listed as having more than three shifts, then each shift is set as a time of 24 hours divided by the highest shift number found.  If the maximum shift number is 3 or less, then each shift is set as 8 hours.  Later on in the build, these shifts will be assigned to your machines.  If the shift times need to be changed this can easily be done either manually or through BCL.  The hardest part is done for you, which is creating and assigning the shifts to machines.

 

Next, workstations are created.  A workstation is just a machine, an input buffer, and an output buffer.  An input buffer receives and holds work until its machine can take it.  An output buffer holds finished work until it can be moved to the next workstation. 

 

As noted above, if TimeToNext is provided for a process, the workstation's output buffer will hold the part for whatever that TimeToNext value is.

 

Each workstation gets added to its own group so you may easily move a workstation around within a model.

 

Next, the builder will build connections between workstations.  This is done based on the requirements of the processes on different machines.

 

Next, laborers are assigned to processes.  If a process has loading or changeover associated with it then the laborer is assigned only to the loading/changeover process(es).  Otherwise the laborer is assigned to the cycle process.

 

Next, loading and changeover machines are assigned to machines.  After that, the builder assigns a process sequence to each part class, based on the chain of requirements and products of all the processes previously built.  One noted problem with this is that the BCL statement to build a process sequence must contain the names of all the processes in the sequence, rather than simply adding one process to the sequence.  This means that you may run against a string size limit when building a model with many long-named processes.  To fix this, modify the BIG_STRING_SIZE constant in the build_from_vsm_generic.scl file to something larger.

 

The builder then assigns action logics, if applicable, as listed in the configuration file.  Next comes machine failures, which are created and assigned if a process lists a machine's reliability as detailed above.

 

Lastly, the builder goes back to the original input array and finds any data columns that were not mapped to known constructs, and creates user attributes on the processes holding that data.  This means you can very easily pass data between eVSM and QUEST without customizing the build_from_vsm_generic.scl file.

 

The builder then cleans up any build errors and data arrays, and saves the model to QUESTLib\Last_Build_Model.mdl.  Also, the builder creates a BCL script of all BCL commands that get executed throughout the build process, and a log file is kept at QUESTlib\Output\writer_log.txt.


Monday, June 29, 2009

Automating DXF import to QUEST

QUEST doesn't come with a BCL command for easily importing geometry, and although that would be very convenient, it's still possible to convert various CAD geometry to QUEST's PDB format.

QUEST doesn't have CAD converts baked into the QUEST.exe application file, but rather uses standalone executables located in the quest\bin folder in your QUEST installation. QUEST simply calls these executables using command line arguments to pass in information about what the user is trying to do through the QUEST UI. The converter then performs the conversion, and dumps out a temporary pdb file into your temp directory (default is C:\Tmp). QUEST has been waiting for the converter exe file to terminate, after which it just does a "retrieve" of the temp file the converter created.

So, in a nutshell, to automate this ourselves, we simply have to call the appropriate converter with the right command line arguments, and we can go around the relatively clunky QUEST UI for dealing with our CAD importing.

My use case will be generating dxf/dwg layouts from vector drawings in MS Visio, and generating a pdb file for QUEST. This means I'll be using VBA in Visio, but the same thing could easily be done using SCL (although there might be a few snags, such as making your SCL code wait until the conversion is complete)

Before I start into laying out the arguments for converting a dwg to pdb, I should mention that DELMIA/Deneb have made it a little easier on us in running these converters. They have provided some DOS batch files for setting environment variables, which the converters basically need to be sure you are a licensed QUEST user.

So to convert dwg to pdb, we use the dwg2pdb.bat and corresponding dwg2pdb.exe files. If you look at dwg2pdb.bat, you can see there's about 5 lines for telling Windows where dwg2pdb.exe is. You can get away with deleting all that junk, and finding the line that says:

%DENEB_BIN_DIR%\dwg2pdb.exe $1 ...

and replacing the %DENEB_BIN_DIR% with the full path to your QUEST installations bin dir (mine is C:\delmia\quest\bin)

The only environment variable you need to make sure is set is the LM_LICENSE_FILE, which you should have set already in your quest.bat file, and if your installation of QUEST works, you shouldn't even need to change this.

So, on to the command line arguments. To see what the arguments are, I quickly built an exe in VB6 that just echos out the command line arguments in a message box. So I renamed my dwg2pdb.exe to something else, and renamed my command line echo exe to dwg2pdb.exe. Then I went into QUEST and ran an import, at which time I was shown that there are four arguments you need to pass to run a dwg conversion:

  1. The full path to the dwg/dxf input file
  2. The full path to the output pdb file location
  3. The full path to a configuration file called dwg_cmd (more on that later)
  4. The full path to an output text callout file location
The first two arguments are fairly straightforward. You just need to get the full path to the input file, and decide where to send the output file.

The third argument is for the full path to a file called "dwg_cmd", which is automatically generated by the QUEST UI when you tell QUEST some of the parameters of the input geometry, such as the default length units, point tolerance, etc... On my system, at least, this file was stored in the quest directory. So I modified it to a default length unit of Inches, and copied the file to quest\bin. This will serve as my default dwg import profile.

The fourth and final argument was the full path to where you'd like the converter to build a plain text file containing all the text from the dwg/dxf file. You'll notice when imporing a file with text, you get the floating annotations containing your drawing text. I guess this is where that text comes from. The format is somewhat easy to understand. Basically, the first line details the number of text annotations there are. Then the annotations start. The first three lines of an annotation are the x, y, and z locations of the text callout, respectively. I'm not entirely certain what the next four lines are, though they could be rotation angles and font sizes. The next line is the number of characters in the callout, and the final line of a callout is the callout text.

Okay, so now we know all the arguments we'll need to pass to dwg2pdb.exe or .bat, to get things translated. When I tried this though, I got an error saying the executable could not find lmgr8b.dll, which is some runtime that QUEST needs in order to operate (and I'm assuming it's for the FlexLM license manager QUEST uses)

To fix this problem, I simply copied the lmgr8b.dll file from my quest dir into my quest\bin dir, and everything seemed to work. I could pass in my arguments and get a pdb file out.

So now anywhere I can generate command line arguments, I can also convert dwg/dxf files into the QUEST format automatically.