File : sonar_handler.adb
-- -*- Mode: Ada -*-
-- Filename : sonar_handler.ads
-- Description : synchronization for the sonar readings
-- Author : Christfried Webers
-- Created On : Mon Nov 8 20:47:28 1999
-- Last Modified By: .
-- Last Modified On: .
-- Update Count : 0
-- Status : Experimental
-------------------------------------------------------------------
with Text_IO; use Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
with Metrics; use Metrics;
package body Sonar_Handler is
InvalidSonarData : constant Raw_16Bit := 16#7FFE# ;
Scale : constant Float := 16#05A5.0# / 1000.0 ;
AllValuesNew : SonarFlags := (others => True);
AllValuesOld : SonarFlags := (others => False);
type Orientation is record
X, Y : Mm;
Angle : Degrees;
end record;
Orientations : array (Sonar.Index) of Orientation :=
(
(X => -305, Y => 150, Angle => 180.0),
(X => -270, Y => 180, Angle => 90.0),
(X => 70, Y => 180, Angle => 90.0),
(X => 110, Y => 175, Angle => 75.0),
(X => 165, Y => 175, Angle => 60.0),
(X => 220, Y => 170, Angle => 45.0),
(X => 290, Y => 110, Angle => 30.0),
(X => 295, Y => 55, Angle => 15.0),
(X => 300, Y => 0, Angle => 0.0),
(X => 295, Y => -55, Angle => -15.0),
(X => 290, Y => -110, Angle => -30.0),
(X => 220, Y => -170, Angle => -45.0),
(X => 165, Y => -175, Angle => -60.0),
(X => 110, Y => -175, Angle => -75.0),
(X => 70, Y => -180, Angle => -90.0),
(X => -270, Y => -180, Angle => -90.0),
(X => -305, Y => -150, Angle =>-180.0)
);
function ClusterIndexToSonarIndex (ClusterIndex: Raw_8Bit)
return Sonar.Index is
First : Integer := Sonar.Index'Pos(Sonar.Index'First);
begin
case ClusterIndex is
when 16#00# => return Sonar.Index'Val(First);
when 16#01# => return Sonar.Index'Val(First + 1);
when 16#02# => return Sonar.Index'Val(First + 2);
when 16#03# => return Sonar.Index'Val(First + 3);
when 16#04# => return Sonar.Index'Val(First + 4);
when 16#05# => return Sonar.Index'Val(First + 5);
when 16#10# => return Sonar.Index'Val(First + 6);
when 16#11# => return Sonar.Index'Val(First + 7);
when 16#12# => return Sonar.Index'Val(First + 8);
when 16#13# => return Sonar.Index'Val(First + 9);
when 16#14# => return Sonar.Index'Val(First + 10);
when 16#20# => return Sonar.Index'Val(First + 16);
when 16#21# => return Sonar.Index'Val(First + 15);
when 16#22# => return Sonar.Index'Val(First + 14);
when 16#23# => return Sonar.Index'Val(First + 13);
when 16#24# => return Sonar.Index'Val(First + 12);
when 16#25# => return Sonar.Index'Val(First + 11);
when others =>
Put("Wrong ClusterIndex in packet!");
return Sonar.Index'First;
end case;
end ClusterIndexToSonarIndex;
protected body Reader is
procedure RecordPacket(PacketNumber: Raw_8Bit; Data: ByteArray) is
-- Data = 00 00 00 02
-- <4 Byte TimeStamp>
-- <1 Byte Cluster> <2 Byte Data>
-- <1 Byte Cluster> <2 Byte Data>
-- <1 Byte Cluster> <2 Byte Data>
-- sometimes more clusters
DataIndex : Integer;
ClusterIndex : Raw_8Bit;
SonarIndex : Sonar.Index;
RawData : Raw_16Bit;
DistanceFromSensor : Float;
SensorAngle : Float;
Xposition, Yposition : Float;
begin
DataIndex := Integer(Data'First+8);
while DataIndex <= Data'Last-2 loop
ClusterIndex := Data(DataIndex);
SonarIndex := ClusterIndexToSonarIndex(ClusterIndex);
RawData := TwoBytes_To_Raw_16Bit(Data(DataIndex+1..DataIndex+2));
if RawData = InvalidSonarData then
NewReadings(SonarIndex).Valid := False;
else
NewReadings(SonarIndex).Valid := True;
DistanceFromSensor := Float(RawData) / Scale;
SensorAngle := Float(Orientations(SonarIndex).Angle);
Xposition := Float(Orientations(SonarIndex).X) +
DistanceFromSensor * Cos(SensorAngle, 360.0);
Yposition := Float(Orientations(SonarIndex).Y) +
DistanceFromSensor * Sin(SensorAngle, 360.0);
NewReadings(SonarIndex).Distance :=
Mm(Sqrt(Xposition*Xposition + Yposition * Yposition ));
NewReadings(SonarIndex).Angle :=
Degrees(Arctan(Yposition, Xposition, 360.0));
end if;
NewValueFlag(SonarIndex) := True;
DataIndex := DataIndex + 3;
end loop;
if NewValueFlag = AllValuesNew then
LastStatus.Sonar := NewReadings;
LastStatus.TimeStamp := Ada.Real_Time.Clock;
NewDataArrived := True;
FirstDataArrived := True;
NewValueFlag := AllValuesOld;
end if;
end RecordPacket;
entry GetCurrentStatus(SonarStatus: out Sonar.Status) when FirstDataArrived is
begin
SonarStatus := LastStatus;
end GetCurrentStatus;
entry WaitForNewData when NewDataArrived or NonBlockingActive is
begin
if WaitForNewData'Count = 0 then
NewDataArrived := False;
end if;
end WaitForNewData;
procedure NonBlocking is
begin
NonBlockingActive := True;
end NonBlocking;
end Reader;
protected body Commander is
procedure StartReading is
begin
Flex_Driver.WriteTask.SendPacket(ByteArray(SonarStartSendingPacket),
SonarStartStopSending);
end StartReading;
procedure StopReading is
begin
Flex_Driver.WriteTask.SendPacket(ByteArray(SonarStopSendingPacket),
SonarStartStopSending);
end StopReading;
end Commander;
end Sonar_Handler;