カスタム作業計算の作成

APS のカスタム C ルーチンを作成して、指定作業の作業時間を計算できます。作業の [カスタムプランナルール] フィールドが選択されていると、システムによってカスタム計算ルーチンが呼び出されます。

標準の作業計算ルーチンについて

標準の作業計算ルーチンは、ol_opercalc です。デフォルトでは、このルーチンから -1.0 が出力されます。これは、作業時間を決定するために、標準(すなわち、カスタムではない)計算を使用するようアルゴリズムに通知する信号です。このルーチンの C コードは以下のとおりです。


#include "ol_api.h"
double
ol_opercalc(opercalc)
opercalc_s* opercalc;
{
return(-1.0);
}

標準ルーチンへの入力

ol_opercalc には、opercalc_s 構造体のポインタを入力します。下記に示すように、この構造体には作業時間を計算するために使用する情報が含まれています。


/*------------------------------------------------------------------------*/
typedef struct attid_struct
/*------------------------------------------------------------------------*/
{
 char                   attid[MAX_OLXFSTR+1];
 char                           attvalue[MAX_OLXFSTR+1];
}
attid_s;
/*------------------------------------------------------------------------*/
typedef struct reslist_struct
/*------------------------------------------------------------------------*/
{
 char                   resource[MAX_OLXFSTR+1];
 char                   category[MAX_OLXFSTR+1];
 double                 catbufpre;
 double                 catbufpost;
 long                   numresattids;
 attid_s**      resattidlist;
}
reslist_s;
/*------------------------------------------------------------------------*/
typedef struct opercalc_struct
/*------------------------------------------------------------------------*/
{
 char                                   operation[MAX_OLXFSTR+1];
 char                           order[MAX_OLXFSTR+1];
 char                           part[MAX_OLXFSTR+1];
 double                         quantity;
 char                           startwindow[14];
 char                           endwindow[14];
 long                           oprflags;
 double                         oprsetup;
 double                         oprcycle;
 double                         oprbufpre;
 double                         oprbufpost;
 long                           oprovltype;
 double                         oprovlvalue;
 long                                   matltag;
 long                           numresources;
 reslist_s**    resourcelist;
 long                           numoprattids;
 attid_s**              oprattidlist;
 long                           numordattids;
 attid_s**              ordattidlist;
 long                           numprtattids;
 attid_s**              prtattidlist;
}
opercalc_s;

標準ルーチンからの出力

ol_opercalc からは以下の 2 種類の出力があります。

  • 関数の戻り値。ol_opercalc からの戻り値は、合計作業時間(倍精度型として)または -1.0(または負数)のいずれかになると予測されます。負数は、システムに標準の(カスタムではない)作業計算を使用するよう通知する信号です。
  • 3 つのパラメタセット。これらは opercalc_s 構造体の一部のパラメタです。
    • oprsetup - 作業段取時間(時間)
    • oprovltype - 作業のオーバーラップ区分
    • oprovlvalue - 作業のオーバーラップ値

アルゴリズムからこれらのパラメタが ol_opercalc に受け渡されるとき、パラメタにはデータベースのユーザ指定値が含まれています。この値をアルゴリズムに戻す前に ol_opercalc 内で変更できます。変更した場合、システムから次のような応答があります。

  • oprsetup - 段取時間が、この作業に対して変更されます。
  • oprovltype - オーバーラップオフセットが、この作業に対して再計算されます。
  • oprovlvalue - オーバーラップオフセットが、この作業に対して再計算されます。

元のデータベース値から作業オーバーラップを有効にできます。または oprovltype を変更することにより有効にできます。作業オーバーラップを有効にするとともに、oprsetup が変更されるか ol_opercalc の戻り値により異なる oprcycle 値の利用が示された(作業の [固定 SCHD 時間] および [カスタムプランナルール] フィールドの設定を考慮)場合、システムではこの作業のオーバーラップオフセットを再計算します。

カスタムルーチンの作成

ルーチンを作成する場合、必ず戻り値を倍精度型にしてください。戻り値は、生産に有効な期間中に、指定した資源を使用して、指定数の部品を製造するのに必要な合計作業時間(時間表記)を表す必要があります。

次の例では、ol_opercalc ルーチンを用いて、ある資源に対する作業時間を算出しています。


