![](https://static.wixstatic.com/media/ea798a_4526880ee36140f188b23e1d38793312~mv2.jpg/v1/fill/w_1920,h_1080,al_c,q_90,enc_avif,quality_auto/ea798a_4526880ee36140f188b23e1d38793312~mv2.jpg)
大型クレーンを作る!
クレーンは、作業場の壁に掛かるレール上を南北方向に移動するクレーン本体と、その本体上を東西方向に移動するトロリのふたつの部分からなります。これら 2 つの部分は独立した Ship として扱われ、作業場のプログラマブルブロックから、壁面に設置したレーザーアンテナを介して、それぞれの Ship のプログラマブルブロックにコマンドを送信して制御します。クレーン全体として、合計 3 つあるプログラマブルブロック中のプログラムは以下の通りです。
コマンド送信プログラム(作業場プログラマブルブロック)
1| public void Main(string argument, UpdateType updateSource)
2| {
3| var ant1 = GridTerminalSystem.GetBlockWithName("LA Workshop 1") as IMyLaserAntenna;
4| var ant2 = GridTerminalSystem.GetBlockWithName("LA Workshop 2") as IMyLaserAntenna;
5|
6| if (argument == "N" || argument == "S" || argument == "Crane_Stop")
7| ant1.TransmitMessage(argument);
8| else
9| ant2.TransmitMessage(argument);
10| }
ふたつのレーザーアンテナは、それぞれクレーン本体とトロリに接続されており、コマンドによってどちらにメッセージを送信するかを決めています。
クレーン本体プログラム
1| IMySensorBlock n_sensor;
2| IMySensorBlock s_sensor;
3| List<IMyMotorAdvancedStator> r_wheels = new List<IMyMotorAdvancedStator>();
4| List<IMyMotorAdvancedStator> l_wheels = new List<IMyMotorAdvancedStator>();
5|
6| public Program()
7| {
8| n_sensor = GridTerminalSystem.GetBlockWithName("Sensor N direction") as IMySensorBlock;
9| s_sensor = GridTerminalSystem.GetBlockWithName("Sensor S direction") as IMySensorBlock;
10| IMyBlockGroup r_wheels_group = GridTerminalSystem.GetBlockGroupWithName("Crane Wheels Right");
11| IMyBlockGroup l_wheels_group = GridTerminalSystem.GetBlockGroupWithName("Crane Wheels Left");
12| r_wheels_group.GetBlocksOfType(r_wheels);
13| l_wheels_group.GetBlocksOfType(l_wheels);
14| }
15|
16| public void Main(string argument, UpdateType updateSource)
17| {
18| var com = argument.Split(',');
19| string move ="";
20|
21| switch (com[0]){
22| case "N":
23| move = CheckWall("N") == true ? "N" : "Stop";
24| break;
25| case "S":
26| move = CheckWall("S") == true ? "S" : "Stop";
27| break;
28| case "Crane_Stop":
29| move = "Stop";
30| break;
31| case "CollisionAlert":
32| move = "Stop";
33| break;
34| }
35|
36| MoveCrane(move);
37| }
38|
39| private bool CheckWall(string direction)
40| {
41| MyDetectedEntityInfo n_entity = n_sensor.LastDetectedEntity;
42| MyDetectedEntityInfo s_entity = s_sensor.LastDetectedEntity;
43| bool result;
44|
45| if (direction == "N")
46| result = n_entity.Type == MyDetectedEntityType.LargeGrid ? false : true;
47| else
48| result = s_entity.Type == MyDetectedEntityType.LargeGrid ? false : true;
49|
50| return result;
51| }
52|
53| private void MoveCrane(string direction)
54| {
55| float vel = 0f;
56|
57| if (direction == "Stop")
58| vel = 0f;
59| else if (direction == "N")
60| vel = -10f;
61| else if (direction == "S")
62| vel = 10f;
63|
64| foreach(var wheel in r_wheels)
65| wheel.TargetVelocityRPM = vel;
66| foreach(var wheel in l_wheels)
67| wheel.TargetVelocityRPM = -vel;
68| }
クレーン本体とトロリには、これらが移動中に可動範囲を超えて衝突するのを防ぐため、壁面への接近を感知するセンサーブロックを設置してあります。 このセンサーブロックは、壁面を感知した時に
文字列 "CollisionAlert" を引数として main() を呼ぶようにセンサーブロックのアクションに設定してあります。
トロリプログラム
1| IMyLandingGear head;
2| List<IMyTerminalBlock> r_wheels = new List<IMyTerminalBlock>();
3| List<IMyTerminalBlock> l_wheels = new List<IMyTerminalBlock>();
4| IMySensorBlock e_sensor;
5| IMySensorBlock w_sensor;
6| List<IMyPistonBase> pistons = new List<IMyPistonBase>();
7|
8| public Program()
9| {
10| head = GridTerminalSystem.GetBlockWithName("Head") as IMyLandingGear;
11| var r_wheels_group = GridTerminalSystem.GetBlockGroupWithName("Slider Wheels Right");
12| var l_wheels_group = GridTerminalSystem.GetBlockGroupWithName("Slider Wheels Left");
13| r_wheels_group.GetBlocks(r_wheels);
14| l_wheels_group.GetBlocks(l_wheels);
15| e_sensor = GridTerminalSystem.GetBlockWithName("Sensor E direction") as IMySensorBlock;
16| w_sensor = GridTerminalSystem.GetBlockWithName("Sensor W direction") as IMySensorBlock;
17| GridTerminalSystem.GetBlocksOfType(pistons);
18| }
19|
20| public void Main(string argument, UpdateType updateSource)
21| {
22| var com = argument.Split(',');
23|
24| switch (com[0]){
25| case "E":
26| if (CheckWall("E") == true)
27| MoveCrane("E");
28| else
29| MoveCrane("Stop");
30| break;
31| case "W":
32| if (CheckWall("W") == true)
33| MoveCrane("W");
34| else
35| MoveCrane("Stop");
36| break;
37| case "S_Stop":
38| MoveCrane("Stop");
39| break;
40| case "Down":
41| OperateHead("Down");
42| break;
43| case "Up":
44| OperateHead("Up");
45| break;
46| case "Stop_Head":
47| OperateHead("Stop");
48| break;
49| case "Unlock":
50| OperateHead("Unlock");
51| break;
52| case "CollisionAlert":
53| MoveCrane("Stop");
54| break;
55| }
56| }
57|
58|
59| private void OperateHead(string com)
60| {
61| float vel = 0f;
62|
63| if (com == "Unlock")
64| head.ApplyAction("Unlock");
65| else if (com == "Down")
66| vel = 0.5f;
67| else if (com == "Up")
68| vel = -0.5f;
69| else if (com == "Stop")
70| vel = 0f;
71|
72| foreach (var piston in pistons)
73| piston.Velocity = vel;
74| }
75|
76| private bool CheckWall(string direction)
77| {
78| MyDetectedEntityInfo e_entity = e_sensor.LastDetectedEntity;
79| MyDetectedEntityInfo w_entity = w_sensor.LastDetectedEntity;
80| bool result;
81|
82| if (direction == "E")
83| result = e_entity.Type == MyDetectedEntityType.LargeGrid ? false : true;
84| else
85| result = w_entity.Type == MyDetectedEntityType.LargeGrid ? false : true;
86|
87| return result;
88| }
89|
90| private void MoveCrane(string direction)
91| {
92| float vel = 0f;
93|
94| if (direction == "Stop")
95| vel = 0f;
96| else if (direction == "E")
97| vel = -10f;
98| else if (direction == "W")
99| vel = 10f;
100|
101| foreach(IMyMotorAdvancedStator wheel in r_wheels)
102| wheel.TargetVelocityRPM = vel;
103| foreach(IMyMotorAdvancedStator wheel in l_wheels)
104| wheel.TargetVelocityRPM = -vel;
105| }