Lock ON и железная кабина. — «Железные» кокпиты

Возникла необходимость (по убедительной просьбе любимого племянника) подключить к военному симулятору Lock On ГС-2 существующую железную кабину, которая работает под МФС.
Что оказалось для меня совсем не простой задачей. Тем более, что программа управления кабиной должна находиться на другом компьютере. Но надеюсь с помощью коллег по симулятору эту проблему решить.

Как известно работа с этой программой обеспечивается за счет взаимодействия по протоколу TCP.
Механизм работы примерно следующий :  программа связи симулятора со внешними устройствами создает TCP «сервер» (ведущий процесс) , который ( упрощенно ) является  областью в памяти компьютера .
Эту область программа связи симулятора с внешними устройствами постоянно прослушивает. В свою очередь  ЛокОн создает «клиент» ( то есть ведомый процесс  ) который  постоянно передает в эту область данные. Увидев наличие данных  программа связи должна считать их, и преобразовав выдать во внешние устройства.  Лок Он при запуске анализирует, создан ли сервер. Если сервер не создан, то Лок Он не будет передавать данные. Таким образом, для  корректной работы необходимо СНАЧАЛА запустить программу связи (сервер), и только после этого ЛокОн.
По совету Андрея (Lisa) попробуем применить такую схему:
Lock On => Lua => TCP/IP => Sioc => клиент => приборы.
SIOC используется исключительно как сервер на который Lock On посылает данные.
Для того , чтобы ЛокОн начал работать с созданным сервером необходимо :
— объяснить программе, что она должна работать по TCP.
— указать программе область памяти ( или сетевой адрес ) в который ей необходимо передавать данные.
— указать программе объем данных ( параметры  ), который необходимо передавать .

Ответов: 47

После настройки программы:
— сформировав сервер дождаться начала обмена данными .

Эта последовательность действий обеспечивается следующим образом.
1. В  файле  …1CEagle DinamicsLOConfigExportConfig.lua
найти строку EnableExportScript = false  ( в принципе она одна там и есть )…
и исправить её так :EnableExportScript = true
Этим мы дадим знать ЛокОн что ему необходимо начать работать на передачу (экспорт)
данных.
2. Заменитьфайл …1CEagle DinamicsLOConfigExportExport.lua
на одноименный файл , ( то есть с нашими данными )
Желательно старый файл не удалять а переименовать (на всякий случай ).

В этом файле находятся :
— настройки TCP ( номер порта и номер хоста )
— ————————————————————
—процедурыоткрытияпорта
functionLuaExportStart()  
package.path  =package.path..»;.\LuaSocket\?.lua»  
package.cpath =package.cpath..»;.\LuaSocket\?.dll»  

socket =require(«socket»)  
host =»192.168.10.190″—сетевойадресSIOC
port =8092– порт SIOC
c = socket.try(socket.connect(host, port))  
c:setoption(«tcp-nodelay»,true)  
c:settimeout(.01)  
end
————————————————————————————
—значения»host»и»port»поумолчаниюдляSIOC
host – сетевой адрес компьютера на котором установлен сервер.

Запускаем SIOC сервер, затем LockOn, выбираем миссию. Компьютеры связаны по локальной сети.
В строчке «Clientsconnecteds» должны увидеть, сколько клиентов подключены. Если соединение получилось уже хорошо.

Прикрепленные изображения

  • Sioc.JPG

Сообщение отредактировал ra3dcs: 08 September 2012 — 14:44

Теперь дальше получаемые данные полета.
— эта функция выполняется после отрисовки каждого кадра
function LuaExportAfterNextFrame()
local lSIOC_SendString = «»
local TAS = LoGetTrueAirSpeed()* 3.6 — получаем значение истинной скорости
local IAS = LoGetIndicatedAirSpeed()* 3.6 — получаем значение прибрной скорости  
local AOA = LoGetAngleOfAttack() — угол атаки
local Gp  = LoGetAccelerationUnits() — перегрузка
local VV  = LoGetVerticalVelocity()   — вертскорость
local altBar = LoGetAltitudeAboveSeaLevel()
local altRad = LoGetAltitudeAboveGroundLevel()
local pitch, bank, yaw = LoGetADIPitchBankYaw()
local Mach = LoGetMachNumber()

