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;