Вчера попросил нейросеть написать программу для вывода азимута в Label по нажатию кнопки. Все примеры, которые показывалв нейросеть были с ошибками. После пятичасового общения с нейросетью получил работающий пример.
Но значения азимута не то что хаотично менялись, они были непредсказуемыми.
type
TForm1 = class(TForm)
LabelAzimuth: TLabel;
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
FSensorManager: TSensorManager;
FCompass: TCustomOrientationSensor;
FLastValidAzimuth: Double;
FReadingCount: Integer;
function GetNormalizedAzimuth: Double;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
FSensorManager := TSensorManager.Current;
FSensorManager.Active := True;
// Поиск датчика компаса
for i := 0 to FSensorManager.Count - 1 do
if (FSensorManager.Sensors[i].Category = TSensorCategory.Orientation) and
(FSensorManager.Sensors[i] is TCustomOrientationSensor) then
begin
FCompass := TCustomOrientationSensor(FSensorManager.Sensors[i]);
Break;
end;
function TForm1.GetNormalizedAzimuth: Double;
const
MAX_READINGS = 10; // Количество показаний для усреднения
var
RawValue: Double;
begin
Result := FLastValidAzimuth; // Возвращаем последнее валидное значение по умолчанию
if Assigned(FCompass) and FCompass.Started then
begin
try
// Получаем сырое значение
RawValue := FCompass.HeadingX * (180/Pi);
// Фильтрация аномальных значений
if (RawValue > 3600) or (RawValue < -3600) then
Exit; // Игнорируем явно ошибочные значения
// Нормализация в диапазон 0-360
Result := RawValue;
while Result < 0 do Result := Result + 360;
while Result >= 360 do Result := Result - 360;
// Простое усреднение
if FReadingCount < MAX_READINGS then
begin
FLastValidAzimuth := (FLastValidAzimuth * FReadingCount + Result) / (FReadingCount + 1);
Inc(FReadingCount);
end
else
begin
FLastValidAzimuth := Result; // После набора статистики используем текущее значение
end;
except
on E: Exception do
LabelAzimuth.Text := 'Ошибка датчика: ' + E.Message;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(FCompass) then
begin
if not FCompass.Started then
begin
FCompass.Start;
FReadingCount := 0; // Сброс счетчика при ручном запуске
end;
Timer1.Enabled := not Timer1.Enabled;
if Timer1.Enabled then Button1.Text := 'Старт'
else Button1.Text := 'Стоп';
end
else
LabelAzimuth.Text := 'Компас не доступен';
end;
Вопрос
Саша
Вчера попросил нейросеть написать программу для вывода азимута в Label по нажатию кнопки. Все примеры, которые показывалв нейросеть были с ошибками. После пятичасового общения с нейросетью получил работающий пример.
Но значения азимута не то что хаотично менялись, они были непредсказуемыми.
Вот "работающий" пример от нейросети:
unit unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Sensors,
System.Math, FMX.Types, FMX.Controls, FMX.Forms, FMX.StdCtrls,
FMX.Controls.Presentation;
type
TForm1 = class(TForm)
LabelAzimuth: TLabel;
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
FSensorManager: TSensorManager;
FCompass: TCustomOrientationSensor;
FLastValidAzimuth: Double;
FReadingCount: Integer;
function GetNormalizedAzimuth: Double;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
FSensorManager := TSensorManager.Current;
FSensorManager.Active := True;
// Поиск датчика компаса
for i := 0 to FSensorManager.Count - 1 do
if (FSensorManager.Sensors[i].Category = TSensorCategory.Orientation) and
(FSensorManager.Sensors[i] is TCustomOrientationSensor) then
begin
FCompass := TCustomOrientationSensor(FSensorManager.Sensors[i]);
Break;
end;
Timer1.Interval := 300; // Оптимальный интервал обновления
FLastValidAzimuth := 0;
FReadingCount := 0;
end;
function TForm1.GetNormalizedAzimuth: Double;
const
MAX_READINGS = 10; // Количество показаний для усреднения
var
RawValue: Double;
begin
Result := FLastValidAzimuth; // Возвращаем последнее валидное значение по умолчанию
if Assigned(FCompass) and FCompass.Started then
begin
try
// Получаем сырое значение
RawValue := FCompass.HeadingX * (180/Pi);
// Фильтрация аномальных значений
if (RawValue > 3600) or (RawValue < -3600) then
Exit; // Игнорируем явно ошибочные значения
// Нормализация в диапазон 0-360
Result := RawValue;
while Result < 0 do Result := Result + 360;
while Result >= 360 do Result := Result - 360;
// Простое усреднение
if FReadingCount < MAX_READINGS then
begin
FLastValidAzimuth := (FLastValidAzimuth * FReadingCount + Result) / (FReadingCount + 1);
Inc(FReadingCount);
end
else
begin
FLastValidAzimuth := Result; // После набора статистики используем текущее значение
end;
except
on E: Exception do
LabelAzimuth.Text := 'Ошибка датчика: ' + E.Message;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(FCompass) then
begin
if not FCompass.Started then
begin
FCompass.Start;
FReadingCount := 0; // Сброс счетчика при ручном запуске
end;
Timer1.Enabled := not Timer1.Enabled;
if Timer1.Enabled then Button1.Text := 'Старт'
else Button1.Text := 'Стоп';
end
else
LabelAzimuth.Text := 'Компас не доступен';
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
FLastValidAzimuth := GetNormalizedAzimuth;
LabelAzimuth.Text := Format('Азимут: %.1f°', [FLastValidAzimuth]);
end;
end.
Выходит, что Embarcadero не может работать корретно с сенсорами. А приложения с компасом, написанные на JAVA работают четко.
Известно, что как-то можно соединить в одном приложении Delphi и Java. Подскажите, пожалуйста, в каком направлении копать.
спасибо!
2 ответа на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.