local HSI = LoGetControlPanel_HSI()
local engine = LoGetEngineInfo()

local route = LoGetRoute()

local PlaneID = LoGetPlayerPlaneId()
local obj = LoGetObjectById(PlaneID)

local myXCoord, myZCoord = getXYCoords(obj.LatLongAlt.Lat, obj.LatLongAlt.Long)

local navi = LoGetNavigationInfo()
R0 = TAS
R1 = IAS
R2 = AOA*ToDegree
R3 = Gp.y
R4 = VV
R5 = altBar
R6 = altRad

— округляем значение до целого
R0 = math.floor(R0 + 0.5)
R1 = math.floor(R1 + 0.5)
R2 = math.floor(R2 + 0.5)
R3 = math.floor(R3 + 0.5)
R4 = math.floor(R4 + 0.5)
R5 = math.floor(R5 + 0.5)
R6 = math.floor(R6 + 0.5)

— формируем строчку номер переменной = значение
R0 = «0=»..R0..»:»
R1 = «1=»..R1..»:»
R2 = «2=»..R2..»:»
R3 = «3=»..R3..»:»
R4 = «4=»..R4..»:»
R5 = «5=»..R5..»:»
R6 = «6=»..R6..»:»
— записываемстрочку
lSIOC_SendString = lSIOC_SendString..R0
lSIOC_SendString = lSIOC_SendString..R1
lSIOC_SendString = lSIOC_SendString..R2
lSIOC_SendString = lSIOC_SendString..R3
lSIOC_SendString = lSIOC_SendString..R4
lSIOC_SendString = lSIOC_SendString..R5
lSIOC_SendString = lSIOC_SendString..R6
— отправляем
if lSIOC_SendString ~= «» then
socket.try(c:send(«Arn.Resp:»..lSIOC_SendString..»n»))
end
end
— процедурызакрытияпорта
function LuaExportStop()
io.close()
socket.try(c:send(«quit»)) — to close the listener socket
c:close()
end

——————————————————————
Приведенный Андреем (Lisa) пример формирования строки переменной для SIOC выглядит очень громоздким. Если, к примеру, мне нужно 50 переменных понадобиться писать более 200 строк?
Наверно существует другой способ записи, может, кто знает и подскажет?

Сообщение отредактировал ra3dcs: 08 September 2012 — 21:03

ra3dcs (08 September 2012 — 21:02) писал:

Наверно существует другой способ записи, может, кто знает и подскажет?

Если этот язык программирования поддерживает массивы и циклы, то, очевидно, надо данные сложить в массив и отправить их в цикле. А приведенный вами код тоже не самый удачный — в нем все переменные складываются в одну строку и отсылаются все скопом если изменилась хотя бы одна переменная. По-хорошему надо отсылать только те переменные, которые не изменились. Описание этого языка программирования доступно? Я мог бы почитать его и что-нибудь присоветовать…

САБ (09 September 2012 — 02:17) писал:

если изменилась хотя бы одна переменная

Нет, даже хуже -все переменные отсылаются при каждом проходе этой функции. Условие if lSIOC_SendString ~= «» then будет истинно всегда, ибо перед этим мы заносили в строку значения переменных: lSIOC_SendString = lSIOC_SendString..R0. Тут бы добавить глобальную переменную lSIOC_SendStringPrev и сравнивать с ней, а обновлять ее значение после отправки… Но лучше массив, цикл и отправлять только действительно изменившиеся переменные..

САБ (09 September 2012 — 02:17) писал:

Если этот язык программирования поддерживает массивы и циклы

Это скрипт на Lua. Значит поддерживаются ассоциативные массивы (таблицы), циклы и ещё много чего.

САБ (09 September 2012 — 02:17) писал:

Описание этого языка программирования доступно?

Доступно:
http://www.lua.ru/doc/
http://steps3d.narod…a-tutorial.html
http://www.script-coding.com/Lua.html
http://w3d.wiki-site….php/Основы_Lua
http://ltwood.wikido…ipting:lua-lang
http://symmetrica.net/lua/lua1.pdf