#include "ol_api.h"
double
ol_opercalc(opercalc)
opercalc_s* opercalc;
{
    FILE* log_fp;
    int i,j;
 double dTime;
   log_fp = fopen("d:\\opercalc50.txt","a");
  fprintf(log_fp,
                "\nopercalc:  oper=>%s&LT\n",
                opercalc->operation );
        fflush(log_fp);
  fprintf(log_fp,
                "opercalc:  numoprattids=%d\n",
                opercalc->numoprattids );
        fflush(log_fp);
  for (i=0;i&LTopercalc->numoprattids;i++)
        {
   fprintf(log_fp,
    "opercalc:  opr attid   =>%s&LT\n"
    "opercalc:  opr attvalue=>%s&LT\n",
                opercalc->oprattidlist[i]->attid,
    opercalc->oprattidlist[i]->attvalue );
            fflush(log_fp);
        }
  fprintf(log_fp,
                "opercalc:  order=>%s&LT\n",
                opercalc->order );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  numordattids=%d\n",
                opercalc->numordattids );
        fflush(log_fp);
  for (i=0;i&LTopercalc->numordattids;i++)
        {
   fprintf(log_fp,
                "opercalc:  ord attid   =>%s&LT\n"
    "opercalc:  ord attvalue=>%s&LT\n",
                opercalc->ordattidlist[i]->attid,
    opercalc->ordattidlist[i]->attvalue );
            fflush(log_fp);
        }
  fprintf(log_fp,
                "opercalc:  part=>%s&LT\n",
                opercalc->part );
        fflush(log_fp);
  fprintf(log_fp,
                "opercalc:  numprtattids=%d\n",
                opercalc->numprtattids );
        fflush(log_fp);
  for (i=0;i&LTopercalc->numprtattids;i++)
        {
   fprintf(log_fp,
          "opercalc:  prt attid   =>%s&LT\n"
    "opercalc:  prt attvalue=>%s&LT\n",
                opercalc->prtattidlist[i]->attid,
    opercalc->prtattidlist[i]->attvalue );
            fflush(log_fp);
        }
        fprintf(log_fp,
                "opercalc:  quantity=%f\n",
                opercalc->quantity );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  start=>%s&LT\n",
                opercalc->startwindow );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  end=>%s&LT\n",
                opercalc->endwindow );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprflags=%d\n",
                opercalc->oprflags );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprsetup=%f\n",
                opercalc->oprsetup );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprcycle=%f\n",
                opercalc->oprcycle );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprbufpre=%f\n",
                opercalc->oprbufpre );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprbufpost=%f\n",
                opercalc->oprbufpost );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprovltype=%d\n",
                opercalc->oprovltype );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  oprovlvalue=%f\n",
                opercalc->oprovlvalue );
        fflush(log_fp);
        fprintf(log_fp,
                "opercalc:  numresources=%d\n",
                opercalc->numresources );
        fflush(log_fp);
  for (i=0;i&LTopercalc->numresources;i++)
        {
   fprintf(log_fp,
                "opercalc:  resource=>%s&LT\n",
                opercalc->resourcelist[i]->resource );
            fflush(log_fp);
   fprintf(log_fp,
                "opercalc:  category=>%s&LT\n",
                opercalc->resourcelist[i]->category );
            fflush(log_fp);
            fprintf(log_fp,
                    "opercalc:  catbufpre=%f\n",
                    opercalc->resourcelist[i]->catbufpre );
            fflush(log_fp);
            fprintf(log_fp,
                    "opercalc:  catbufpost=%f\n",
                    opercalc->resourcelist[i]->catbufpost );
            fflush(log_fp);
      fprintf(log_fp,
                    "opercalc:  numresattids=%d\n",
                    opercalc->resourcelist[i]->numresattids );
            fflush(log_fp);
      for (j=0;j&LTopercalc->resourcelist[i]->numresattids;j++)
            {
       fprintf(log_fp,
        "opercalc:  res attid   =>%s&LT\n"
        "opercalc:  res attvalue=>%s&LT\n",
                    opercalc->resourcelist[i]->resattidlist[j]->attid,
        opercalc->resourcelist[i]->resattidlist[j]->attvalue );
                fflush(log_fp);
            }
        }
  dTime = -1.0;
  if ( (!strcmp(opercalc->part,"SA-50910")) &&
    (!strcmp(opercalc->operation,
             "SA-50910                      SA-5.20")) &&
    (!strcmp(opercalc->resourcelist[0]->resource,"PNT10.1")) )
  {
   if ( opercalc->oprflags == 2 )
            {
    fprintf(log_fp, "opercalc:  per cycle\n");
    fflush(log_fp);
    if ( opercalc->quantity > 10.0 )
    {
        opercalc->oprsetup = 0.15;
     fprintf(log_fp, "opercalc:  changing oprsetup\n");
     opercalc->oprcycle = 0.25;
     fprintf(log_fp, "opercalc:  changing oprcycle\n");
     opercalc->oprovltype = 1;
     fprintf(log_fp, "opercalc:  changing oprovltype\n");
     opercalc->oprovlvalue = opercalc->quantity / 2;
     fprintf(log_fp, "opercalc:  changing oprovlvalue\n");
     opercalc->oprbufpre = opercalc->quantity / 2;
     fprintf(log_fp, "opercalc:  changing oprbufpre to qty/2=%f\n",
                        opercalc->oprbufpre);
     opercalc->oprbufpost = opercalc->quantity / 4;
     fprintf(log_fp, "opercalc:  changing oprbufpost to qty/4=%f\n",
                        opercalc->oprbufpost);
//     dTime = opercalc->oprcycle * opercalc->quantity;
     fflush(log_fp);
    }
            }
   else
            {
    fprintf(log_fp, "opercalc:  per load\n");
    fflush(log_fp);
    dTime = 1.0;
                /* opercalc->oprsetup = 0.0;
                opercalc->oprcycle = 0.1;
                opercalc->oprovltype = 1;
                opercalc->oprovlvalue = 3.0; */
            }
  }
  fprintf(log_fp, "opercalc:  dTime = >%f&LT\n", dTime );
        fflush(log_fp);
  fclose(log_fp);
  return(dTime);
}

Opercalc.dll の作成

カスタム作業計算ルーチン用 Opercalc.dll の作成」 を参照してください。

カスタムルーチンの呼び出し

APS を実行するとき、作業の[JOBSTEP.STEPTMRL] フィールドが 2 ([カスタムプランナルール] が選択され、[固定 SCHD 時間] に値が入力されている)または 3 ([カスタムプランナルール] が選択され、[固定 SCHD 時間] が未入力か 0 が入力されている)に設定されている場合のみ、カスタムルーチンが使用されます。STEPTMRL 値が 2 の作業では、固定サイクルタイムが使用され、3 の場合は 1 個当たりのサイクルタイムが使用されます。

作業の [カスタムプランナルール] がクリアされている場合、カスタム ol_opercalc ルーチンは呼び出されません。