曾经帮航天部的一个哥们编过一个小程序,很简单也很有趣,大家放松一下。
问题的提出:
假设一只正在休息的瞎狗被一只晕头晕脑的兔子弄醒了,此时兔子开始向某个不确定的方向狂奔逃窜,瞎狗开始追赶。
1. 对于瞎狗并不知道兔子逃跑的方向和路线,假设兔子直线逃窜,那么瞎狗应该以什么样的追击路线追击兔子呢?(假设只要瞎狗在后来的奔跑过程中碰到兔子就认为是捉到兔子)
2. 假设瞎狗以阿基米德曲线追击,那么它的奔跑速度最小是多少,才能保证在自己奔跑一圈以后,无论兔子采取什么策略,都会被包含在以起点与狗当前所在位置距离Rx为半径的圆里面呢?
3. 假设兔子很狡猾,在奔跑途中发现追击自己的原来是一只瞎狗从而改变了策略,站立不动,瞎狗岂不是越跑越远 ?
4. 假设在瞎狗奔跑过程中不断狂吠,虽然尽了力,但还是没有抓到兔子,但它的叫声引来一只目光能够看2* Rx的狗,哈哈,那就等着瞧吧,兔子。
问题的解决:
假设瞎狗以阿基米德曲线追击,即参数方程为r=ro+aθ,其中r为极径,ro为初始极径,θ=w*t,θ为极角=角速度*时间,而a为常数.
FC1 程序说明,程序仅画出一个直角坐标系阿基米德曲线痕迹,存在DB1 中,如果再增加转换程序,在触摸屏上可以显示出来。
X0 瞎狗直角坐标系X轴原始位置
Y0 瞎狗直角坐标系Y轴原始位置
A0 瞎狗直线速度
W0 瞎狗角速度
此程序比较简单,也不太实用,我对于为何使用PLC也有所疑惑,但那个哥们说:“肯定不是用在航天上,而且我仅仅是想看看西门子的编程格式”。当然此程序不是我所提交的最终程序,那份程序肯定是不敢程序公开的。
调试通过的源程序:
FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
X0 : REAL ;
Y0 : REAL ;
A0 : REAL ;
W0 : REAL ;
DB_DATA : BLOCK_DB ;
END_VAR
VAR_TEMP
loopcounter : INT ;
Address_pointer : DWORD ;
R1 : REAL ;
W1 : REAL ;
END_VAR
BEGIN
NETWORK
TITLE =
OPN #DB_DATA;
NETWORK
TITLE =
//radian
//
L 0;
T #loopcounter;
L P#DBX 0.0;
LAR1 ;
LP: NOP 0;
L #loopcounter;
L 64;
*I ;
T #Address_pointer;
LAR1 ;
L #loopcounter;
ITD ;
DTR ;
L #W0;
*R ;
L 3.600000e+002; //convert from angle to radian
/R ;
L 3.141593e+000;
*R ;
L 2.000000e+000;
*R ;
T #W1;
L #A0;
*R ;
T #R1;
L #W1;
COS ;
L #R1;
*R ;
L #X0;
+R ;
T DBD [AR1,P#0.0];
L #W1;
SIN ;
L #R1;
*R ;
L #Y0;
+R ;
T DBD [AR1,P#4.0];
L #loopcounter;
L 1;
+I ;
T #loopcounter;
L 361;
>=I ;
JCN LP;
END_FUNCTION
ORGANIZATION_BLOCK OB 1
TITLE = "Main Program Sweep (Cycle)"
VERSION : 0.1
VAR_TEMP
OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
OB1_PRIORITY : BYTE ; //Priority of OB Execution
OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
OB1_RESERVED_1 : BYTE ; //Reserved for system
OB1_RESERVED_2 : BYTE ; //Reserved for system
OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
CALL FC 1 (
X0 := 1.000000e+000,
Y0 := 2.000000e+000,
A0 := 1.000000e+000,
W0 := 1.000000e+000,
DB_DATA := DB 1);
END_ORGANIZATION_BLOCK