Вот этот кусок с присвоением переменных:

Spoiler

вроде можно сократить таким образом:

R0 = «0=»..math.floor(TAS + 0.5)..»:»
R1 = «1=»..math.floor(IAS + 0.5)..»:»
R2 = «2=»..math.floor(AOA*ToDegree + 0.5)..»:»
R3 = «3=»..math.floor(Gp.y + 0.5)..»:»
R4 = «4=»..math.floor(VV + 0.5)..»:»
R5 = «5=»..math.floor(altBar + 0.5)..»:»
R6 = «6=»..math.floor(altRad + 0.5)..»:»

Jeka_M (09 September 2012 — 03:58) писал:

Вот этот кусок с присвоением переменных:
вроде можно сократить таким образом:

R0 = «0=»..math.floor(TAS + 0.5)..»:»
R1 = «1=»..math.floor(IAS + 0.5)..»:»
R2 = «2=»..math.floor(AOA*ToDegree + 0.5)..»:»
R3 = «3=»..math.floor(Gp.y + 0.5)..»:»
R4 = «4=»..math.floor(VV + 0.5)..»:»
R5 = «5=»..math.floor(altBar + 0.5)..»:»
R6 = «6=»..math.floor(altRad + 0.5)..»:»

Спасибо! Работает!!!

Прикрепленные изображения

  • Sioc1.JPG

Если принцип функционирования скрипта оставить как есть, то ещё вот этот фрагмент:

ra3dcs (08 September 2012 — 21:02) писал:

— записываемстрочку
lSIOC_SendString = lSIOC_SendString..R0
lSIOC_SendString = lSIOC_SendString..R1
lSIOC_SendString = lSIOC_SendString..R2
lSIOC_SendString = lSIOC_SendString..R3
lSIOC_SendString = lSIOC_SendString..R4
lSIOC_SendString = lSIOC_SendString..R5
lSIOC_SendString = lSIOC_SendString..R6

можно сократить вот так:
lSIOC_SendString = lSIOC_SendString..R0..R1..R2..R3..R4..R5..R6

или даже так:
lSIOC_SendString = R0..R1..R2..R3..R4..R5..R6
(Если предполагается, что раньше этого фрагмента НЕ будет присвоено какое-то значение переменной lSIOC_SendString, которое также нужно добавить в отправляемую строку. В данном скрипте так и есть, эта переменная объявляется пустой в функции LuaExportAfterNextFrame() )

———
Если же количество пересылаемых данных влияет на производительность, то как писал ув. САБ, можно подумать и попробовать переделать скрипт так, чтобы отправлялись только те переменные, которые поменяли своё значение, а не все подряд. Это при условии, что SIOC не обязательно каждый раз пересылать значение переменной, если оно не изменилось. Я с SIOC и с «железными кокпитами» вообще не сталкивался, поэтому не уверен.

Сообщение отредактировал Jeka_M: 09 September 2012 — 13:41

Jeka_M (09 September 2012 — 13:22) писал:

можно сократить вот так:
lSIOC_SendString = lSIOC_SendString..R0..R1..R2..R3..R4..R5..R6

Спасибо!
Подскажите максимальная длинна строки переменной какая может быть?

ra3dcs (09 September 2012 — 18:19) писал:

Подскажите максимальная длинна строки переменной какая может быть?

К сожалению не могу подсказать, нигде не нашёл такой информации. Нужно пробовать.

ra3dcs (10 September 2012 — 14:47) писал:

но с Иваном на эту тему говорить бесполезно, не создан он для общения с коллегами.

Странно, у меня сложилось противоположное мнение.

ra3dcs (10 September 2012 — 14:47) писал:

По «разведданным» эта программа есть еще у Сергея (Саб) может он, что подскажет в этом направлении?

