...

修士論文 オペレータモデルを用いたアラームシステムの評価 笠井理恵

by user

on
Category: Documents
9

views

Report

Comments

Transcript

修士論文 オペレータモデルを用いたアラームシステムの評価 笠井理恵
NAIST-IS-MT0651027
修士論文
オペレータモデルを用いたアラームシステムの評価
笠井 理恵
2008 年 3 月 15 日
奈良先端科学技術大学院大学
情報科学研究科 情報システム学専攻
本論文は奈良先端科学技術大学院大学情報科学研究科に
修士 (工学) 授与の要件として提出した修士論文である。
笠井 理恵
審査委員:
西谷 紘一 教授
(主指導教員)
木戸出 正繼 教授
(副指導教員)
野田 賢 准教授
(副指導教員)
オペレータモデルを用いたアラームシステムの評価∗
笠井 理恵
内容梗概
プラント運転において,異常発生時といった高度な判断が必要な場面でオペ
レータの助けとなるプラントアラームシステムの設計は,異常の見落としや,ア
ラームの洪水を招くことのない,適切な設計でなければならない.
アラームの洪水を抑制する手段の一つであるリアルタイムアラームマネジメン
トにはサプレッション,シェルビング,状態ベースアラーム管理機能などがある.
オペレータへの負担が軽減される一方,アラームをオペレータから隠す処理であ
るが故に危険性も孕んでいるため,リアルタイムアラームマネジメントに対して
も適切な評価が必要である.
本論文では,リアルタイムマネジメントの一つであるサプレッション評価を目
的としてオペレータモデルを作成し,オペレータモデルを用いた評価法を提案し,
その有効性を示した.また,オペレータモデルを用いてプラントアラームの定量
的評価の支援を目的とするソフトウェアの構築を行った.
キーワード
プラント,アラームシステム,オペレータモデル,評価,
リアルタイムアラームマネジメント
∗
奈良先端科学技術大学院大学 情報科学研究科 情報システム学専攻 修士論文, NAIST-IS-
MT0651027, 2008 年 3 月 15 日.
i
Evaluation of Plant Alarm System by using
Operator Model
∗
Rie Kasai
Abstract
Industrial plant alarm systems form an essential part of the operator interfaces
for automatically monitoring of plant state deviations and for attracting the plant
operator’s attention to the changes that require his/her intervention. To design
an efficient alarm system that assists operators to quickly identify the causes of
abnormalities and to respond to the situations is vital for the safe operation of
the plant.
In this paper, a evaluation method of a real time alarm management system
by using a operator model is proposed. The real time alarm management system
is a sub-system of the plant alarm system, which rationalizes generated alarms.
The proposed operator model is applied to a boiler plant alarm system with
a repeating alarm suppression algorithm for this case study and the evaluation
results prove the usefulness of the proposed method.
Keywords:
Plant, Alarm System, Operator Model, Evaluation,
Real-Time Alarm Management
∗
Master’s Thesis, Department of Information Systems, Graduate School of Information
Science, Nara Institute of Science and Technology, NAIST-IS-MT0651027, March 15, 2008.
ii
目次
1. 緒論
1
1.1 研究背景 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.1.1
プラントアラームシステム . . . . . . . . . . . . . . . . . .
1
1.1.2
アラームマネジメント . . . . . . . . . . . . . . . . . . . .
1
1.1.3
リアルタイムアラームマネジメント . . . . . . . . . . . . .
2
1.1.4
オペレータモデルによるアラームシステム評価 . . . . . .
4
1.2 研究の目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2. 対象プラント
6
3. 異常診断時のプラントオペレータの
認知情報処理モデル
13
3.1 オペレータモデルによるアラームシステムの評価 . . . . . . . . .
13
3.2 オペレータモデルの改良 . . . . . . . . . . . . . . . . . . . . . . .
18
3.2.1
オペレータモデルの変更内容 . . . . . . . . . . . . . . . .
18
3.2.2
オペレータモデルの動作比較 . . . . . . . . . . . . . . . .
22
3.3 オペレータモデルを用いた
リアルタイムアラームマネジメントの評価 . . . . . . . . . . . . .
27
3.3.1
サプレッションの方法 . . . . . . . . . . . . . . . . . . . .
27
3.3.2
評価シミュレーション . . . . . . . . . . . . . . . . . . . .
27
3.3.3
評価結果と考察 . . . . . . . . . . . . . . . . . . . . . . . .
29
4. 評価支援ソフトウェア
35
4.1 評価手順 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5. 結論
39
40
5.1 研究成果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
5.2 今後の課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
謝辞
42
iii
参考文献
43
付録
44
A. 異常伝播図上の兆候出現の順番を考慮した探索戦略
44
A.1 目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
A.2 提案する探索戦略 . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
A.3 シミュレーション . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
A.4 評価結果と考察 . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
B. オペレータモデルのソースコード
54
iv
図目次
1
Effective alarm systems by EEMUA 191 Guide . . . . . . . . . . .
2
2
異常伝播図の例(ボイラープラント)
. . . . . . . . . . . . . . .
4
3
ボイラープラントのプロセスフロー図
. . . . . . . . . . . . . . .
6
4
アラームステータス
. . . . . . . . . . . . . . . . . . . . . . . . .
8
5
ユーザパネル . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
6
プラントオペレータの認知情報処理モデル(オペレータモデル) .
13
7
原因と兆候の関係 . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
8
オペレータモデル A の ASSP フローチャート . . . . . . . . . . . .
17
9
オペレータモデル B の ASSP フローチャート . . . . . . . . . . . .
21
10
ASSP フローチャート省略記号
. . . . . . . . . . . . . . . . . . .
22
11
Mal-10 発生後の主要プロセス変数のトレンドデータ . . . . . . . .
23
12
Mal-10 における合計 AS 値の変化 . . . . . . . . . . . . . . . . . .
26
13
10 [s] ごとのアラーム発生回数( 0 [s] ∼ 70 [s])
. . . . . . . . .
29
14
兆候の確認数の時間変化 . . . . . . . . . . . . . . . . . . . . . . .
33
15
確認兆候の種類数の時間変化
. . . . . . . . . . . . . . . . . . . .
33
16
アラームの累積発生回数( 0 [s] ∼ 70 [s]) . . . . . . . . . . . . .
34
17
合計 AS 値の時間変化 . . . . . . . . . . . . . . . . . . . . . . . . .
34
18
評価支援ソフトウェア起動画面 . . . . . . . . . . . . . . . . . . .
36
19
プロセストレンドデータ表示ソフトウェア起動画面 . . . . . . . .
37
20
オペレータモデルの選択画面
. . . . . . . . . . . . . . . . . . . .
37
21
パラメータの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
22
アラーム設定の画面
. . . . . . . . . . . . . . . . . . . . . . . . .
38
23
提案する評価手順 . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
24
異常原因と兆候の関係 . . . . . . . . . . . . . . . . . . . . . . . .
46
25
兆候の発生順序によるグループ . . . . . . . . . . . . . . . . . . .
47
26
StrategyB における兆候確認の順序 . . . . . . . . . . . . . . . . .
48
27
StrategyC における兆候確認の順序 . . . . . . . . . . . . . . . . .
48
28
Mal-11 における Mal-11 に対する合計 AS 値の時間変化 . . . . . .
51
v
29
Mal-11 における兆候確認成功回数・失敗回数 . . . . . . . . . . .
vi
52
表目次
1
主要なアラームシステム評価指数と目標値 . . . . . . . . . . . . .
2
2
ボイラープラントシミュレータのタグ一覧 . . . . . . . . . . . . .
7
3
アラームステータスの種類 . . . . . . . . . . . . . . . . . . . . . .
8
4
Nomal fluctuation . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
5
AM-KB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
6
原因-兆候の因果関係を表す行列 . . . . . . . . . . . . . . . . . . .
15
7
アラームの設定(1par) . . . . . . . . . . . . . . . . . . . . . . .
24
8
オペレータモデル A の異常診断シミュレーション結果 . . . . . . .
25
9
オペレータモデル B の異常診断シミュレーション結果 . . . . . . .
25
10
アラームの設定(SystemB1par) . . . . . . . . . . . . . . . . . .
28
11
評価結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
12
サプレッションを行わなかった場合の異常診断シミュレーション結果 31
13
サプレッションを行った場合の異常診断シミュレーション結果 . .
31
14
各兆候の AS 値に基づく各種順位 . . . . . . . . . . . . . . . . . .
45
15
兆候出現順序の情報を表す 2 次元配列 . . . . . . . . . . . . . . . .
46
16
アラームの設定(1par) . . . . . . . . . . . . . . . . . . . . . . .
50
17
評価結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
vii
1. 緒論
1.1 研究背景
1.1.1 プラントアラームシステム
近年のプラント運転では,普段の多くの作業はシステムの自動化が進み,オペ
レータはそれを監視するという形態がとられている.高度に自動化されたプラン
トにおいても,異常発生時といった高度な判断が必要な場面では,依然,人間に
よって異常原因推定・処置等の判断が行われている.
異常診断の際,オペレータがプラントの異常を早期に検知し,正確な異常診断
をするための重要なインタフェースの一つが,
「「音」や,点滅,メッセージ表示や
その他様々な識別子といった「視聴覚的な指示」によってオペレータに伝えられ
る警告」[1] と定義される,プラントアラームシステム(以下アラームシステム)
である.オペレータの異常診断を支援するアラームシステムの設定は,異常の見
落としや,正確な判断の妨げとなるアラームの洪水を招くことのない,適切なも
のであることが求められる.そこで,アラームシステムの設定が適切であるかの
評価が必要となる.
1.1.2 アラームマネジメント
アラームシステムの設計・評価について,EEMUA (Engineering Equipment and
Material Users Association) がガイドライン [1] を提唱している.こガイドライン
には,アラームシステムのシステマティックな設計手法と,オペレータの情報処
理能力の考慮の重要性が述べられている.
アラームシステムの設計について EEMUA ガイドラインでは,良いアラームの
特徴として,関連性があること(Relevant),一意性があること(Unique),適時
であること(Timely),優先順位付けされていること(Prioritised),メッセージ
が明確で理解可能であること(Understandable),発生している事態を判断でき
ること(Diagnostic),とるべき対策があること(Advisory),重要な問題に注目
させること(Focusing),の 8 項目を挙げている.また,アラームの設定は Fig.
1
1 に示すような正常状態と異常状態,異常状態と緊急停止の境界線上であること
が望ましいとされている.とるべき対策のない注意喚起のみのアラームや,すで
に手遅れの状態でのアラームといった境界線上以外の範囲に含まれるような無駄
なアラームの削減が主張されている.
Fig. 1 Effective alarm systems by EEMUA 191 Guide
EEMUA ガイドランは適切なアラームの設計のための,様々な指標とその目標
値を定めている.Table 1 [6] に代表的な指標と目標値を示す.
Table 1 主要なアラームシステム評価指数と目標値
評価指数
目標値
安定時のアラーム発生頻度
1/10 min 以下
異常発生後 10 分以内の
10 以下
アラーム発生数
未対応アラーム平均残数
10 以下
棚上げアラーム平均残数
30 以下
1.1.3 リアルタイムアラームマネジメント
アラームの適正化の手段の一つとしてリアルタイムアラームマネジメントがあ
る.リアルタイムアラームマネジメントは運転状況に応じたアラームシステムの
2
設定変更や管理を,自動的に実行する機能をいう [2].”The Alarm Management
Handbook”[3] には,リアルタイムアラームマネジメントの手法として,サプレッ
ション(Suppression),シェルビング(棚上げ,Shelving),状態ベースアラー
ム管理機能(State-Based Alarming)などが紹介されている.
サプレッションは,優先順位など何らかの条件で発生アラームをオペレータに
提示しない処理を行う.フィールドセンサーに問題がある場合や数秒ごとに繰り
返されるチャタリングアラームに対して有効である.
シェルビングは不要アラームを手動または自動で一時的に退避させる手法であ
る.アラームを一時的に停止またはアラーム閾値を変更して退避させる.
状態ベースアラーム管理機能はプラントのスタートアップ,シャットダウンと
いった特別な状況や,原料・製品変更など,運転状態が変化する時に,自動的に
アラーム設定値の変更,不要なアラームの停止を行い,適した設定を適用する手
法である.
”The Alarm Management Handbook”が提唱する,効率的なアラームシステム
にするための 7 ステップの中で,リアルタイムアラームマネジメントは Step6 に
位置する.必須のステップは Step1 から Step3 とされているが,Step6 は次の段
階としてパフォーマンスを上げるために必要なステップである.
Step1. アラームの設計思想の構築
Step2. システムのデータ収集と性能調査
Step3. 役に立たないアラームの解消
Step4. アラームの文書化と合理化
Step5. 自動監査と強制設定機能の装備
Step6. リアルタイムアラームマネジメント
Step7. 改良したシステムの維持
リアルタイムアラームマネジメントは,アラームの洪水を防ぎ,オペレータの
負担の軽減を期待して行われる.しかしこの手法は,アラームをオペレータから
隠す処理であるが故に危険性も孕んでいる.リアルタイムアラームマネジメント
での適切な設定,定量的な評価が重要である.定量的な評価法の一つにアラーム
数があるが,アラームシステムの適切な設定であるかの評価には,アラームの数
3
といった指標の他に,オペレータが異常診断に必要な情報を得られるかどうかも
考慮しなくてはならない.
本研究では,リアルタイムアラームマネジメントの中でも特に,アラームサプ
レションの定量的評価法として,ヒューマンオペレータの異常診断を模擬するオ
ペレータモデルを用いた評価法を提案する.
1.1.4 オペレータモデルによるアラームシステム評価
アラーム設計段階における適切なアラームの選出,設定やオペレータモデルを
用いた評価の先行研究として,Luo らによる先行研究 [4] や Liu らによる先行研
究 [5] がある.
Liu ら [5] は,アラーム設定の定量的評価を目的として,異常診断を模擬するオ
ペレータモデルを用いた手法を提案した.オペレータモデルは,Fig. 2 に示す異
常伝播図を基に作成された原因と兆候の関係の強さの情報などの知識ベースに基
づいて異常診断を行う.異常診断シミュレーションの結果得られた異常診断過程
を詳しく分析することで,オペレータが原因同定に要した時間,同定中発生する
アラーム数,オペレータの視線移動距離,原因探索過程などの定量的評価結果が
得られ,アラームシステムの評価に利用することができる.
Fig. 2 異常伝播図の例(ボイラープラント)
Liu らのオペレータモデルは,一度発生したアラームは後に Normal 状態に戻っ
ても,そのアラームが発生し続けているものとして異常探索を行うため,アラー
4
ムが頻繁に発生したり消えたりする場面で用いるサプレッションの評価に用いる
には,いくつかの問題点がある.
1.2 研究の目的
本研究ではリアルタイムマネジメントの一つであるチャタリングアラームのサ
プレッションを対象として,サプレッションが与えるオペレータの異常診断への
影響をオペレータモデルを用いて評価する方法を提案する.また,オペレータモ
デルを用いたプラントアラームの定量的評価支援ソフトウェアを構築する.
本論文の構成は以下の通りである.第 3 章にてアラームサプレッションの評価
に用いるオペレータモデルの構成について述べ,第 4 章にて作成したプラントア
ラームの定量的評価を支援するソフトウェアについて述べる.最後に第 5 章にて
本論文をまとめる.
5
2. 対象プラント
本論文ケーススタディに用いたボイラープラントシミュレータのプロセスフ
ローを Fig. 3 に示す.ボイラープラントシミュレータは横河電機株式会社製の訓
練用シミュレータ [7] で,監視制御システム(DCS,Distributed Control System)
として CENTUM-CS に接続されている.ボイラープラントはドラム,ファーネ
ス,FDF(Forced Draft Fan),IDF(Induced Draft Fan),BFP(Boiler Feed
Pump),燃料ポンプから成り,主蒸気温度 485 ℃の水蒸気 80t/h を発生させる.
Table 2 には DCS に割り振られているタグ(識別子)制御板計器に割り振られて
いる識別子であるを示す.制御板計器から得られる物理量にはプロセス変数(PV,
Process Variable)と,操作量を表す操作変数(MV,Manipulated Variable)が
あり,例えば A201 のプロセス変数値を A201.PV などと表記する.各タグに該当
する物理量の平常時の PV・MV 値の上下限値を Table 4 に示す [5].
Fig. 3 ボイラープラントのプロセスフロー図
発生するアラームの状態の種類を Table3 に示す.Fig.4 に示すように,NR は
6
Table 2 ボイラープラントシミュレータのタグ一覧
タグ
内容
A201
O2 濃度
A202
CO 濃度
C208
O2 計と CO 計の切替
F201
メインスチーム流量
F202
燃料流量
F203
流量自動選択器
F204
空気流量
F205
ドラム給水流量
F206
過熱防止装置スプレー流量
L202
ドラムレベル
P201
メインスチーム圧力
P202
ドラム圧力
P203
ファーネス圧力
P204
バーナー排気圧力
P206
BFP 排気口圧力
R034* 燃料オイル粘度
R080* 風速
T201
メインスチーム温度
T203
ドラム内水温
T204
燃料温度
∗ 測定点ではない
7
正常範囲内であること,HI および HH,LO および LL は,物理量が各々に設定さ
れた限界値の設定を超えて値が高いもしくは低い,異常状態の範囲内であること
を表すアラームである.アラームも同様にアラーム設定値よりも値が低い異常状
態を表す.速度アラームは値の変化率に関するアラーム,MHI・MLO は操作変
数は設定限界値を超えて値が高いもしくは低い状態を表すアラームである.
ステータス
Table 3 アラームステータスの種類
内容
ステータス
内容
NR
Normal
VEL+
速度アラーム+
HH
High-high アラーム
VEL-
速度アラーム-
HI
High アラーム
MHI
出力 High アラーム
LO
Low アラーム
MLO
出力 Low アラーム
LL
Low-Lo wアラーム
Fig. 4 アラームステータス
8
Tag
Table 4 Nomal fluctuation of PV and MV values
Low PV value High PV value Low MV value High MV value
A201
2.61
2.78
49.1
49.9
A202
23.5
25.7
0
0
C208
−
−
49.1
49.9
F201
77.9
82.4
−
−
F202
6.78
7.23
51.1
53.7
F203
51.1
53.7
51.1
53.7
F204
69.9
71.9
47.7
55.5
F205
75.59
81.11
42.9
44.7
F206
1.68
1.88
40.61
43.49
L201
−1.68
1.12
0
0
L202
−1.63
1.12
75.9
81.4
P201
79.3
80.6
67.9
72.3
P202
83.3
84.6
−
−
P203
−14.9
−5.8
66.1
72.9
P204
3.75
4.1
0
0
P205
12.6
12.9
−
−
P206
96.7
97.2
−
−
T201
480.4
489.8
1.67
1.88
T202
480.4
489.8
−
−
T203
297.9
298.8
−
−
T204
89.1
90.0
−
−
9
ボイラープラントシミュレータでは,仮定されている以下の異常(Malfunction)
を起こすことができる.
Mal-1: FOP1FAIL
FOP(Fuel Oil Pump)の 1 つ FOP1 が異常を起こし,燃料油流量やバー
ナー先端の圧力が低下する.
Mal-2: BURNER EXTINGUISH
全てのバーナーが失火し,バーナの圧力やメインスチームの流量が低下する.
Mal-3: BFP1TRIP
BFP(Boiler Feed Pump)の 1 つ BFP1 がトリップし,ドラムと過熱防止
装置への水の供給が妨げられ,水管の破裂を招く.
Mal-4: WATERTUBELEAK
水管から水が漏れ,ファーネス圧力が増加し,水流量がわずかに低下する.
Mal-5: O2ANALYZERFAIL
酸素センサーが故障し,低い値のまま一定となり,空気/燃料率が増加する.
Mal-6: FDFCAPACITYDOWN
FDF の故障のため,空気の取り込み量が減少し,ファーネスの圧力が低下
する.空気/燃料比率制御対応によって燃料油流量が低下する.
Mal-7: IDFTRIP
IDF がトリップして空気排気が減少し,ファーネス圧力が増加する.
Mal-8: TURBINETRIP
タービンのトリップ.多数の変数が激しく変化する.
Mal-9: OILHEAREFAIL
オイルヒーターの異常.油の温度の低下による粘度の増加で,油流量が低
下する.
10
Mal-10: P204SENSOR
バーナー先端の圧力である P204 センサーが低い値のまま一定となる異常.
これにより燃料流量が最大まで増加する.
Mal-11: FUELLEAK
燃料漏れ.バーナーへの燃料流量が減り,熱量が不十分になるため,十分
なスチーム流量を提供できなくなる.
本シミュレータのユーザパネルは Fig. reffig:panels に示す 6 種類,プラント
オーバービュー画面,アラーム説明画面,ACC エンジニアリング画面,ドラム給
水操作画面,FWC/STC エンジニアリング画面 ,バーナー点火画面からなる.
11
プラントオーバービュー画面
アラーム説明画面
バーナー点火画面
ドラム給水操作画面
FWC/STC エンジニアリング画面
ACC エンジニアリング画面
Fig. 5 ユーザパネル
12
3. 異常診断時のプラントオペレータの
認知情報処理モデル
3.1 オペレータモデルによるアラームシステムの評価
Liu ら [5][8] は,Card らの人間情報処理モデル [9] を基本モデルとして,対象プ
ラントのデータから作成された知識ベースと異常診断戦略に基づいて異常診断を
行うオペレータモデルを開発した.オペレータモデルを用いることで,EEMUA
ガイドラインや PAS ハンドブックで述べられている人間の情報処理能力を考慮
して,定量的なアラームシステムの評価ができる.Liu らが提案したプラントオ
ペレータの認知情報処理モデルを Fig. 6 に示す.なお,以降,Liu らによって作
成されたオペレータモデルを,オペレータモデル A と表記する.
Fig. 6 プラントオペレータの認知情報処理モデル(オペレータモデル)
オペレータモデルは,知覚プロセッサ,知識ベースが格納された長期記憶,短
期記憶,認知プロセッサ,駆動プロセッサからなる.ユーザインタフェースから
入力された情報を知覚プロセッサが知覚し,短期記憶に保存,長期記憶・短期記
憶の情報を参照しながら認知プロセッサで処理を行い,表示ユーザパネルを変え
13
るなどの動作が必要な場合は駆動プロセッサに伝える.
長期記憶には知識ベースと異常同定(Fault Detection and Identification,FDI)
のための手順が記憶されている.知識ベースには VI-KB(Variable Information -
Knowledge Base),AM-KB(Alarm Management - Knowledge Base),FS-KB
(Failure Symptom relation - Knowledge Base)の 3 つがある.
VI-KB は,各タグの定義やユーザパネル上の各タグやアイコンの位置やサイズ
の情報,AM-KB は Table. 5 に示すようなアラームステータスと兆候との対応に
関する情報,FS-KB は Fig. 7 に示すような定常状態における異常原因と兆候の
関係に関する情報が格納されている.
FS-KB はプラントで想定される全ての事故シナリオに対して HAZOP 解析や
シミュレーションを用いて整理された異常伝播図から作成し,Tble. 6 のような情
報を 2 次元配列情報として持っている.Table. 6 の Fm はインデックス m 番の異
常原因を,Sn はインデックス n 番の兆候を表しており,異常伝播図上で Sn − Fm
間に関係があれば Sn と Fm の交点の値が 1 となり,関係がない場合は 0 となる.
また,ある兆候に接続の原因の数を SL 値,ある原因に接続の兆候の数を FL 値と
定義し,Sn の SL 値を SLn ,Fm の FL 値を F Lm と表記する.なお,M ,N はそ
れぞれ異常原因と兆候のインデックスの最大値である.
Table 5 AM-KB
HI,HH LO,LL
アラームステータス
VEL+
VEL-
MHI
MLO
NR
兆候
PV.High
PV.Low
MV.High
MV.Low
.NR
異常同定のための手順 ASSP(Abnormal State Supervising Procedure)は異常
診断時に,ありうる原因の候補の中から真の原因を絞り込んでいくための手順で
ある.その手順は以下のようになっている.手順をフローチャートにしたものを
Fig. 8 に示す.
(1)アラームの発見.
(2) AM-KB を参照してアラーム情報を兆候に変換.
14
原因
兆候1 兆候2 兆候3 兆候4 兆候5 兆候6
Fig. 7 原因と兆候の関係
Table 6 原因-兆候の因果関係を表す行列
F1 F2 · · · Fm · · · FM
S1
0
1
···
1
···
0
S2
..
.
1
..
.
1
..
.
···
..
.
0
..
.
···
..
.
0
..
.
Sn
..
.
1
..
.
0
..
.
···
..
.
1
..
.
···
..
.
1
..
.
SN
0
1
···
1
···
1
15
(3) FS-KB を参照して,アラーム情報から想定される異常原因候補の集合を求
める.
(4)異常原因候補の中で最も AS 値の高いものを選択.
(5)異常原因候補が存在していない場合は(3)へ戻る.
(6)(4)で選択した異常原因候補に関係する兆候の中で AS 値の高いものを確
認する兆候に選択.
(7)(6)で選択した兆候が現れているか DCS 画面より確認する.
(8)(7)で兆候が確認された場合は,現在注目している(4)で選ばれた原因
候補と(6)で選ばれた兆候の組合せの AS 値を AS 合計値に加算する.
(9)(7)で兆候が確認されなかった場合は,該当する原因候補が過去に除外さ
れているならば(6)へ,除外されるのがはじめてならば注目していた原因
候補を候補から除外して(4)へ戻る.
(10)新しいアラームが発生しているかを確認し,新しいアラームが確認された
場合は始めの手順(1)に戻る.
(11)合計 AS 値がある閾値を超えていたならば同定完了.超えていなかった場合
は新しいアラームの確認を行い,確認されれば(1)へ,確認されなければ
(6)へ戻る.
ここで,AS(Association-Strength)値とは原因と兆候の組合せごとに式(1)
にて計算される値であり,原因と兆候の関係の強さを表わす.
wm,n
n
ASm,n = SLw
m,n
k∈Am
(1)
SLk
ここで,m は対象とする異常原因のインデックス,n は対象とする兆候のイ
ンデックス,Am は Fm に接続されている全ての兆候の添え字の集合, wm,n は
Fm − Sn 間の接続の重みを表す.
16
Fig. 8 オペレータモデル A の ASSP フローチャート
17
オペレータモデルの ASSP では,AS 値が高いほど,すなわち原因との関連性が
強い兆候ほど,その兆候を確認する優先順位が高くなる.また,確認できた兆候
の AS 値を合計した合計 AS 値を,同定完了を判定する基準として使用している.
異常同定時の人間の動作は,駆動,知覚,認知,短期記憶,長期記憶のサブタ
スクからなる.本研究ではサブタスクのまとまりをオペレーショナルステージと
定義する.オペレーショナルステージは,知覚・認知・短期記憶・長期記憶およ
び少なくとも一つの短期記憶からなり,知覚,認知,長期記憶,駆動の順に並ん
でいる.ただし,全ての種類のサブタスクがオペレーショナルステージに含まれ
るとは限らない.
評価にはオペレーショナルステージ数や FDI 間のアラーム発生数,視点移動距
離等が用いられる.異常同定の間に発生したアラームの数は第 1.1.2 節 Table1 に
示したような EEMUA のガイドラインとの比較に,視点移動距離は DCS 画面設
計の指標として利用できる.その他,最も早く発生したアラームなども評価に利
用できる.
3.2 オペレータモデルの改良
3.2.1 オペレータモデルの変更内容
本研究では,リアルタイムマネージメントの一手法であるアラームサプレッショ
ンの評価を目的とする.アラームサプレッションが必要な場面として,同一アラー
ムが短時間にオン・オフを繰り返したり,複数種のアラームが短時間に発生する
場面が想定される.そのため,モデルに必要な機能として,発生したアラームを
もれなく処理できること,High もしくは Low になったあるアラームステータス
が,Normal に戻った場合にアラームの状態が変化したと認識し,再度 High もし
くは Low になった場合には新たなアラーム認識をできることが必要がある.
オペレータモデル A は,複数のアラームが短時間に発生した場合,未処理のア
ラームが保持されないという問題があった.また,オペレータモデル A は変動が
安定した定常状態での評価を行うモデルであるため,一度 High もしくは Low に
なったアラームステータスが Normal に戻ってもアラームが発生し続けているも
18
のとして異常同定を行う問題があった.
そのため,本研究では前述の 2 つの問題点を解決するために,オペレータモデ
ル A をベースに新たなオペレータモデル B を作成した.オペレータモデル B で
は,アラームの処理は順に行い,新しいアラームが発生すれば未処理のアラーム
として追加保存し,保存されているアラームの中の最も古いものから次のアラー
ム処理を開始する.また新しいアラームが発生すれば,ただちにアラームの確認
処理をするようにした.
オペレータモデル A では,異常原因の可能性のある原因候補の集合から一度外
された原因は,全ての原因候補が否定されるまで再考されず,また,原因候補の
集合から外れた時点で合計 AS 値が 0 にリセットされていた.本研究のオペレー
タモデルでは,原因候補の集合からある原因を外すとき,原因の合計 AS 値は保
持したまま候補から外し,後に Normal が確認された時点で原因候補の集合が再
考され,一度外れた原因も回復されるようにした.また,Normal もアラームス
テータスの一種として処理するように処理を変更した.ただし,異常同定に用い
る知識ベースは,オペレータモデル A と同じものを用いている.
オペレータモデル B の ASSP の手順は以下のようになっている.手順のフロー
チャートを Fig. 9 に示す.新しいアラームの確認と同定完了判定は,Fig. 9 中の
省略記号の地点で行う.省略記号の説明は Fig. 10 に示す.
(1)アラームの発見.
(2) AM-KB を参照してアラーム情報を兆候に変換.NR アラームであった場合
(5)での原因探
は,過去に確認済みのアラームから最近のアラームを,
(4 )
索の起点に設定する.
(3) FS-KB を参照して,アラーム情報から想定される異常原因候補の集合を求
める.NR アラームによる異常原因候補への回復も行う.
(4)発見アラームの処理.異常原因候補の中で最も AS 値の高い Fm ,Sn を選択.
発見アラームが NR アラームでなければ,全ての原因に対して,合計 AS 値
に AS 値を加算する.
19
(5)計 AS 値がある閾値を超えていたならば同定完了.超えていなかった場合は
兆候の確認作業を開始する.
(6)異常原因候補の中で最も AS 値の高いものを選択.
(7)異常原因候補が存在していない場合は,
(12)で異常原因候補から一時的に
除外していた原因を回復し,0.5 秒待って(6)の手前へ戻る.
(8)(4)で選択した異常原因候補に関係する兆候の中で AS 値の高いものを確
認する兆候に選択.
(9)探索すべき兆候が存在しない場合は,注目異常原因を次の異常原因へ移す
ため,
(6)の手前へ戻る.
(10)(8)で選択した兆候が現れているか DCS 画面より確認する.
(11)(10)で兆候が確認された場合は,現在注目している(6)で選ばれた原因
候補と(8)で選ばれた兆候の組合せの AS 値を AS 合計値に加算する.
(12)(11)で兆候が確認されなかった場合は,該当する原因候補が過去に除外
されているならば(8)へ,除外されるのがはじめてならば注目していた原
因候補を候補から除外して(6)へ戻る.
20
Fig. 9 オペレータモデル B の ASSP フローチャート
21
Fig. 10 ASSP フローチャート省略記号
3.2.2 オペレータモデルの動作比較
オペレータモデル A とオペレータモデル B で,異常診断過程の違いを見るため
に,異常診断シミュレーションを行った.
シミュレーションの条件は以下のように設定した.アラーム設定は,2 節 Table
4 に示す 各タグの平常時の値変動の上下限値に,計測範囲の 1 % の値をマージン
として加えた値を使用した.このアラーム設定を Table 7 に示し,以下 SettingA
と表記する.発生させる異常は Mal-10:P204SENSOR とした.Fig.11 に Mal-10
発生後 300 秒までの主要プロセス変数のトレンドデータのグラフを示す.Fig.11,
各グラフ中の 2 本の破線は HI と LO もしくは MHI と MLO の設定値である.ま
た,トレンドデータに F206.PV の値に,1Hz の sin 波と測定範囲の 2 % の積を
ノイズとして加え,シミュレーション中に F206.PV のアラームが発生するように
した.F206.PV のアラームが発生すると,F206.PV は Mal-10 には関係がないた
め,異常原因である Mal-10 が原因候補から外される.
アラームの設定: SettingA(Table 7 )
同定とする合計 AS 値の閾値: 0.6
発生マルファンクション: Mal-10:P204SENSOR
22
Fig. 11 Mal-10 発生後の主要プロセス変数のトレンドデータ
23
tag
HH
P201
-
P202
-
Table 7 アラームの設定(SettingA)
PH
PL
LL VL
Unit1
MH
81.6
85.6
78.3
82.3
-
ML
Unit2
-
Kg/cm2
-
-
%
-
2
-
-
%
Kg/cm
2
P203
-
-
-
-
-
Kg/cm
P204
-
4.25
3.6
-
-
Kg/cm2
-
-
%
P206
-
98.2
95.7
-
-
Kg/cm2
-
-
-
F201
-
83.4
76.9
-
-
t/h
-
-
-
F202
-
7.33
6.68
-
-
t/h
-
-
%
F203
-
-
-
-
-
-
F204
-
72.9
68.9
-
-
t/h
-
-
%
F205
-
82.11
74.59
-
-
t/h
-
-
%
F206
-
1.98
1.58
-
-
t/h
-
-
%
T201
-
492.8
477.4
-
-
℃
-
-
%
T203
-
302.8
293.9
-
-
℃
-
-
-
T204
-
91
88.1
-
-
℃
-
-
-
L202
-
3.12
−3.63
-
-
mm
-
-
%
A201
-
2.88
2.51
-
-
%
-
-
%
A202
-
30.7
18.5
-
-
ppm
-
-
%
C208
-
-
-
-
-
-
73.9 65.1
54.7 50.1
50.9 48.1
%
%
%
異常診断シミュレーションの結果,オペレータモデル A では一定タスク数内に
原因を同定できずに終了したのに対し,オペレータモデル B では,正しく Mal-10:
P204SENCOR の同定することができた.Table8,Table9 にはオペレータモデル
A,B の合計 AS 値の変化の様子を,Fig.12 にはオペレータモデル A,B の Mal-10
における合計 AS 値の変化の様子を示す.ただし,Table8 は同定ができないまま続
くので,異常発生後 1 分後までを掲載した.Table8,Table9 の発生アラームの項
目には発生したアラーム全て発生時間と内容を,経過時間以降の列にはオペレー
24
タモデルによる異常診断過程にともなう,時間,合計 AS 値,異常診断の過程を
示す.FDI プロセスの(再)という表示は,過去に確認したことのあるアラーム
を再度確認したことを表している.アラーム発生時間と異常診断の経過時間は,
はじめてのアラーム発生時間を 0 秒としている.なお,Table8,Table9 の FDI プ
ロセスには合計 AS 値が上昇した場合のみを掲載しているため,兆候を確認して
兆候が確認されなかった場合は掲載されていない.
Table 8 オペレータモデル A の異常診断シミュレーション結果
Table 9 オペレータモデル B の異常診断シミュレーション結果
Table8 より,オペレータモデル A は 2 つ目発生アラーム F206.ALRM.HI など
いくつかのアラームを見落としているが,Table9 より,オペレータモデル B は発
生アラームを全て確認している.さらに,一度 Normal 以外の状態になり,その
25
Fig. 12 Mal-10 における合計 AS 値の変化
後 Normal に戻ったという情報が,オペレータモデル A では無視されているが,
オペレータモデル B では確認している.
Table8 より,オペレータモデル A では,F206.HI のアラームが発生した時点で,
真の異常原因である Mal-10 は異常原因候補から除外されると同時に合計 AS 値
が 0 にリセットされ,同定することはできない.しかしオペレータモデル B では,
Table9 に示すように F206.HI が一度発生するものの,F206.NR の発生を確認す
ると,結果として Mal-10 を異常原因として特定できている.Fig.12 より,オペ
レータモデル A では,合計 AS 値のリセット後に合計 AS 値が上昇することはな
いが,オペレータモデル B では,F206.HI 発生時に合計 AS 値のリセットはされ
ず,F206.NR 確認後には,再び合計 AS 値が上昇し,原因同定完了の判定閾値の
0.6 に達している.
以上の結果より,オペレータモデル B ではアラームステータス NR の確認と発
生アラーム全ての認識,アラーム発生中の兆候が Normal の状態に戻ったことに
よる原因候補の集合の再構成がされており,オペレータモデル A の問題点が解決
できていることを確認できた.
ただし,オペレータモデル B の原因同定の判断材料は,オペレータモデル A と
同じく,異常伝播図上での関係の有無のみであるため,異常伝播図上,発生する
はずのない兆候のアラームが現れて,消えなかった場合には,オペレータモデル
26
B は正常な同定を行うことができない.
3.3 オペレータモデルを用いた
リアルタイムアラームマネジメントの評価
3.3.1 サプレッションの方法
本ケーススタディでは,リアルタイムアラームマネジメントの方法として,単
一タグのアラームステータスが短時間で切り替わるチャタリングアラームを抑制
するサプレッションを評価の対象する.通常,アラームステータスは,設定され
た閾値を横切る度に更新される.本ケーススタディで使用したサプレッションの
方法では,アラームが変化した後,一定の保留時間,アラームステータスが保た
れた場合にアラームステータスを更新する.具体的なサプレッションの方法を以
下に示す.なお,保留時間は 10 秒とした.
1. NR の状態から,High または Low になった場合には,DCS 上でアラームを
発生する.
2. アラームステータスが変化した後,設定した保留時間,同じ状態が保たれ
れば DCS 上のアラームの状態表示を更新する.
3.3.2 評価シミュレーション
作成したオペレータモデルを用いて,サプレッションを評価するシミュレーショ
ンを行った.比較したのは,サプレッションを行わない場合と,第 3.3.1 節の保
留時間が 10 秒のサプレッションを行った場合の 2 つについてである.シミュレー
ションの条件を以下のように設定した.アラーム設定は Table 10 に示す設定と
し,以下 SettingB と記述する.
アラームの設定: SettingB(Table 10 )
同定とする合計 AS 値の閾値: 0.8
発生マルファンクション: Mal-10:P204SENSOR
27
Table 10 アラームの設定(SettingB)
PH
PL
LL VL
Unit1
MH
tag
HH
ML
Unit2
P201
-
81.6
-
-
-
Kg/cm2
-
-
%
P202
-
−3.8
−16.9
-
-
Kg/cm2
-
-
%
P203
-
−3.8
−16.9
-
-
Kg/cm2
-
-
%
P204
-
5.6
2.25
-
-
Kg/cm2
-
-
%
P206
-
-
95.7
-
-
Kg/cm2
-
-
-
F201
-
-
-
-
-
t/h
-
-
-
F202
-
-
6.68
-
-
t/h
-
-
%
F203
-
-
-
-
-
-
-
50.1
%
F204
-
-
-
-
-
t/h
-
-
%
F205
-
-
-
-
-
t/h
-
-
%
F206
-
1.98
-
-
-
t/h
-
-
%
T201
-
-
-
-
-
℃
-
-
%
T203
-
302.8
-
-
-
℃
-
-
-
T204
-
-
88.1
-
-
℃
-
-
-
L202
-
-
-
-
-
mm
-
-
%
A201
-
-
2.51
-
-
%
-
-
%
A202
-
-
-
-
-
ppm
-
-
%
C208
-
-
-
-
-
-
28
50.9 48.1
%
使用するプロセストレンドデータは,チャタリングアラームを発生させるため,
複数のタグに,0∼1 のランダム値と各タグの計測範囲の 2% の積を加算した.Fig.
13 は,アラームの発生した数を 10 秒ごとにまとめたグラフである.サプレッショ
ンなしの場合,Fig. 13 では,サプレッションによって,多くのアラームが抑制
されていることが示されている.
Fig. 13 10 [s] ごとのアラーム発生回数( 0 [s] ∼ 70 [s])
3.3.3 評価結果と考察
シミュレーションの結果,サプレッションを行った場合,行わなかった場合,ど
ちらのケースでも異常原因が Mal-10 であると正しい同定ができた.評価結果を
Table11 に,サプレッションを行わなかった場合,行った場合の異常診断シミュ
レーションによる合計 AS 値の変化の様子を,Table12,Table13 に示す.Table11
より,サプレッションを行った場合の方が,同定時間が短のに対し,視線移動距
離やオペレーショナルステージ数はサプレションを行った場合の方が多いという
結果になった.
オペレータモデルの思考の詳細を出力したものを確認すると,サプレッション
を行わない場合には何度も兆候確認の作業の途中でアラームの確認作業が頻発す
29
Table 11 評価結果
サプレッション
なし
あり
同定時間 [s]
65
56
オペレーシショナルステージ
132
206
発生したアラーム数
17
5
視線移動距離 [cm]
559
1041
確認成功回数
3
8
確認失敗回数
19
55
るのに対し,サプレッションを行った場合は兆候の確認作業がアラーム発生によっ
て妨げられないために,兆候確認作業がより多いオペレーショナルステージの間
行われていた.
Fig.14 と Fig.15 に,兆候確認回数と,確認した兆候の種類の数の時間変化の
様子を示す.ig.14 と Fig.15 において,上 2 つのグラフは,TURBINE_ TRIP,
P204SENSOR,それぞれに注目しての兆候確認回数および,種類の数,下のグラ
フはそれらを合計しての兆候確認回数および,種類の数である.Fig.14 から,サ
プレッションをした場合の方が候数の確認回数が多いことが分かる. Fig.15 を見
ると確認した兆候の種類の数に関してもサプレッションをした場合の方が多いこ
とが分かる.これらのことから,サプレッションを行った場合の方が,サプレッ
ションをしなかった場合よりも確認回数が多いのは, ただ多くの同じ兆候を確認
しているのではなく,より多くの種類の兆候を確認が行われているためである.
Fig. 16,Fig.17 は,異常発生後 70 秒までのアラーム発生回数の累積の時間変
化,合計 AS 値の時間変化を,それぞれ,サプレッションあり,サプレッション
なしの場合について,示したグラフである.Fig. 16,Fig.17 より,サプレッショ
ンによって発生アラーム数が抑制されていても,合計 AS 値がサプレッションを
行わない場合よりも速く増加していることが示されている.
以上の結果より,サプレッションを行うことで,同定時間は 10 秒弱短縮され,
アラームの発生が非常に多く抑制されていても,合計 AS 値の時間変化はサプレッ
ションを行わなかった場合よりも速く増加していることから,原因探索が効率的
30
Table 12 サプレッションを行わなかった場合の異常診断シミュレーション結果
Table 13 サプレッションを行った場合の異常診断シミュレーション結果
31
に行われていることが示されている.サプレッションを行った場合の方が,オペ
レーショナルステージの数は増加していたが,兆候の確認によるものであること
が示された.本シミュレーションにより,チャタリングアラームに対するサプレッ
ションの有効性を示すことができた.
本オペレータモデルの知識ベースは対象プラントのユーザパネルや異常伝播図
から作成できる.シミュレーション時にオペレータモデルに入力されるデータは,
各兆候についてのアラームステータスと計測値のみであるので,一般的なプラン
トに対して汎用性がある.
32
Fig. 14 兆候の確認数の時間変化
Fig. 15 確認兆候の種類数の時間変化
33
Fig. 16 アラームの累積発生回数( 0 [s] ∼ 70 [s])
Fig. 17 合計 AS 値の時間変化
34
4. 評価支援ソフトウェア
前章で述べたオペレータモデルを用いて,プラントアラームシステム設計支援
を目的としたツールを作成した.作成した本ソフトウェアは,オペレータモデル
を用いたシミュレーションにより,プラントアラームシステムの評価を行うツー
ルである.オペレータモデルによってオペレータの異常診断過程を模擬し,原因
同定までに要した時間,同定までに発生したアラーム数などを評価結果として出
力する.
本ソフトウェアはシミュレーションの設定,シミュレーションの実行,結果の
表示を行うことができる.本ソフトウェアに想定されるプラント異常発生時のプ
ロセストレンドデータを読み込んだ後,そのプロセストレンドデータに対して,
設定したアラーム設定,オペレータモデルを適用してアラーム発生時刻を計算し,
異常診断過程をシミュレートする.プラント異常発生時のプロセストレンドデー
タを読み込むインタフェースソフトウェアは,Liu らによる先行研究 [5] で作成さ
れたソフトウェアにアラーム設定の変更の反映とサプレッションの機能を加えた
ものである.本評価支援ソフトウェアの起動画面を Fig. 18 に,プロセストレン
ドデータを評価支援ソフトウェアに送信するインタフェースソフトウェアの起動
画面を Fig. 19 に示す.この画面でマルファンクションとサプレッションの有無,
種類を選択する.サプレッションの種類は前章で述べた保留時間を用いる方法で,
保留時間が 10 秒のサプレッションと 30 秒のサプレッションの 2 種類である.
評価支援ソフトウェアでの設定項目は以下の主に 3 項目である.
・ アラームの設定値
・ 異常診断ストラテジー
・ シミュレーションの条件
Fig. 20 異常診断ストラテジーの選択では,オペレータモデルの原因探索戦略
を複数の戦略の中から選ぶことができる.モデルによって兆候確認の優先順位を
算出する戦略が異なる.モデルは 3 種類あり,1 つは前章ので述べた,Liu 氏の
AS 値が高いものを優先する戦略,残りの 2 つは異常伝播図に現れる順番を考慮
した戦略で,詳細は付録 A に添付する.
35
Fig. 18 評価支援ソフトウェア起動画面
Fig. 21 パラメータの設定では,原因同定の閾値,同定されていない場合にも
強制的にシミュレーションを終了するサブタスク数の上限値を設定することがで
きる.
アラームの設定値は Fig. 22 で設定することができる.
出力項目は原因推測の結果,シミュレーション時間,初めのアラームが発生す
るまでの時間,同定に要した時間,オペレーショナルステージ数,解決までに発
生したアラーム数,視点移動距離,確認成功・失敗回数といった「評価結果」
「オ
ペレータモデルの異常原因探索の過程」である.評価結果は,Fig.18 のウィンド
ウの評価結果の部分にシミュレーション条件と共に表示される.また,txt ファ
イルや csv ファイルとしても出力される.
36
Fig. 19 プロセストレンドデータ表示ソフトウェア起動画面
Fig. 20 オペレータモデルの選択画面
37
Fig. 21 パラメータの設定
Fig. 22 アラーム設定の画面
38
4.1 評価手順
Fig.23 はプラントアラームシステムを本ツールで評価する手順である.
Fig. 23 提案する評価手順
1. 想定されるマルファンクション発生時のプロセストレンドデータの読み込み
2. 評価したいアラーム設定の入力
3. シミュレーションの設定,シミュレーション
4. 評価結果の検討
入力するデータは対象プラントで想定されるマルファンクション発生時のプロ
セストレンドデータと,評価したいアラーム設定である.これらを本ツールにて
読み込み,シミュレーション設定,シミュレーションを行う.設計者は得られた
評価結果を EEMUA 等のガイドラインと照らし合わせ検討する.このツールの
特徴として,Fig. 22 の画面のように,GUI を用いて簡単に設定し,手順(2)∼
(3)の工程を設定を変えて容易に繰り返すことができる.EEMUA が提唱する,
定量的かつ人間の情報処理能力を考慮した評価が可能となる.
39
5. 結論
5.1 研究成果
本研究では,リアルタイムアラームマネジメントの手法の一つ,アラームサプ
レッションの評価を行うことを目的として,オペレータモデルを作成し,そのオ
ペレータモデルを用いたシミュレーションによってプラントアラームシステム定
量的評価の支援を行うソフトウェアを作成した.
作成したオペレータモデルでは,アラームステータス NR のアラームや,ON,
OFF を繰り返すアラームを認識できる.発生するはずのない兆候のアラームが発
生した異常原因候補は,その時点で異常原因候補の集合から除外されるが,その
後プロセス変数の値が Normal の範囲に戻れば,異常原因候補が再構成され同定
することが可能である.
オペレータモデルを用いたシミュレーションによる評価を行い,オペレータモ
デルの思考過程や兆候確認回数などの結果から,チャタリングアラームに対する
サプレッションの有効性を示した.
また,オペレータモデルを用いたシミュレーションを GUI にて設定・実行を行
うことができる,プラントアラームシステム評価支援ソフトウェアを作成し,機
能と利用手順を示した.GUI によりシミュレーションの設定・実行ができるため,
設計者は得られた定量的評価結果をガイドラインなどと照らし合わせて検討し,
さらに設定を変えて容易に繰り返し評価・検討することができる.
5.2 今後の課題
本研究で評価対象としたリアルタイムアラームマネジメントの手法は,単一タ
グからのチャタリングアラームのみであった.はじめに挙げたその他のリアルタ
イムアラームマネジメント手法,シェルビング,状態ベースアラーム管理機能や,
複数のタグからのアラームサプレッション,に対する評価が必要である.近年,
タグにそのアラームについての情報を付加し,重要なアラームを選んで優先順位
付けをする手法も用いられている.リアルタイムアラームマネジメントの様々な
40
手法や,優先順位付けに対するオペレータモデルを用いた定量的評価の検討が,
今後の課題であると考える.
本研究のオペレータモデルでは,測定値が変動によるアラームの ON・OFF の
認識と異常原因候補の再構成が可能となったが,知識ベースは定常状態での原因兆候関係を用いている.測定値が変動する過渡状態を知識を内包した知識ベース
の検討・作成もまた,今後の課題であると考える.
41
謝辞
本研究を進めるにあたり御指導,御教授を頂きました,主指導教員の奈良先端
科学技術大学院大学情報科学研究科の西谷紘一教授に厚く御礼申し上げます.
お忙しい修士論文審査を引き受けて下さり,貴重な御助言を頂きました,副指
導教員の奈良先端科学技術大学院大学情報科学研究科の木戸出正繼教授に厚く御
礼申し上げます.
本研究を進めるにあたり,御指導と御教授を頂きました,副指導教員の奈良先
端科学技術大学院大学情報科学研究科の野田賢準教授に心より厚く御礼申し上げ
ます.
本研究を進めるにあたり,リサーチミーティング等にて御助言を頂きました,
奈良先端科学技術大学院大学情報科学研究科の小坂洋明助教,中村文一助教,竹
本雅憲特任助教に心より厚く御礼申し上げます.
本研究を進めるにあたり,基となるプログラムや研究についての質問にいろい
ろ答えて下さった,Liu Xiwei さん,Luo Yan さんに厚く御礼申し上げます.
最後になりましたが,日常の手続きをはじめ,大学院生活を支えて下さった制
御管理講座秘書の青盛まどかさん,多大な助言や励ましを下さったシステムシス
テム制御管理講座の皆様,支えて下さった皆様に厚く御礼申し上げます.
42
参考文献
[1] EEMUA:”ALARMS SYSTEMS -A GUIDE TO DESIGN, MANAGEMENT
AND PROCUREMENT-”,EEMUA Publication 191, Second Edition,
2007
[2] 高井努:”化学プラントにおけるアラームマネジメントの動向”,ヒューマン
ファクターズ,Vol.12,No.1,pp.10-23,2007
[3] Bill R. Hollifield and Eddie Habibi (PAS) : ”The Alarm Management
Handbook -A Comprehensive Guide-”, Fidlar Doubleday, First Edition,
2006
[4] Luo YAN,Liu XIWEI,Masaru NODA,Hirokazu NISHITANI:”Systematic
Design Approach for Plant Alarm Systems”,Journal of Chemical Engineerring of Japan, Vol.40, No.9, pp.765-772 , 2007
[5] Xiwei Liu: ”Evaluation of User Interfaces in Plant Operations by Using Informaition Processing Models”,Doctoral Thesis, Nara Institute of Science
and Technology, 2006
[6] 野田賢 : ”EEMUA ガイドラインにみるプラントアラームシステムの設計と
評価” ,化学工学会第 39 回秋季大会 , 2007
[7] 横河電機株式会社 システム PMK 部ドキュメント Gr:”CENTUM-CS 運
転員訓練シミュレータ 80T/H ボイラプロセス ”,横河グラフィックアーツ
株式会社,1994
[8] Xiwei Liu, Hiroaki Kosaka, Masaru Noda, and Hirokazu Nishitani : ”Modelbased Dynamic Evaluation to Support the Design of Alarm Systems Part 1:
Development of Virtual Subject”, ヒューマンファクターズ , Vol.11,No.2,
pp.118-127, 2006
[9] Card, S. K., Moran, T. P., and Newell, A.:”The Psychologyof HumanComputer Interaction”,Lawrence Erlbaum Associates,London,1983
43
付録
A. 異常伝播図上の兆候出現の順番を考慮した探索戦略
A.1 目的
Liu らによって作成されたオペレータモデル A は,異常原因と兆候の関係は,
Fig.24 の左側の図のような時間要素を含まない定常状態のモデルで表され,異常
伝播図から異常と兆候の関係性の強さを表す AS 値が大きい兆候から順番に確認
を行う探索戦略によって異常診断がされている.しかし,実際には各兆候が現れ
る時間には差があり,異常伝播図の兆候のつながりで表されるような時間的な順
序がある.
Table 14 は燃料漏れを異常原因としたときについて,各兆項に対して計算され
る AS 値と AS 値に応じて定められるプログラム上の優先順位と共に,異常伝播図
において原因からの数えた距離の順位と兆候確認時に兆候が現れていると判定さ
れる時間の順位を示している.Table 14 より,プログラム上の優先順位と兆候有
りと判定される時間の順位に差のある兆候があることが分かる.また,オペレー
タモデル A の原因探索過程からは,異常伝播図では時間が経過しないと現れない
兆候を早くから確認を繰り返す様子が見られた.
そこで,順序を考慮した Fig.24 の右側の図に表される情報をオペレータモデル
の知識にベース加えることで異常原因同定に要する時間が短縮できるのではない
かと考え,異常伝播図上の兆候出現の順番を考慮した探索戦略を提案した.
A.2 提案する探索戦略
異常伝播図上の兆候出現の順番についての情報を知識ベースに加えるため,新
しく Table15 のような 2 次元配列情報を追加した.
Table. 15 の Fm ,Sn は,第 3.1 節同様,インデックス m 番の異常原因,イン
デックス n 番の兆候を表している.なお,M ,N はそれぞれ異常原因と兆候のイ
ンデックスの最大値である.Sn と Fm の交点の値は,異常伝播図上で Sn − Fm 間
44
Table 14 各兆候の AS 値に基づく各種順位
プログラム 異常伝播図 兆候有り判定
兆候
AS
上の順位
距離の順位
の時間の順位
P203.PV.HIGH
0.086661
1
5
13
P204.PV.HIGH
0.08496176
2
10
5
F202.PV.HIGH
0.08496176
3
9
4
F202.MV.HIGH
0.06372131
4
8
2
F204.PV.HIGH
0.06372131
5
6
9
A201.PV.HIGH
0.06372131
6
1
1
R080.CPV.HIGH 0.06372131
7
6
11
C208.MV.LOW
0.06372131
8
3
1
T203.PV.LOW
0.05097705
9
1
7
F203.MV.HIGH
0.05097705
10
9
2
A202.PV.LOW
0.05097705
11
1
8
P203.MV.HIGH
0.05097705
12
8
10
T201.PV.LOW
0.05097705
13
2
3
F204.MV.HIGH
0.04248088
14
5
6
F206.PV.LOW
0.04248088
15
5
12
P202.PV.LOW
0.04248088
16
1
4
P201.PV.LOW
0.04248088
17
2
4
45
Fig. 24 異常原因と兆候の関係
Table 15 兆候出現順序の情報を表す 2 次元配列
F1 F2 · · · Fm · · · FM
S1
0
0
···
1
···
0
S2
..
.
2
..
.
3
..
.
···
..
.
0
..
.
···
..
.
3
..
.
Sn
..
.
0
..
.
0
..
.
···
..
.
3
..
.
···
..
.
0
..
.
SN
0
0
···
0
···
0
に関係がなければ 0,関係がある場合は Fig.25 に示すグループ分けに従って 1∼
3 の数値を設定する.
Fig.25 に示すグループは,式(2)を用いて 3 グループに分けた場合を示して
いる.
1 グループの兆候の数 =
最も遠い兆候までの距離
グループの数
(2)
ただし,直接発見できないことを意味する破線で囲まれた兆候は数えない.また,
商の余りは中央のグループに分配する.
Fig.25 の場合,最も遠い兆候までの距離は 8 なので,各グループの兆候の数は
2,4,2 となる.Table. 15 では,最も異常発生に近いグループに属する兆候に,グ
46
Fig. 25 兆候の発生順序によるグループ
ループ数を最高値として 3,次のグループには 2,続いて 1 と設定する.Sn − Fm
間に設定したこの数値を,以降,AO(Appear Order)値と表記する.
兆候確認時の優先順位を決める値を優先度として,この値が大きい兆候から確
認を行うとすると,Liu 氏らが用いていた探索戦略では AS 値がそのまま優先度
である式(3)となる.
提案する探索戦略は,AO 値を AS 値の和と積が優先度とする 2 つの探索戦略
である.
式(4)和を優先度とする探索戦略では,AO 値が大きいものが優先され,同じ
AO 値同士では AS 値が大きいもの優先される.式(5)積を優先度とする探索戦
略では,概ね AO 値が大きいものが優先されるが,AS 値の大きさによっては前
後する.
優先度 = AS 値
(3)
優先度 = AO 値 + AS 値
(4)
優先度 = AO 値 × AS 値
(5)
以降,Liu 氏らが用いていた探索戦略を StrategyA,提案する AO 値+AS 値を
用いる探索戦略を StrategyB,AO 値 ×AS 値を用いる探索戦略を StrategyC,と
表記する.
StrategyB,C での検索の順番を Fig.26,Fig.27 に示す.
47
Fig. 26 StrategyB における兆候確認の順序
Fig. 27 StrategyC における兆候確認の順序
48
A.3 シミュレーション
本シミュレーションでは,第 2 節にて挙げた,ボイラープラントシミュレータ
で想定されている 11 種類の異常の内,必要なプロセス変数のデータの取得等の問
題から用いることができなかった異常原因を除く 5 つの異常原因,Mal-5,Mal-8,
Mal-9,Mal-10,Mal-11 について行った.
シミュレーションの条件は以下のように設定した.このアラーム設定を Table
16 に示し,以下 SettingC と表記する.
アラームの設定: SettingC(Table 16 )
同定とする合計 AS 値の閾値: 0.6
発生マルファンクション: O2ANALYZERFAIL(Mal-5),TURBINETRIP(Mal-8),
OILHEAREFAIL(Mal-9), P204SENSOR(Mal-10),
FUELLEAK(Mal-11)
A.4 評価結果と考察
評価結果を Table17 に示す.提案した StratagyB では原因同定までの所要時間
や確認回数が StrategyA に比べ大幅に増加している.StrategyC では異常原因に
よって異なり,概ね StrategyB に近い結果だが, StrategyA に近い場合もあった.
StrategyB,C が,StrategyA よりも原因同定の所要時間などが増加しているこ
とについて,Mal-11:FUELLEAK に注目して考察を行った.28 は Mal-11 にお
ける StrategyA,B,C の Mal-11 に対する合計 AS 値の時間変化を表したグラフ
である.Table17 の評価結果で見たように,StrategyA 合計 AS 値が最も速く増加
してる.28 より,合計 AS 値が増加しない区間について,StrategyA よりも長い
区間がいくつか見られる.
29 は Mal-11 における兆候の確認を行って,成功した回数と失敗した回数をグ
ラフに表したものである.29 では,真の原因である FUELLEAK に対する成功回
49
tag
HH
Table 16 アラームの設定(SettingC)
PH PL
LL VL
Unit1
MH ML
P201
90
85
P202
-
-
75
-
70
-
Unit2
-
Kg/cm2
-
-
%
-
2
-
-
%
2
Kg/cm
P203
-
50
−50
-
-
Kg/cm
-
-
%
P204
-
-
2.2
2
-
Kg/cm2
-
-
%
P206
-
-
-
-
-
Kg/cm2
-
-
-
F201
-
-
-
-
-
t/h
-
-
-
F202
-
-
-
-
-
t/h
-
-
%
F203
-
-
-
-
-
-
-
40
%
F204
-
-
25
20
-
t/h
-
-
%
F205
-
90
-
-
-
t/h
-
-
%
F206
-
-
-
-
-
t/h
-
-
%
480
470
-
℃
-
-
%
T201
520 500
T203
-
-
-
-
-
℃
-
-
-
T204
-
-
-
-
-
℃
-
-
-
L202
95
50
−50
−95
-
mm
-
-
%
A201
-
-
1.5
0.5
-
%
-
-
%
A202 275 150
-
-
-
ppm
-
-
%
C208
-
-
-
-
60
40
%
-
-
数と失敗回数に注目すると,StrategyA に比べ,StrategyB,C では確認成功回数
が多い.しかし同時に,確認失敗回数も StrategyA に比べ,StrategyB,C の方が
多い.また,真の原因以外の原因候補に対する成功回数と失敗回数も増加してお
り,真の原因以外の原因候補に対する兆候確認が StrategyA に比べ多いことが示
されている.
以上のことから,StrategyB,C が,StrategyA よりも原因同定の所要時間など
が増加している原因として,兆候確認の回数が成功・失敗共に,真の原因以外の
50
Table 17 評価結果
Fig. 28 Mal-11 における Mal-11 に対する合計 AS 値の時間変化
51
Fig. 29 Mal-11 における兆候確認成功回数・失敗回数
52
ものも増加し,他の原因候補に対する探索時間も増えたことが考えられる.
また,28 から,合計 AS 値の増加について,増加幅が小さいものが見られる.
本オペレータモデルは原因同定の判断に AS のみを用いているため,AS 値の大き
さが原因同定の速さへの影響が大きい.AS 値以外の優先基準を取り入れたため
に,兆候が確認できて加算される AS 値が大きいとは限らないことも原因である
と考えられる.
短時間で原因判定ができる異常診断探索戦略として 2 つの探索戦略を提案した
が,これらの理由から,StrategyA に比べ原因同定までの所要時間や確認回数が
増加する結果となった.
53
B. オペレータモデルのソースコード
オペレータモデルのソースコード主要関数を以下に示す.
public class LTMemory//長期記憶クラス
{
//関数:次にチェックすべき S の Index を nextSIndex を調べる strategyA
//(原因探索の基点となる兆候のインデックス,兆候を調べた数,調べる異常原因のインデックス,
//調べる兆候のインデックス,対象原因に対する全兆候を調べたフラッグ)
public bool ASS1(int firstIndex, string[] ConfirmedSymptom, ref int times,
out int failureIndex, out int nextSIndex, out bool rewind)
{
failureIndex = 0;
nextSIndex = 0;
bool result = true;
rewind = false;
int zeroNum = 0;
for (int m = 0; m < malfuncNum; m++)
{
//対象としている F の AS を計算
AS[m] = (weight[firstIndex, m] / SL[firstIndex] / sigma(m)) * alarmRejectIndex[m];
if (AS[m] == 0)//AS=0 即ち対象としている S に関係のない F の数を数える
{
zeroNum++;
}
}
if ((rejectTime < malfuncNum - zeroNum))
{
failureIndex = selectIndex(AS, rejectTime);
if (AS[failureIndex] == 0) MessageBox.Show("Error on selection of failure cause!");
}
else
{
for (int i = 0; i < malfuncNum; i++)
{
rejectIndex[i] = 1;
}
rejectTime = 0;
failureIndex = selectIndex(AS, 0);
result = false;
}
int positiveCount = 0;
float tempTest = 0;
for (int j = 0; j < FSmatrix.Length / malfuncNum; j++)//次に調べる兆候を AS 値を基に選ぶ
{
symptomAS[j] =
(SL[j] != 0) ? weight[j, failureIndex] * FSmatrix[j, failureIndex] / SL[j] / sigma(failureIndex) : 0;
tempTest += symptomAS[j];
if (symptomAS[j] != 0)
{
positiveCount++;
}
while (true)//まだ調べるべき兆候が残ってるか,残っていれば次の兆候を選択
{
if (times < positiveCount)
{
nextSIndex = selectIndex(symptomAS, times);//time 番目に AS の大きい index を nextSIndex に設定
if (ConfirmedSymptom[failureIndex].IndexOf(abnormality[nextSIndex]) > 0 ||
nextSIndex == firstIndex)
{
times++;
54
}
else
{
break;
}
}//end if (times < positiveCount)
else
{
rewind = true;
break;
}
}// end while(true)
if (failureCause[failureIndex] == "FUELLEAK" && abnormality[nextSIndex] == "P203.PV.LOW" && !rewind)
MessageBox.Show("Error!!");
return result;
}
//********順序決定のための関数 strategyB
//関数:次にチェックすべき S の Index を nextSIndex を調べる
//(原因探索の基点となる兆候のインデックス,兆候を調べた数,調べる異常原因のインデックス,
//調べる兆候のインデックス,対象原因に対する全兆候を調べたフラッグ)
public bool ASS2(int firstIndex, string[] ConfirmedSymptom, ref int times,
out int failureIndex, out int nextSIndex, out bool rewind)
{
//************************
次に確認すべき F の選択
strategyA と同じ為,記載省略
//************************
int positiveCount = 0;
float tempTest = 0;
//******** 優先順位に関わる値の計算地点 OA 以下
for (int j = 0; j < FSmatrix.Length / malfuncNum; j++)
{
symptomAS[j] =
(SL[j] != 0) ? weight[j, failureIndex] * FSmatrix[j, failureIndex] / SL[j] / sigma(failureIndex) : 0;
tempTest += symptomAS[j];
symptomAO[j] = AOmatrix[j, failureIndex];//symptomOA 計算式
if (symptomAS[j] != 0)
{
positiveCount++;
symptomPP[j] = symptomAO[j] + symptomAS[j];//symptompp 計算式
}
else
{
symptomPP[j] = 0;//symptomAS が 0 ならば優先順位は 0 とする
}
}
//*************************
while (true)
{
if (times < positiveCount)
{
nextSIndex = selectIndex(symptomPP, times);
if (ConfirmedSymptom[failureIndex].IndexOf(abnormality[nextSIndex]) > 0 || nextSIndex == firstIndex)
{
times++;
}
else
{
break;
}
55
}
else
{
rewind = true;
break;
}
}
if (failureCause[failureIndex] == "FUELLEAK" &&
abnormality[nextSIndex] == "P203.PV.LOW" && !rewind) MessageBox.Show("Error!!");
return result;
}
//****************順序決定のための関数 strategyC
//関数:次にチェックすべき S の Index を nextSIndex を調べる
//(原因探索の基点となる兆候のインデックス,兆候を調べた数,調べる異常原因のインデックス,
//調べる兆候のインデックス,対象原因に対する全兆候を調べたフラッグ)
public bool ASS3(int firstIndex, string[] ConfirmedSymptom, ref int times, out int failureIndex,
out int nextSIndex, out bool rewind)
{
//************************
次に確認すべき F の選択
strategyA と同じ為,記載省略
//************************
int positiveCount = 0;
float tempTest = 0;
//********
優先順位に関わる値の計算地点 OA 以下
for (int j = 0; j < FSmatrix.Length / malfuncNum; j++)
{
symptomAS[j] =
(SL[j] != 0) ? weight[j, failureIndex] * FSmatrix[j, failureIndex] / SL[j] / sigma(failureIndex) : 0;
tempTest += symptomAS[j];
symptomAO[j] = AOmatrix[j, failureIndex];//symptomOA 計算式
if (symptomAS[j] != 0)
{
positiveCount++;
symptomPP[j] = symptomAO[j] * symptomAS[j];//symptompp 計算式
}
else
{
symptomPP[j] = 0;//symptomAS が 0 ならば優先順位は 0 とする
}
}
//*************************
while (true)
{
if (times < positiveCount) //the number of positive elements for the symptoms AS
{
nextSIndex = selectIndex(symptomPP, times);
if (ConfirmedSymptom[failureIndex].IndexOf(abnormality[nextSIndex]) > 0 || nextSIndex == firstIndex)
{
times++;
}
else
{
break;
}
}
else
{
rewind = true;
break;
56
}
}
if (failureCause[failureIndex] == "FUELLEAK" &&
abnormality[nextSIndex] == "P203.PV.LOW" && !rewind) MessageBox.Show("Error!!");
return result;
}
}
public class hmimodel
{
//関数:summary_Disp_Alarms(未処理アラーム) 配列の更新(前回の state との比較によって行う)
//返り値:Stack のアラームの数
public int new_Alarm_Stack()
{
string[] Now_Alarms = new string[alarmNum]; ;
Array alarms = Array.CreateInstance(typeof(object), alarmNum);
alarms = Ahmi.bulkDataRead(alarmVar);//各タグのデータの取得
//以下の配列処理において,alarmVar でデータは同じ順番に並んでいる保障があるとしてタグ名は格納しない
//***アラームのタグ名とその状態を currentAlarm[] 配列に格納 (NoData も含む)***
for (int i = 0; i < alarmNum; i++)
{
Now_Alarms[i] = (string)alarms.GetValue(i);
}
//***before_Alarms に値が格納されていない場合 before_Alarms を NR で初期化***
if (before_Alarms[0] == null)
{
for (int j = 0; j < before_Alarms.Length; j++)
{
before_Alarms[j] = "NR";
}
}
string tempstr = null;
//**今までのの summary_Disp_Alarms を tempstr にの字列として代入
if (summary_Disp_Alarms != null)
{
for (int k = 0; k < summary_Disp_Alarms.Length; k++)
{
tempstr += summary_Disp_Alarms[k] + ",";//k 番目のデータの値を get
}
}
//*****比較処理
for (int l = 0; l < before_Alarms.Length; l++)
{
//if (Now_Alarms[l] != "NR" && (Now_Alarms[l] != "NoData"))
if (Now_Alarms[l] != "NoData")
{
if (before_Alarms[l] != Now_Alarms[l])
{
//k 番目のデータの値を get
tempstr += alarmVar[l].Substring(0, 5) + (string)alarms.GetValue(l) + ",";
}
}
}
//*****Now_Alarms を before_Alarms へコピー
for (int m = 0; m < before_Alarms.Length; m++)
{
before_Alarms[m] = Now_Alarms[m];
}
int tempLen = 0;
57
int ansLen = 0;
if (tempstr != null)
{
tempLen = tempstr.Length;
tempstr = tempstr.Remove(tempLen - 1);
summary_Disp_Alarms = tempstr.Split(’,’);
ansLen = summary_Disp_Alarms.Length;
}
else
{
summary_Disp_Alarms = new string[] { };
ansLen = 0;
}
return ansLen;
}
}
//関数:Interface からデータを読み込み,新しいアラームがあった場合は OnAlarmOccur イベントを起こす
//返り値:新しいアラームがあったかどうか.
(ループに入ったかどうか)
public bool checkAlarm()
{
short jj = 0;
int tempLen = 0;
bool ans = false;
stackAlarmNum = new_Alarm_Stack();//summary_Disp_Alarms(未処理アラーム) 配列の更新
while (stackAlarmNum > 0)
{
ans = true;
string tempstr = null;
if (order == 0)
{
refresh1S_endRefresh();//1 秒ごとにアラーム確認するイベントを停止
}
order++;
newAlarm = summary_Disp_Alarms[0];
if (summary_Disp_Alarms[0].Length<=4)
{
int aa = 0;//デバッグ
}
//******添え字 0 のアラームを NewAlarm として,それを summary_Disp_Alarms から削除した配列を作り直す
if (stackAlarmNum > 1 && summary_Disp_Alarms[0] != null)
{
for (int i = 1; i < summary_Disp_Alarms.Length; i++)
{
tempstr += (summary_Disp_Alarms[i] + ",");
}
tempLen = tempstr.Length;
tempstr = tempstr.Remove(tempLen - 1);
summary_Disp_Alarms = tempstr.Split(’,’);
stackAlarmNum = summary_Disp_Alarms.Length;
}
else
{
summary_Disp_Alarms = new string[] { };
stackAlarmNum = 0;
}
OnAlarmOccur(EventArgs.Empty);//アラーム発見イベントの発生
//結果報告中以降ならば
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
58
{
break;
}
}
return ans;
}
public class Perception : System.Windows.Forms.Form //認知プロセッサクラス
{
//*****関数(イベント)原因の同定を行い,結果を出力する
//lock の記入は一連の処理のためアラームチェックが危険な区間
private void Ahmimodel_AlarmOccur(object sender, EventArgs e)
{
string output_str = null;
bool no_ConfirmedAlarm = false;//一つも ConfirmedAlarm がなくなったときに true
bool NRalarmFlag = false;//NewAlarm が NR のとき true の Flag
try
{
//
// lock section1 ->*/
//
int times = 0, failureIndex = 0;
bool alarmAppear = true;//alarmAppear:アラーム発生を示す
bool haveAppearedflag = false;//haveAppearedflag 過去に発生した事があることを示す;
//****1 回目の呼び出し時のみに行う処理.
//オブジェクトのインスタンス化や出力ファイルストリームの生成,初めの出力など
if (Ahmimodel.order == 1)
{
cognitiveTask = new Cognition();
LTMFDI = new LTMemory();
physical = new Motor();
STM = new STMemory();
currentTime = DateTime.Now;
TimeSpan malDiff = currentTime - malStart;
string fileNamePart = currentTime.Hour.ToString() + "-" + currentTime.Minute.ToString() +
"-" + currentTime.Second.ToString();
fileNamePart = causeMal + "@" + fileNamePart;
Share_data.Share_data.set_Auto_FilePath(fileNamePart);
sw = new StreamWriter(Share_data.Share_data.output_csv_path, false);
sw2 = new StreamWriter(Share_data.Share_data.output_txt_path, false);
sw.WriteLine(", No., FOP1FAIL, BURNER EXTINGUISH, BFP1TRIP, WATERTUBELEAK,
O2ANALYZERFAIL, FDFCAPACITYDOWN, IDFTRIP, TURBINETRIP, OILHEAREFAIL,
P204SENSOR, FUELLEAK");
this.txtChunk3 = malDiff.TotalSeconds.ToString() + " S";
//***
sw3 = new StreamWriter(Share_data.Share_data.output_Ordertxt_path, false);
//********
sw5 = new StreamWriter(Share_data.Share_data.output_Disptxt_path, false);
}
alarmCount++; //出ているアラームの数を++
//****視覚と STM 出力****
output_str = "New alarm appears at " + currentTime.ToString();
sw2.WriteLine("\n" + output_str);//sw2:output txt
sw.WriteLine("\n" + "New alarm appears at " + DateTime.Now.ToString());//sw:output csv
sw3.WriteLine("\n" + output_str);//sw3:order txt
exe_listBox.Items.Add(output_str);
59
sw5.WriteLine(output_str);
//****debug
StreamWriter sw4 = new StreamWriter(Share_data.Share_data.exe_Current + @"\CheakData\" +
"Alarm_cheak" + ".txt", true);
sw4.WriteLine(currentTime.ToString("G"));
sw4.Close();
//****
//****アラーム発見と Persepton 出力****
sw2.WriteLine("=================================Alarm=================================");
sw3.WriteLine("=================================Alarm=================================");
exe_listBox.Items.Add("=================================Alarm=================================");
this.Refresh();
sw5.WriteLine("=================================Alarm=================================");
elapsed_time = DateTime.Now - currentTime;
elapsed_time_int = (elapsed_time.Hours *360) + (elapsed_time.Minutes * 60) + elapsed_time.Seconds;
output_str = elapsed_time_int + " [s] " + numberOfSubtask.ToString() +
": Perception: Detect an alarm " + Ahmimodel.newAlarm;
sw2.WriteLine(output_str);
sw3.WriteLine(output_str);
exe_listBox.Items.Add(output_str + "\n");
sw5.WriteLine(output_str);
numberOfSubtask++;
subtaskCount[PERCEPT]++;
txtOutput += "P-";
this.exe_listBox.Refresh();
//*****************
//*********STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//*****************
modelEye.move2position(490, 60); //alarm message on the menu /メニューバーの上に視点を移動
//関数:引数として渡されたアラームを confirmedAlarm から削除する.
if ((Ahmimodel.newAlarm).IndexOf("NR") >= 0)
{
NRalarmFlag = true;
//個数は Perception の alaemCount++のみで数える->認識した回数
//関数 offAlarmRejectInList :引数として渡されたアラームを confirmedAlarm から削除する.
Ahmimodel.offAlarmRejectInList(Ahmimodel.newAlarm);
}
string[] copyConfirmedAlarm = new string[Ahmimodel.getConfirmedAlarmLength()];
Ahmimodel.getConfirmedAlarm(ref copyConfirmedAlarm);
//copyConfirmedAlarm に関係のある F の Inndex を 1 にする
//前回のチェックアラームで NR に戻っていたアラームの F を回復(原因候補の集合の再設定)
LTMFDI.clearAndSetPossible(copyConfirmedAlarm);
//******newAlarm の処置
string detectedAlarm = Ahmimodel.newAlarm;
//search symptom in LTM abnormality
if (NRalarmFlag == false)
{
Ahmimodel.confirmAlarm(detectedAlarm);//confirmAlarm を更新
}
string[] haveAppearedAlarmCopy = new string[Ahmimodel.get_haveAppearedAlarmLength()];
Ahmimodel.get_haveAppearedAlarm(ref haveAppearedAlarmCopy);
for (int i = 0; i < haveAppearedAlarmCopy.Length; i++) //出たことがあるアラームチェック
{
if (haveAppearedAlarmCopy[i] == detectedAlarm)
60
{
haveAppearedflag = true;
break;
}
}
//*****見たことのあるアラームならばその旨を出力,ただし作業量は増えない
if (haveAppearedflag == true)
{
if (NRalarmFlag == false)
{
sw2.WriteLine("This alarm is an alarm that has already been confirmed: " +
Ahmimodel.newAlarm);
}
else
{
sw2.WriteLine("This alarm is an alarm that has already been confirmed. and an NR-Alarm: "
+ Ahmimodel.newAlarm);
sw2.WriteLine("Possible failure causes were recovered by the NR-Alarm");
}
}
if (haveAppearedflag == false)
{
Ahmimodel.confirm_haveAppearedAlarm(detectedAlarm);//haveAppearedAlarm を追加
}
//*******************
//*****発見されたアラームを Symptom の番号に変換********
int symptomIndex = -1;
string[] VarAlarm = null;
if (NRalarmFlag == false)//NR-Alarm でない場合
{
VarAlarm = detectedAlarm.Split(’.’);
detectedAlarm = VarAlarm[0] + LTMFDI.alarm_Symptom(VarAlarm[1]);
for (int i = 0; i < LTMFDI.abnormality.Length; i++)
{
if (detectedAlarm == LTMFDI.abnormality[i])
{
symptomIndex = i;//index of symptom from alarm info.
break;
}
}
if (symptomIndex == -1)
{
MessageBox.Show("Alarm Type Error!!!");
}
//****************************************************
//SymptomIndex (兆候のインデックス)の S に対して関係のない原因候補を集合から除外する
//アラームに関係のない原因を除外 (現時点の NewAlarm のみ)
LTMFDI.rejectByAlarm(symptomIndex);
LTMemory.rejectTime = 0;
}// end if (NRalarmFlag == false)
else
{
if (Ahmimodel.getConfirmedAlarmLength() > 0)
{
string[] copy = new string[Ahmimodel.getConfirmedAlarmLength()];
Ahmimodel.getConfirmedAlarm(ref copy);
if (copy.Length != 0 && copy[0] != null)
{
VarAlarm = copy[copy.Length - 2].Split(’.’); ;
detectedAlarm = VarAlarm[0] + LTMFDI.alarm_Symptom(VarAlarm[1]);
61
for (int i = 0; i < LTMFDI.abnormality.Length; i++)
{
if (detectedAlarm == LTMFDI.abnormality[i])
{
symptomIndex = i;//index of symptom from alarm info.
break;
}
}
}
else
{
no_ConfirmedAlarm = true;
MessageBox.Show("There is NO ConfirmedAlarm!!!");
}
if (symptomIndex == -1)
{
MessageBox.Show("Alarm Type Error!!!");
}
}
}
if (no_ConfirmedAlarm == false)
{
//*************LTM 出力
if (NRalarmFlag == false)
{
sw2.WriteLine(numberOfSubtask.ToString() + " LTM: Find a symptom from AM-KB: " +
LTMFDI.abnormality[symptomIndex]);
}
else
{
sw2.WriteLine(numberOfSubtask.ToString() +
" LTM: Find a last confirmed symptom from AM-KB: " +LTMFDI.abnormality[symptomIndex]);
}
numberOfSubtask++;
subtaskCount[LTMEMORY]++;
txtOutput += "L-";
//**********
//**********STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//**********
//**********Morter 出力*****
physical.keyPress("shortcut");
sw2.WriteLine(numberOfSubtask.ToString() + " Physical: Switch to Alarm Summary Panel");
numberOfSubtask++;
subtaskCount[PHYSICAL]++;
txtOutput += "M-";
//**********
//****見ている画面を alarmsummary に変更*****
if (panels != hmimodel.userPanels.alarmsummary.ToString())
{
pictureBox1.Image = Image.FromFile
(Share_data.Share_data.exe_Current + @"\Panels\blankalarm.bmp");
this.pictureBox1.Update();
}
panels = hmimodel.userPanels.alarmsummary.ToString();
this.Text = "Evaluation_Tool_for_Alarm_System -Switch to Alarm Summary Panel-";
//************
62
}
//*****M 出力
physical.keyPress("shortcut");
sw2.WriteLine(numberOfSubtask.ToString() + " Physical: KeyPress to eliminate sound and flashing");
numberOfSubtask++;
subtaskCount[PHYSICAL]++;
txtOutput += "M-";
//******
//
//<- lock section1 /
//
//*****ASS の開始*********
sw2.WriteLine("ASS procedure begins");
if (alarmAppear ==false)
{
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
}
while (true)
{
//
/* lock section2-> */
//
if (no_ConfirmedAlarm == true && Ahmimodel.getStackAlarmNum() == 0)
{
Share_data.Share_data.simu_state = Share_data.Share_data.SimulationState.Re_Start;
}
//結果報告以降ならば
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;
}
int nextIndex = 0, posIndex;
int tempSaveFIndex = failureIndex;
bool rejectAll = false;
bool rewind = false;
//
/* <-lock section2 */
//
if (alarmAppear == false)
{
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
}
//*************次に確認する symptom の選択
switch (opmodel_number)
{
case 0: rejectAll = !LTMFDI.ASS1(symptomIndex, STM.confirmedSymptom, ref times,
out failureIndex, out nextIndex, out rewind);
break;
case 1: rejectAll = !LTMFDI.ASS2(symptomIndex, STM.confirmedSymptom, ref times,
out failureIndex, out nextIndex, out rewind);
break;
63
case 2: rejectAll = !LTMFDI.ASS3(symptomIndex, STM.confirmedSymptom, ref times,
out failureIndex, out nextIndex, out rewind);
break;
}
//**************
if (alarmAppear == false)
{
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
}
//****発見されたアラームの処理
if (alarmAppear)
{
//
//lock3->
//
alarmAppear = false;
if (NRalarmFlag == false)
{
for (int i = 0; i < STM.totalAS.Length; i++)
{
int tempP = STM.confirmedSymptom[i].IndexOf(LTMFDI.abnormality[symptomIndex]);
if (tempP < 0)
//has not been confirmed
{
STM.totalAS[i] += LTMFDI.AS[i];
STM.confirmedSymptom[i] += "Alarm: -" + symptomIndex.ToString() +
"-" + LTMFDI.abnormality[symptomIndex] + "& ";
}
}
}
sw.Write(DateTime.Now.ToString() + ", " + numberOfSubtask.ToString() + ", "
+ STM.totalAS[0].ToString() + ", "
+ STM.totalAS[1].ToString() + ", " + STM.totalAS[2].ToString() + ", "
+ STM.totalAS[3].ToString() + ", " + STM.totalAS[4].ToString() + ", "
+ STM.totalAS[5].ToString() + ", " + STM.totalAS[6].ToString() + ", "
+ STM.totalAS[7].ToString() + ", " + STM.totalAS[8].ToString() + ", "
+ STM.totalAS[9].ToString() + ", " + STM.totalAS[10].ToString() +
", with alarm " + Ahmimodel.newAlarm);
sw2.Write("alarm:" + Ahmimodel.newAlarm);
if (haveAppearedflag == true)
{
sw.Write("(haveAppeared)");
sw2.Write("(haveAppeared)");
}
sw.Write("\n");
sw2.Write("\n");
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
if (STM.totalAS[failureIndex] >= Cognition.cogthreshold)
{
Share_data.Share_data.simu_state = Share_data.Share_data.SimulationState.in_Result;
identifiedFlag = true;
break; //Threshold!
}
//
64
//<-lock3
//
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
}//****end if (alarmAppear)
else
{
if (rewind)//For rewind symptom after reject all//その F に関する全ての S を reject
{
output_str = "Rewind " + LTMFDI.failureCause[failureIndex] + "times=" + times.ToString();
sw2.WriteLine(output_str);
sw3.WriteLine(output_str + "\n");
exe_listBox.Items.Add(output_str + "\n");
this.exe_listBox.Refresh();
sw5.WriteLine(output_str);
times = 0;
cognitiveTask.reject();
rewind = false;
}//end if (rewind)
else
{
string candidateFailure;
string newSymptom;
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
if (rejectAll)//全ての ASVal が 0 ならありうる F を変える
{
LTMemory.rejectTime = 0;
sw2.WriteLine("=================================Reconsider
================================");
sw3.WriteLine("=================================Reconsider
================================");
exe_listBox.Items.Add("=================================Reconsider
================================");
sw5.WriteLine("=================================Reconsider
================================");
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >=Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
//****C 出力
sw2.WriteLine(numberOfSubtask.ToString() +
" Cognition: Select another failure cause from FS-KB");
numberOfSubtask++;
subtaskCount[COGNITION]++;
txtOutput += "C-";
//****
65
//新しいアラームがないかチェック Reconsider で何度も調べるのは無駄なので stack 確認のみ
Ahmimodel.new_Alarm_Stack();
//****
//****STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM retrieve");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//****
//新しいアラームがないかチェック Reconsider で何度も調べるのは無駄なので stack 確認のみ
Ahmimodel.new_Alarm_Stack();
//****
//****LTM 出力
output_str = elapsed_time_int + " [s] " + numberOfSubtask.ToString() + " LTM: FS-KB: " +
LTMFDI.failureCause[failureIndex] + ", symptom: " + LTMFDI.abnormality[nextIndex];
sw2.WriteLine(output_str);
sw3.WriteLine(output_str);
elapsed_time = DateTime.Now - currentTime;
elapsed_time_int = (elapsed_time.Hours * 360) + (elapsed_time.Minutes * 60) +
elapsed_time.Seconds;
exe_listBox.Items.Add(output_str + " \n");
sw5.WriteLine(output_str + " \n");
txtOutput += "L-";
numberOfSubtask++;
subtaskCount[LTMEMORY]++;
this.exe_listBox.Refresh();
//****
//for debug
if (LTMFDI.failureCause[failureIndex] == "FUELLEAK" &&
LTMFDI.abnormality[nextIndex] == "P203.PV.LOW")MessageBox.Show("Error!!");
//新しいアラームがないかチェック Reconsider で何度も調べるのは無駄なので stack 確認のみ
Ahmimodel.new_Alarm_Stack();
//****
//****STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//*******
//Reconsider で何度も調べるのは無駄なので stack 確認だけして,
//アラーム画面の更新は 1 秒のためこのブロックの最後で 0.5 秒待つ
Thread.Sleep(500);
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
}//end if (rejectAll)
candidateFailure = LTMFDI.failureCause[failureIndex];
newSymptom = LTMFDI.abnormality[nextIndex];
posIndex = nextIndex / 2;
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
66
break;//break while (true)
}
//****C 出力
sw2.WriteLine(numberOfSubtask.ToString() +
" Cognition: Search possible failure cause and next symptom from FS-KB");
numberOfSubtask++;
subtaskCount[COGNITION]++;
txtOutput += "C-";
//*******
//アラーム画面の更新は 1 秒のため
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******L 出力
elapsed_time = DateTime.Now - currentTime;
elapsed_time_int = (elapsed_time.Hours * 360) + (elapsed_time.Minutes * 60) +
elapsed_time.Seconds;
output_str = elapsed_time_int + " [s] " + numberOfSubtask.ToString() +
" LTM: failure cause in FS-KB: " + LTMFDI.failureCause[failureIndex] +
", symptom: " + newSymptom;
sw2.WriteLine(output_str);
sw3.Write(output_str);
exe_listBox.Items.Add(output_str + "\n");
sw5.WriteLine(output_str);
txtOutput += "L-";
this.exe_listBox.Refresh();
numberOfSubtask++;
subtaskCount[LTMEMORY]++;
//*******
//for debug
if (LTMFDI.failureCause[failureIndex] == "FUELLEAK" &&
LTMFDI.abnormality[nextIndex] == "P203.PV.LOW")MessageBox.Show("Error!!");
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
//****
//*******STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//*******
//*******C 出力
sw2.WriteLine(numberOfSubtask.ToString() +
" Cognition: Search variable information from VI-KB");
numberOfSubtask++;
subtaskCount[COGNITION]++;
txtOutput += "C-";
//*******
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
67
//*****見ているパネルの移動
int position_Row_num = -1;
if (LTMFDI.position[posIndex, 0] != 0)
{
position_Row_num = 0;
if (panels != hmimodel.userPanels.overvieworig.ToString())
{
physical.keyPress("shortcut");
this.Text = "Evaluation_Tool_for_Alarm_System -Switch to Overview Panel-";
pictureBox1.Image = Image.FromFile(Share_data.Share_data.exe_Current +
@"\Panels\overview.bmp");
this.pictureBox1.Update();
panels = hmimodel.userPanels.overvieworig.ToString();
}
}
else if (LTMFDI.position[posIndex, 2] != 0)
{
position_Row_num = 2;
if (panels != hmimodel.userPanels.ACCENGorig.ToString())
{
physical.keyPress("shortcut");
this.Text = "Evaluation_Tool_for_Alarm_System -Switch to ACC Engineering Panel-";
pictureBox1.Image = Image.FromFile(Share_data.Share_data.exe_Current +
@"\Panels\ACCENG.bmp");
this.pictureBox1.Update();
panels = hmimodel.userPanels.ACCENGorig.ToString();
}
}
else if (LTMFDI.position[posIndex, 4] != 0)
{
position_Row_num = 4;
if (panels != hmimodel.userPanels.Burnerorig.ToString())
{
physical.keyPress("shortcut");
this.Text = "Evaluation_Tool_for_Alarm_System -Switch to Fuel Supply Panel-";
pictureBox1.Image = Image.FromFile(Share_data.Share_data.exe_Current +
@"\Panels\burner.bmp");
panels = hmimodel.userPanels.Burnerorig.ToString();
}
}
else if (LTMFDI.position[posIndex, 6] != 0)
{
position_Row_num = 6;
if (panels != hmimodel.userPanels.trendfwc.ToString())
{
physical.keyPress("shortcut");
this.Text = "Evaluation_Tool_for_Alarm_System -Switch to FWC Trend Panel-";
pictureBox1.Image = Image.FromFile(Share_data.Share_data.exe_Current +
@"\Panels\trendfwc.bmp");
this.pictureBox1.Update();
panels = hmimodel.userPanels.trendfwc.ToString();
}
}
if (position_Row_num < 0)
{
MessageBox.Show("position_Row_num < 0!");
}
//********
68
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
//*******LTM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " LTM VI-KB: panel " + panels +
", position (" + LTMFDI.position[posIndex, position_Row_num].ToString() + ", " +
LTMFDI.position[posIndex, (position_Row_num + 1)].ToString() + ")");
numberOfSubtask++;
subtaskCount[LTMEMORY]++;
txtOutput += "L-";
//*******
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//*******
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******現在地点の移動
int lastX = modelEye.Pupil.X;
int lastY = modelEye.Pupil.Y;
modelEye.move2position(LTMFDI.position[posIndex, position_Row_num],
LTMFDI.position[posIndex, (position_Row_num + 1)]);
int nowX = modelEye.Pupil.X;
int nowY = modelEye.Pupil.Y;
totalDistance += Math.Sqrt((double)((lastX - nowX) * (lastX - nowX) + (lastY - nowY) *
(lastY - nowY)));
physical.eyeMove();
//*******
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******M 出力
sw2.WriteLine(numberOfSubtask.ToString() + " Physical: Move fixation point to (" +
LTMFDI.position[posIndex, position_Row_num].ToString() + ", " +
LTMFDI.position[posIndex, (position_Row_num +1)].ToString() + ")");
numberOfSubtask++;
subtaskCount[PHYSICAL]++;
txtOutput += "M-";
//*******
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
69
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//****
//*********Symptom の確認作業
dataItem[] allVar = new dataItem[] { };
allVar = modelEye.visualMemory(panels);
int targetIndex = 0;
//
int visualIndex=10;
for (int i = 0; i < allVar.Length; i++)
{
int tempIndex = newSymptom.LastIndexOf(".");
//tempStr に P204.PV(.LOW<-ここを削除) のようなタグ名を代入
string tempStr = newSymptom.Substring(0, tempIndex);
if (allVar[i].readOnlyName == newSymptom.Substring(0, tempIndex))
{
targetIndex = i;
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >=
Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******P 出力
sw2.WriteLine(numberOfSubtask.ToString() + " Perception: Detect the variable "
+ tempStr);
numberOfSubtask++;
subtaskCount[PERCEPT]++;
txtOutput += "P-";
//*******P
//新しいアラームがないかチェック. 戻ってくるのは終了後のみ探索終了後のための処理を行う
Ahmimodel.checkAlarm();
if (Share_data.Share_data.simu_state >=
Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
//*******STM 出力
sw2.WriteLine(numberOfSubtask.ToString() + " STM stores ");
numberOfSubtask++;
subtaskCount[STMEMORY]++;
txtOutput += "S-";
//*******
break;
}
else if (i == allVar.Length - 1)
{
MessageBox.Show("Error: newsymptom=" + tempStr);
}
}//end if (allVar[i].readOnlyName == newSymptom.Substring(0, tempIndex))
//
//lock4->
//
bool confirmSuc = false;
if (nextIndex > posIndex * 2)//Low 側の判定
{
Type testType = allVar[targetIndex].dataValue.GetType();
if (testType == Type.GetType("System.Double"))
{
70
confirmSuc=(double)allVar[targetIndex].dataValue<LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.Single"))
{
confirmSuc=(float)allVar[targetIndex].dataValue<LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.Int32"))
{
confirmSuc=(int)allVar[targetIndex].dataValue<LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.String"))//データがなかったら
{
if ((string)allVar[targetIndex].dataValue == "non")
{
confirmSuc = false;
}
}
}
else if (nextIndex == posIndex * 2)//High 側の判定
{
Type testType = allVar[targetIndex].dataValue.GetType();
if (testType == Type.GetType("System.Double"))
{
confirmSuc=(double)allVar[targetIndex].dataValue>LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.Single"))
{
confirmSuc=(float)allVar[targetIndex].dataValue>LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.Int32"))
{
confirmSuc=(int)allVar[targetIndex].dataValue>LTMFDI.abnormalValues[nextIndex];
}
else if (testType == Type.GetType("System.String"))//データがなかったら
{
if ((string)allVar[targetIndex].dataValue == "non")
{
confirmSuc = false;
}
}
}
sw2.WriteLine("///Compare " + allVar[targetIndex].dataValue.ToString() + " with " +
LTMFDI.abnormalValues[nextIndex].ToString());
//
//<-lock4
//
if (confirmSuc)
{
//
//lock5->
//
STM.totalAS[failureIndex] += LTMFDI.symptomAS[nextIndex];//.AS [failureIndex];
//****C 出力
sw2.WriteLine("///failure is " + failureIndex.ToString() +
". success order is " + times.ToString());
sw2.WriteLine(numberOfSubtask.ToString() + " Cognition: Confirmation succeeds,
total AS: "+ STM.totalAS[failureIndex].ToString());
sw3.WriteLine("○" + " total AS: " + STM.totalAS[failureIndex].ToString());
output_str = "○" + " total AS: " + STM.totalAS[failureIndex].ToString();
exe_listBox.Items.Add(output_str);
sw5.WriteLine(output_str);
numberOfSubtask++;
subtaskCount[COGNITION]++;
71
txtOutput += "C-";
this.exe_listBox.Refresh();
//********
successTime++;
successJudge[failureIndex]++;
STM.confirmedSymptom[failureIndex] += times.ToString() + "-" + nextIndex.ToString() +
"-" + newSymptom + "& ";
times++;//no repeat successful check
sw.WriteLine(DateTime.Now.ToString() + ", " + numberOfSubtask.ToString() +
", " + STM.totalAS[0].ToString() + ", "
+ STM.totalAS[1].ToString() + ", " + STM.totalAS[2].ToString() + ", "
+ STM.totalAS[3].ToString() + ", " + STM.totalAS[4].ToString() + ", "
+ STM.totalAS[5].ToString() + ", " + STM.totalAS[6].ToString() + ", "
+ STM.totalAS[7].ToString() + ", " + STM.totalAS[8].ToString() + ", "
+ STM.totalAS[9].ToString() + ", " + STM.totalAS[10].ToString() + ", for "
+ LTMFDI.failureCause[failureIndex] + "-" + LTMFDI.abnormality[nextIndex]);
//
//<-lock5
//
}
else
{
//
//lock6->
//
string oldFailure = LTMFDI.failureCause[failureIndex];
int tempP = STM.failSymptom[failureIndex].IndexOf(newSymptom);
if (tempP < 0)
//first time to check the symptom and fail
{
STM.failSymptom[failureIndex] += newSymptom;
cognitiveTask.reject(); //NOT BE USED!!
LTMFDI.rejectIndex[failureIndex] = 0;
//****C 出力
sw2.WriteLine("///failure is " + failureIndex.ToString() +
". fail order is " + times.ToString());
sw2.WriteLine(numberOfSubtask.ToString() + " Cognition: Confirmation fails,
temporarily reject " + oldFailure);
sw3.WriteLine("× reject " + oldFailure + "\n");
output_str = "× reject " + oldFailure + "\n";
exe_listBox.Items.Add(output_str);
sw5.WriteLine(output_str);
txtOutput += "C-";
this.exe_listBox.Refresh();
numberOfSubtask++;
subtaskCount[COGNITION]++;
failTime++;
failJudge[failureIndex]++;
//****
times = 0;
}
else
{
//****C 出力
sw2.WriteLine("///failure is " + failureIndex.ToString() +
". fail order is " + times.ToString());
times++;
sw2.WriteLine(numberOfSubtask.ToString() + " Cognition: Confirmation fails,
but continue to next symptom of "+ oldFailure);
sw3.WriteLine("× , but continue" + oldFailure);
output_str = "× , but continue" + oldFailure;
exe_listBox.Items.Add(output_str);
sw5.WriteLine(output_str);
txtOutput += "C-";
this.exe_listBox.Refresh();
numberOfSubtask++;
72
subtaskCount[COGNITION]++;
failTime++;
failJudge[failureIndex]++;
//*******
}
//
//<-lock6
//
}//end if (confirmSuc)else
//}//if (rejectAll != true)
}//end if (rewind)
}//****end if (alarmAppear) else
//}// end if(no_ConfirmedAlarm == true)
if (numberOfSubtask > taskloop_num)//サブタスクオーバー
{
Share_data.Share_data.simu_state = Share_data.Share_data.SimulationState.in_Result;
Share_data.Share_data.nots_reason = Share_data.Share_data.NotIdentifiedReason.task_over;
break;//break while (true)
}
if (STM.totalAS[failureIndex] >= Cognition.cogthreshold)//同定
{
Share_data.Share_data.simu_state = Share_data.Share_data.SimulationState.in_Result;
identifiedFlag = true;
break;//break while (true)
}
if (Ahmimodel.getStackAlarmNum() == 0)//たまっているアラームがない
{
Ahmimodel.checkAlarm();//新しいアラームがないかチェックし, なければ現在の続きをする
//探索終了以降ならば
if (Share_data.Share_data.simu_state >= Share_data.Share_data.SimulationState.in_Result)
{
break;//break while (true)
}
if (no_ConfirmedAlarm == true)
{
sw2.WriteLine("There is no ConfirmedAlar.\nWait 1 Second.");
sw3.WriteLine("There is no ConfirmedAlar.\nWait 1 Second.");
exe_listBox.Items.Add("There is no ConfirmedAlar.\nWait 1 Second.");
sw5.WriteLine("There is no ConfirmedAlar.\nWait 1 Second.");
Thread.Sleep(1000);
}
}
else if (Ahmimodel.getStackAlarmNum() > 0)//たまっているアラームがある
{
Ahmimodel.new_Alarm_Stack();//新しいアラームをチェックし, ためる
//たまっているアラームを処理するためにこの関数を出て同時に出ていた次のアラームへ
break;//break while (true)
}
else
{
MessageBox.Show("StackAlarmNum<0!");
}
}//end while (true)
//********ASS の終了**********************
if (Share_data.Share_data.simu_state ==
Share_data.Share_data.SimulationState.in_Result)//結果報告中ならば
{
if (identifiedFlag == true)
{
Ahmimodel.refresh1S_endRefresh();
//Ahmimodel_AlarmOccur のイベントの無効化
Ahmimodel.AlarmOccur -= new AlarmEventHandler(Ahmimodel_AlarmOccur);
73
sw2.WriteLine("=======================================END=======================================");
sw3.WriteLine("=======================================END=======================================");
exe_listBox.Items.Add("=======================================END
=======================================");
sw5.WriteLine("=======================================END=======================================");
DateTime endTime = DateTime.Now;
this.Refresh();
TimeSpan FDIperiod = endTime - currentTime;
txtChunk5 = FDIperiod.TotalSeconds.ToString() + " S";
txtChunk6 = (double.Parse(txtChunk3.Split(’ ’)[0]) +FDIperiod.TotalSeconds).ToString() + " S";
sw2.WriteLine("Mal starts: " + txtChunk1 + ", Earliest alarm: " + txtChunk2 +
", Appearance after: " + txtChunk3
+ ", FDI ends at: " + txtChunk4 + ", Elapsed time for FDI: " + txtChunk5);
sw2.WriteLine("Failure cause " + LTMFDI.failureCause[failureIndex] + " is identified!");
sw.WriteLine("Failure cause " + LTMFDI.failureCause[failureIndex] + " is identified!");
sw.WriteLine("Total elapsed time : " + txtChunk6);
sw.WriteLine("Alarm Appears after: " + txtChunk3);
sw.WriteLine("Elapsed time for FDI process: " + txtChunk5);
sw.WriteLine("Number of operational stage: " +
(subtaskCount[COGNITION] + alarmCount).ToString());
sw2.WriteLine("Number of alarms: " + alarmCount.ToString());
sw.WriteLine("Number of alarms: " + alarmCount.ToString());
txtChunk2 = alarmCount.ToString() + " alarms";
sw2.WriteLine("There are totally " + numberOfSubtask.ToString() + " subtasks including "
+ successTime.ToString() + " successful confirmation and "
+ failTime.ToString() + " failed confirmation");
sw2.WriteLine("Detailedly, these subtasks contains: ");
sw2.WriteLine("Perception subtasks " + subtaskCount[PERCEPT].ToString());
sw2.WriteLine("Cognition subtasks " + subtaskCount[COGNITION].ToString());
txtChunk1 = (subtaskCount[COGNITION] + alarmCount).ToString() + " operational stages";
sw2.WriteLine("Physical subtasks " + subtaskCount[PHYSICAL].ToString());
sw2.WriteLine("Short-term memory subtasks " + subtaskCount[STMEMORY].ToString());
sw2.WriteLine("Long-term memory subtasks " + subtaskCount[LTMEMORY].ToString());
double diagonalD = totalDistance / 1639.1998;//1280X1024
double moveLength = diagonalD * 50;
txtChunk4 = moveLength.ToString() + " cm";
sw2.WriteLine("Total length of eye movement: " + moveLength.ToString() + "cm");
sw.WriteLine("Total length of eye movement: " + moveLength.ToString() + " cm");
sw2.WriteLine("All failure causes are: FOP1FAIL, BURNER EXTINGUISH, BFP1TRIP,
WATERTUBELEAK, O2ANALYZERFAIL, " + "FDFCAPACITYDOWN, IDFTRIP,
TURBINETRIP, OILHEAREFAIL, P204SENSOR, FUELLEAK");
sw2.WriteLine("Success judgement times: {" + successJudge[0].ToString() + ", "
+ successJudge[1].ToString() + ", " + successJudge[2].ToString() + ", "
+ successJudge[3].ToString() + ", " + successJudge[4].ToString() + ", "
+ successJudge[5].ToString() + ", " + successJudge[6].ToString() + ", "
+ successJudge[7].ToString() + ", " + successJudge[8].ToString() + ", "
+ successJudge[9].ToString() + ", " + successJudge[10].ToString() + "}");
sw2.WriteLine("Fail judgement times: {" + failJudge[0].ToString() + ", "
+ failJudge[1].ToString() + ", " + failJudge[2].ToString() + ", "
74
+
+
+
+
failJudge[3].ToString()
failJudge[5].ToString()
failJudge[7].ToString()
failJudge[9].ToString()
+
+
+
+
",
",
",
",
"
"
"
"
+
+
+
+
failJudge[4].ToString() + ", "
failJudge[6].ToString() + ", "
failJudge[8].ToString() + ", "
failJudge[10].ToString() + "}");
sw2.WriteLine("Confirmed Variables: {" +
+ STM.confirmedSymptom[1].ToString()
+ STM.confirmedSymptom[3].ToString()
+ STM.confirmedSymptom[5].ToString()
+ STM.confirmedSymptom[7].ToString()
+ STM.confirmedSymptom[9].ToString()
STM.confirmedSymptom[0].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[2].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[4].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[6].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[8].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[10].ToString() + "}");
sw2.WriteLine("successTime: " + this.successTime);
sw.WriteLine("successTime: " + this.successTime);
sw2.WriteLine("failTime: " + this.failTime);
sw.WriteLine("failTime: " + this.failTime);
sw2.WriteLine("FDI track: " + txtOutput);
sw.WriteLine("FDI track: " + txtOutput);
if (sw != null) sw.Close();
if (sw2 != null) sw2.Close();
if (sw3 != null) sw3.Close();//add20070712
if (sw5 != null) sw5.Close();
File.Copy(
Share_data.Share_data.get_config_txt_path(), Share_data.Share_data.get_result_folder() + "\\"
+ Share_data.Share_data.Only_FileName(Share_data.Share_data.get_config_txt_path()), false);
File.Copy(
Share_data.Share_data.get_Alarm_config_path(), Share_data.Share_data.get_result_folder()+"\\"
+ Share_data.Share_data.Only_FileName(Share_data.Share_data.get_Alarm_config_path()), false);
File.Copy(Share_data.Share_data.get_TopW_congfig_csv_path(),
Share_data.Share_data.get_result_folder()+"\\"+Share_data.Share_data.Only_FileName(
Share_data.Share_data.get_TopW_congfig_csv_path()),false);
MessageBox.Show(LTMFDI.failureCause[failureIndex] + " is identified!");
}//end if (identifiedFlag == true)
else
{
Ahmimodel.refresh1S_endRefresh();
//Ahmimodel_AlarmOccur のイベントの無効化
Ahmimodel.AlarmOccur -= new AlarmEventHandler(Ahmimodel_AlarmOccur);
string reason_str = "";
switch (Share_data.Share_data.nots_reason)
{
case Share_data.Share_data.NotIdentifiedReason.task_over:
reason_str = taskloop_num + " task OVER \n is not identified!";
break;
}
sw.WriteLine(reason_str);
sw2.WriteLine("=======================================END=======================================");
sw2.WriteLine(reason_str);
sw3.WriteLine("=======================================END=======================================");
sw3.WriteLine(reason_str);
exe_listBox.Items.Add("=======================================END
=======================================");
exe_listBox.Items.Add(reason_str);
sw5.WriteLine("=======================================END=======================================");
sw5.WriteLine(reason_str);
sw.WriteLine("Number of operational stage: " +
(subtaskCount[COGNITION] + alarmCount).ToString());
sw2.WriteLine("Number of alarms: " + alarmCount.ToString());
sw.WriteLine("Number of alarms: " + alarmCount.ToString());
txtChunk2 = alarmCount.ToString() + " alarms";
sw2.WriteLine("There are totally " + numberOfSubtask.ToString() + " subtasks including "
+ successTime.ToString() + " successful confirmation and "
75
+ failTime.ToString() + " failed confirmation");
sw2.WriteLine("Detailedly, these subtasks contains: ");
sw2.WriteLine("Perception subtasks " + subtaskCount[PERCEPT].ToString());
sw2.WriteLine("Cognition subtasks " + subtaskCount[COGNITION].ToString());
txtChunk1 = (subtaskCount[COGNITION] + alarmCount).ToString() + " operational stages";
sw2.WriteLine("Physical subtasks " + subtaskCount[PHYSICAL].ToString());
sw2.WriteLine("Short-term memory subtasks " + subtaskCount[STMEMORY].ToString());
sw2.WriteLine("Long-term memory subtasks " + subtaskCount[LTMEMORY].ToString());
double diagonalD = totalDistance / 1639.1998;//1280X1024
double moveLength = diagonalD * 50;
txtChunk4 = moveLength.ToString() + " cm";
sw2.WriteLine("Total length of eye movement: " + moveLength.ToString() + "cm");
sw.WriteLine("Total length of eye movement: " + moveLength.ToString() + " cm");
sw2.WriteLine("All failure causes are: FOP1FAIL, BURNER EXTINGUISH, BFP1TRIP,
WATERTUBELEAK, O2ANALYZERFAIL, " + "FDFCAPACITYDOWN, IDFTRIP, TURBINETRIP,
OILHEAREFAIL, P204SENSOR, FUELLEAK");
sw2.WriteLine("Success judgement times: {" + successJudge[0].ToString() + ", "
+ successJudge[1].ToString() + ", " + successJudge[2].ToString() + ", "
+ successJudge[3].ToString() + ", " + successJudge[4].ToString() + ", "
+ successJudge[5].ToString() + ", " + successJudge[6].ToString() + ", "
+ successJudge[7].ToString() + ", " + successJudge[8].ToString() + ", "
+ successJudge[9].ToString() + ", " + successJudge[10].ToString() + "}");
sw2.WriteLine("Fail judgement
+ failJudge[1].ToString()
+ failJudge[3].ToString()
+ failJudge[5].ToString()
+ failJudge[7].ToString()
+ failJudge[9].ToString()
times:
+ ", "
+ ", "
+ ", "
+ ", "
+ ", "
{" + failJudge[0].ToString() + ", "
+ failJudge[2].ToString() + ", "
+ failJudge[4].ToString() + ", "
+ failJudge[6].ToString() + ", "
+ failJudge[8].ToString() + ", "
+ failJudge[10].ToString() + "}");
sw2.WriteLine("Confirmed Variables: {" +
+ STM.confirmedSymptom[1].ToString()
+ STM.confirmedSymptom[3].ToString()
+ STM.confirmedSymptom[5].ToString()
+ STM.confirmedSymptom[7].ToString()
+ STM.confirmedSymptom[9].ToString()
STM.confirmedSymptom[0].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[2].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[4].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[6].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[8].ToString() + ":: "
+ ":: " + STM.confirmedSymptom[10].ToString() + "}");
sw2.WriteLine("successTime: " + this.successTime);
sw.WriteLine("successTime: " + this.successTime);
sw2.WriteLine("failTime: " + this.failTime);
sw.WriteLine("failTime: " + this.failTime);
if (sw != null) sw.Close();
if (sw2 != null) sw2.Close();
if (sw3 != null) sw3.Close();
if (sw5 != null) sw5.Close();
File.Copy(
Share_data.Share_data.get_config_txt_path(), Share_data.Share_data.get_result_folder() +"\\"
+Share_data.Share_data.Only_FileName(Share_data.Share_data.get_config_txt_path()), false);
File.Copy(Share_data.Share_data.get_Alarm_config_path(),
Share_data.Share_data.get_result_folder() + "\\" + Share_data.Share_data.Only_FileName(
Share_data.Share_data.get_Alarm_config_path()), false);
File.Copy(Share_data.Share_data.get_TopW_congfig_csv_path(),
Share_data.Share_data.get_result_folder() + "\\" + Share_data.Share_data.Only_FileName(
Share_data.Share_data.get_TopW_congfig_csv_path()), false);
MessageBox.Show(reason_str);
}//end if (identifiedFlag == true)else
76
Refresh_TopWindow_Disp(true);
this.Refresh();
Thread.Sleep(1000);
}//end if if (Share_data.Share_data.simu_state == Share_data.Share_data.SimulationState.in_Result)
}//end try
catch (Exception ee)
{
this.Refresh();
}
//結果報告中ならば
if (Share_data.Share_data.simu_state == Share_data.Share_data.SimulationState.in_Result)
{
Share_data.Share_data.simu_state = Share_data.Share_data.SimulationState.Ending;
this.simu_state_toolStripStatusLabel.Text = "終了中";
end_clearAll();
}
}
}
77
Fly UP