Основные параметры полета удалось получить, за исключением сигнальных лампочек и вооружения.
Функция вывода примерно будет выглядеть пока так.
function LuaExportAfterNextFrame()
    local lSIOC_SendString = «»
    local TAS = LoGetTrueAirSpeed()* 3.6 — значение истинной скорости
    local IAS = LoGetIndicatedAirSpeed()* 3.6     — значение приборной скорости  
    local AOA = LoGetAngleOfAttack() — угол атаки
    local Gp  = LoGetAccelerationUnits()     — перегрузка
    local VV  = LoGetVerticalVelocity()   — верт. скорость
    local altBar = LoGetAltitudeAboveSeaLevel()   — высота баром.
    local altRad = LoGetAltitudeAboveGroundLevel()   — радио высота
    local pitch, bank, yaw = LoGetADIPitchBankYaw()  — крен, тангаж, курс.
    local Mach = LoGetMachNumber()


    local Magn_yaw = LoGetMagneticYaw()  — ????

    local HSI    = LoGetControlPanel_HSI()  — ????
    local engine = LoGetEngineInfo()  — параметры двигателя температура, обороты, топливо, гидро.
    local route = LoGetRoute()
    local PlaneID = LoGetPlayerPlaneId()
    local obj = LoGetObjectById(PlaneID)
    local myXCoord, myZCoord = getXYCoords(obj.LatLongAlt.Lat, obj.LatLongAlt.Long)
    local navi = LoGetNavigationInfo()


    — формируем строчку номер переменной = значение

    — округляем значение до целого
    R0 = «0=»..math.floor(TAS + 0.5)..»:»
    R1 = «1=»..math.floor(IAS + 0.5)..»:»
    R2 = «2=»..math.floor(AOA*ToDegree + 0.5)..»:»
    R3 = «3=»..math.floor(Gp.y + 0.5)..»:»
    R4 = «4=»..math.floor(VV + 0.5)..»:»
    R5 = «5=»..math.floor(altBar + 0.5)..»:»
    R6 = «6=»..math.floor(altRad + 0.5)..»:»
     R7 = «7=»..math.floor(HSI.Compass + 0.5)..»:»
    R8 = «8=»..math.floor(engine.RPM.left + 0.5)..»:»
    R9 = «9=»..math.floor(engine.RPM.right + 0.5)..»:»
    R10 = «10=»..math.floor(engine.Temperature.left + 0.5)..»:»
    R11 = «11=»..math.floor(engine.Temperature.right + 0.5)..»:»
    R12 = «12=»..math.floor(pitch*ToDegree + 0.5)..»:»
    R13 = «13=»..math.floor(bank*ToDegree + 0.5)..»:»
    R14 = «14=»..math.floor(yaw*ToDegree + 0.5)..»:»
    R15 = «15=»..math.floor(Magn_yaw*ToDegree + 0.5)..»:»
    R16 = «16=»..math.floor(engine.fuel_internal + 0.5)..»:»
    R17 = «17=»..math.floor(engine.fuel_external + 0.5)..»:»
    R18 = «18=»..math.floor(engine.HydraulicPressure.left + 0.5)..»:»
    R19 = «19=»..math.floor(engine.HydraulicPressure.right + 0.5)..»:»
    R20 = «20=»..math.floor(navi.Requirements.roll + 0.5)..»:»
    R21 = «21=»..math.floor(navi.Requirements.pitch + 0.5)..»:»
    R22 = «22=»..math.floor(navi.Requirements.altitude + 0.5)..»:»
    R23 = «23=»..math.floor(myXCoord + 0.5)..»:»
    R24 = «24=»..math.floor(obj.LatLongAlt.Alt + 0.5)..»:»
    R25 = «25=»..math.floor(myZCoord + 0.5)..»:»
    — записываем строчку
    lSIOC_SendString = lSIOC_SendString..R0..R1..R2..R3..R4..R5..R6..R7..R8..R9..R10..R11..R12..R13..R14..R15..R16..R17..R18..R19..R20..R21..R22..R23..R24..R25
    — отправляем
    if lSIOC_SendString ~= «» then
    socket.try(c:send(«Arn.Resp:»..lSIOC_SendString..»n»))
    end
end
————————————————————————————————
Однако получить данные от Локк Она оказалось еще пол дела, теперь нужно эти переменные вытащить из SIOС-а.
Иван (Sly) написал программу клиент, но с Иваном на эту тему говорить бесполезно, не создан он для общения с коллегами.
По «разведданным» эта программа есть еще у Сергея (Саб) может он, что подскажет в этом направлении?

LISА (10 September 2012 — 18:12) писал:

рабочий код приводить не буду, лень искать (для лок она это все равно не атуально)

Жаль! Пригодилось бы!

Вот записали меня во враги народа )))
Не помню чтобы я кому-нибудь отказывал…

Александр и и не помню чтобы вы обращались ко мне с подобной просьбой.
Собственно прокладку можете взять у Сергея, могу отправить я как первоисточник )

С Уважением, Иван.

напоминаю, что можно сэкономить на передаче данных !
кроме функции LuaExportAfterNextFrame()
есть еще другой способ получения данных через равные интервалы времени:

function LuaExportActivityNextEvent(t)
  local tNext = t
  ......
  tNext = tNext + 0.1  --  сдесь задается временнной интервал в секундах 
  return tNext
end

кроме того массив состояния сигнальных ламп можно (даже нужно!) обработать с помощью цикла,
рабочий код приводить не буду, лень искать (для лок она это все равно не атуально)

ra3dcs (13 September 2012 — 14:22) писал:

Соединение с сервером есть

Александр, еще чуть-чуть и сможете наконец выбросить свой комп с виндовсом МЕ :sarcastic:

При технической поддержки Евгения (Shaman_2010) попытаемся встроить подпрограмму чтения переменных от сервера SIOC. В программу управления приборами.
Язык программирования Delphi.

В строку подключаемых модулей добавляем модуль Sockets.

И на существующую форму добавляем объект ClientSocket . Так же нам еще понадобятся три кнопки  и два поля редактирования  компоненты Edit для ввода адреса сервера и номера порта,

Прикрепленные изображения

  • Sioc2.JPG
  • Sioc3.JPG

Процедура Обработки события при нажатии кнопки «Connect Button.

                           procedure TForm1.Connect_Buttonclick(Sender: TObject);
begin
   ClientSocket.Address := Adress_SIOC.Text;
   ClientSocket.Host := Adress_SIOC.Text;
   ClientSocket.Port := StrToInt(Port_SIOC.Text);
   ClientSocket.Active := True;
end;

Процедура обработки сообщения об ошибках:


procedure TForm1.ClientSocketError(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  if ErrorCode = 10061 then begin
    ShowMessage(‘Сервер не найден!’);
    ErrorCode := 0;
  end else begin
    ShowMessage(‘Неизвестная ошибка!’);
    ErrorCode := 0;
  end;
end;




Процедура чтения данных с сервера:



procedure TForm1.ClientSocketRead(Sender: TObject;

  Socket: TCustomWinSocket);
var
  sBuffer: string;
  iPos, iVar, iVal: integer;
begin
sBuffer := Socket.ReceiveText;
  if pos(‘Resp’, sBuffer) <> 0 then begin
    sBuffer := StringReplace(sBuffer, ‘Arn.Vivo:’, », [rfReplaceAll]);
    sBuffer := StringReplace(sBuffer, ‘Arn.Resp:’, », [rfReplaceAll]);
    sBuffer := StringReplace(sBuffer, #$D + #$A, », [rfReplaceAll]);
    if length(sBuffer) > 0 then begin
  while (length(sBuffer) > 1) do begin
    iPos := pos(‘=’, sBuffer);
    iVar := StrToInt(copy(sBuffer, 1, iPos — 1));
    delete(sBuffer, 1, iPos);
    iPos := pos(‘:’, sBuffer);
    iVal := StrToInt(copy(sBuffer, 1, iPos — 1));
    delete(sBuffer, 1, iPos);
    Log_window.Lines.Add(IntToStr(iVar) + ‘==’ + IntToStr(iVal))
  end;
    end;
  end;
  sBuffer := »;
end;

Процедура обработки соединения.


procedure TForm1.ClientSocketConnect(Sender: TObject;

  Socket: TCustomWinSocket);
begin
  Connect_Button.Enabled := False;
  Disconnect_Button.Enabled := True;
  Button1.Enabled := True;
  ClientSocket.Socket.SendText(SIOC_Hello);
end;
Процедура отработки нажатия кнопки запрос данных:


procedure TForm1.Button1Click(Sender: TObject);

begin
  SIOC_Quest := ‘0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20‘;
  SIOC_Vars := ‘Arn.Inicio:’ + SIOC_Quest + #$D + #$A;
  ClientSocket.Socket.SendText(SIOC_Vars);
  SIOC_Vars := »;
end;
Процедура нажатия кнопки Disconnekt и отключение от  сервера.


procedure TForm1.ClientSocketDisconnect(Sender: TObject;

  Socket: TCustomWinSocket);
begin
  Connect_Button.Enabled := True;
  Disconnect_Button.Enabled := False;
  Button1.Enabled := False;
end;


procedure TForm1.Disconnect_Buttonclick(Sender: TObject);

begin
   ClientSocket.Socket.SendText(‘Arn.Fin’ + #$D + #$A);
   ClientSocket.Active := False;
end;
Что получилось в итоге?
Соединение с сервером есть, данные получаю, но использовать пока не могу, так как переменные iVar , iVal  оказались локальные и доступны пока в процедуре чтения данных.

Прикрепленные изображения

  • Sioc4.JPG

САБ (13 September 2012 — 15:39) писал:

Александр, еще чуть-чуть и сможете наконец выбросить свой комп с виндовсом МЕ :sarcastic:

Пока еще такого сделать не могу!!!!!

Наконец заработали основные приборы!
Но некоторые параметры найти в ЛокОне пока не удалось.
Это индикация положения шасси.
Индикация положения закрылков,
Тормозной шиток.
Давление топлива.
Давление масла.
Мркер, ДПР,БПР.

Прикрепленные изображения

  • P1040234.JPG

ra3dcs (22 September 2012 — 18:00) писал:

Это индикация положения шасси.
Индикация положения закрылков,
Тормозной шиток.

LoGetMechInfo()

result_is =
{
gear          = {status,value,main = {left = {rod},right = {rod},nose =  {rod}}}
flaps   = {status,value}  
speedbrakes   = {status,value}
refuelingboom = {status,value}
airintake     = {status,value}
noseflap      = {status,value}
parachute     = {status,value}
wheelbrakes   = {status,value}
hook          = {status,value}
wing          = {status,value}
canopy        = {status,value}
controlsurfaces = {elevator = {left,right},eleron = {left,right},rudder = {left,right}} — relative vlues (-1,1) (min /max) (sorry:(
}

Еще бы пример записи этого в export.lua посмотреть!

Ну если совсем кратко то так

local MechInfo = LoGetMechInfo()

if MechInfo then
  local gVal = MechInfo.gear.value —состояние шасси (от 0 до 1)
  local bVal = MechInfo.speedbrakes.value  —воздушный тормоз (от 0 до 1)
  local fVal = MechInfo.flaps.value —положение закрылков (от 0 о1)
  local hStat = MechInfo.hook.status  — тормозной гак
end

положения упр. поверхностей выдаются значениями от 0 до 1

сложность была только одна, с индикацией положений закрылков и воздухозаборника. Насколько я помню, была зависимость от высоты полета (воздухозаборник) и угла атаки (закрылки)
гдето вот в этой теме http://forums.eagle….t=67613&page=17 полный код экспорта выкладывал, поищи там самый последний вариант, тамже есть ссылка на видео работы ППИ, вроде достаточно похоже получилось

Сообщение отредактировал kreml: 23 September 2012 — 06:54

Спасибо!
Работает если только вместо value поставить status.
И по шасси хотелось бы получить состояние раздельных стоек.

    R20 = «20=»..math.floor(MechInfo.gear.status)..»:»
    R21 = «21=»..math.floor(MechInfo.speedbrakes.status)..»:»
    R22 = «22=»..math.floor(MechInfo.flaps.status)..»:»

С отдельными стойками косяк в экспорте, вывести по отдельности неполучица.

Сообщение отредактировал kreml: 23 September 2012 — 15:28

Kreml, подскажите эти сигналы есть возможность вытащить?
«Триммер РВ».
«Пуск разрешен»
«Отворот»

По первым двум пунктам надо посмотреть, а вот «Отворот» думаю придется самим считать по параметрам полета.

Довольно интересно организован экспорт в ЛоскОне.
Сингал airintake = {status} (клин воздухозаборника) выводится одновременно с выпуском шасси.
wheelbrakes   = {status,value}  тормоз колес не выводится совсем!

Сообщение отредактировал ra3dcs: 26 September 2012 — 14:11

Еще интересный глюк с экспортом данных.
При сбросе тормозного парашюта пропадает сигнал выпущенного положения шасси.

Кто знает, есть в экспорте Lock On сигнал «пожар двигателя» и соответственно «пожаротушение»?

вот кусок мего кода

local MCPState = LoGetMCPState()

local FIRE_L = (MCPState.LeftEngineFailure and 1) or 0
local FIRE_R = (MCPState.RightEngineFailure and 1) or 0
local FIRE = ( ((FIRE_L == 1) or (FIRE_R == 1)) and 1) or 0

Сообщение отредактировал kreml: 13 October 2012 — 19:24

kreml (13 October 2012 — 19:24) писал:

вот кусок мего кода
………

Cпасибо, работает!

Прикрепленные изображения

  • Fire1.JPG
  • P1040244.JPG

На примере кода Kreml  еще получилась индикация нейтрального положения триммера РВ, ЭЛ. РН.

LoGetTrimmerStatus()

возвращает таблицу вида
{
ElevatorNeutral = true/false,
AileronNeutral = true/false,
RudderNeutral = true/false
}

local TrimmerStatus = LoGetTrimmerStatus()   — Индикация триммеров
  
local TRIM_RV = (TrimmerStatus.ElevatorNeutral and 1) or 0   — триммер РВ
local TRIM_EL = (TrimmerStatus. AileronNeutral and 1) or 0   — триммер ЭЛ
local TRIM_RN = (TrimmerStatus. RudderNeutral and 1) or 0   — триммер РН

Сообщение отредактировал ra3dcs: 14 October 2012 — 14:55

Kreml, подскажите сигнал запуска двигателей удалось  вытащить?

kreml (16 October 2012 — 17:17) писал:

((RPM_L > 100) and 1) or 0

В последних собщениях проскакивает эта конструкция. В чем ее глубокий физический смысл? Я не знаю Lua, руководствуюсь только здравым смыслом. Можно предположить, что результат операции «>» содержит единички не только в младшем бите (что очень странно и маловероятно) и тогда «and1» сбрасывает все биты кроме младшего. Но операция or 0 для любого второго операнда даст в результате тот же самый второй операнд, т.е. фактически только зря тратит процессорное время. Язык интерпретирющий, навряд ли имеет оптимизатор способный выкинуть подобный ничего не делающий код, но даже если и выкидывает — какой смысл писать этот лишний код в исходник?

Ну сам сигнал вытащить невыйдет, я его получал расчетным путем:
(если обороты двигателя <50% и они растут, то считаем что двигатели запускаются.)

код:

LastRPM_L = 0 — глобальные переменные для хранения предыдущего показания оборотов
LastRPM_R = 0

function GetOther()

local EngineInfo = LoGetEngineInfo()

local RPM_L = EngineInfo.RPM.left
local RPM_R = EngineInfo.RPM.right

local EngineLeftStart = ((RPM_L > LastRPM_L) and (RPM_L < 50) and 1) or 0  — если текущее показание больше предыдущего и обороты меньше 50%
local EngineRightStart = ((RPM_R > LastRPM_R) and (RPM_R < 50) and 1) or 0
LastRPM_L = RPM_L — запоминаем текущее показание
LastRPM_R = RPM_R

local LeftAfterburning = ((RPM_L > 100) and 1) or 0 — сигнал форсажа
local RightAfterburning = ((RPM_R > 100) and 1) or 0

end

Сообщение отредактировал kreml: 16 October 2012 — 17:18

Да, это особенности языка. в lua нет побитовых операций к каким мы привыкли (кстати все переменные изначально с плавающей запятой), мне даже пришлось писать спец. функции чтобы организовать побитовые И и ИЛИ.

А в луа вот как это работает:
выражение (X1 and X2) = X2 если X1 ИСТИНА, в противном случае равно X1 (т.е. = ЛОЖЬ)
(X1 or X2) = X2 если X1 ЛОЖЬ, в противном случае равно X1 (т.е. = ИСТИНА)
Если из выражения выкинуть or 0, тогда результатом может быть либо 1, либо ЛОЖЬ, а ЛОЖЬ нам в качестве итогового значения совсем ненужна, or 0 делает замену ЛОЖЬ на 0

в итоге вот что получаем:
1) X = ( (RPM_L > 100) and 1), если обороты > 100 то X = 1, иначе оно X = ЛОЖЬ
2) Y = (X or 0),  если X равен ЛОЖЬ, то результат выражения приравнивается к 0, иначе (а иначе Х может быть равен только 1) результат будет равен Х, т.е. 1

Сообщение отредактировал kreml: 16 October 2012 — 19:30

kreml (16 October 2012 — 18:27) писал:

в итоге вот что получаем:

«Вон оно как, Михалыч!». То есть у них ложь и 0 — это совершенно разные, автоматом не приводящиеся друг к другу значения? Хм, запишу себе на корочку.

ra3dcs (24 September 2012 — 19:47) писал:

Kreml, подскажите эти сигналы есть возможность вытащить?
«Триммер РВ».
«Пуск разрешен»
«Отворот»

Первый пункт уже решен. Теперь по второму:
Вытащить полностью идентичный игре сигнал «ПР» не получится, но кое что можно:
1. получил информацию по сопровождаемой цели
2. получил динамические данные по макс. и мин. дальности пуска выбранного оружия (ракет)
3. получил дальность до цели

Используя эти данные, можно вывести «ПР» если дистанция до цели находится между мин и макс дальностью пуска, теперь о том расхождениях с игрой

— дальности пуска рассчитаны только для управляемых ракет, применяемых по захваченной цели. Т.е. если. даже если мы ведем цель, но используем пушку, дальности пуска все равно выводятся для ракеты. Также если цель не захвачена  например при работе по земле, то дальности также не выводятся.
в принципе, этот пункт можно решить, нужно только будет прописать дальности применения неуправляемого оружия, и сравнивать его с дистанцией до цели, а в случае работы по земле, еще рассчитывать дальность до поверхности земли (по оси самолета)
— помехи. Тут сложнее, наша функция всегда выдает нам дистанцию до цели, и диапазон пусков. Мы в принципе имеем информацию, использует цель помехи или нет, также знаем, произошел «прожиг» помехи или нет. Но, в игре, когда захвачена «непроженная» помеха, дистанцию до цели можно ввести вручную, от этого будет зависеть сигнал «ПР», в экспорте введенную дальность мы получить не можем. Это первое расхождение которое не выйдет убрать.
— ракеты с ТГСН. тут сигнал «ПР» зависит не только от разрешенных дальностей пуска, но и того смогла ли ГСН ракеты захватить цель или нет. Информации по ГСН ракет в экспорте тоже нет. Это второе неразрешимое расхождение с игрой.

В итоге, если мое описание заинтересовало, и со всеми недочетами готов мирится, то по «ПР» смогу помочь.

kreml (18 October 2012 — 20:02) писал:

В итоге, если мое описание заинтересовало, и со всеми недочетами готов мирится, то по «ПР» смогу помочь.

Было бы полезно!

Дальность   до  цели   —   штука   то же  прикольная !  Можно  оживить  в  родном   прицеде  АСП-ПФД-21(да и не только в нём)    шкалу  дальности  и  соответственно   отработку   кольца (база цели ) .  Нужно  только  решить главную  проблему  ( для  адекватной  работы  прицела ) —  колимационную  визуалку (или  как  она  там  правильно  называется )  пардон  за  оффтоп.