function [range_cm] = hokuyoRangeNavLab(s1, fireString, theta) % s1 (serial port object) and fireString are set up by hokuyoRangeIntensity_Init % return Range in CM, intensity in ???, and any error codes % Theta has been established by hokuyoRangeIntensity_Init maxedOut = 1000; %Intensity = nan(N,M); %AGC = nan(N,M); % FIRE THE LASER! fprintf(s1,fireString); % laser is a string 'GXXXYYYZZ' % G: Get range data % XXX three digit # is starting angle in counts (min is 000) % YYY three digit # is end angle (max is 768) % ZZ two digits cluster size (returns min dist in cluster) % count goes CCW, but dead until 44 % straight ahead is 384 % ends at 768 but dead after 725 % nominal angular range is 270 degrees % [N,M] = size(theta); %err = nan(N,M); range_cm = maxedOut*ones(N,M); try % taking a scan % Read Response % need to make sure you read all data! % ciel(769/inc) *2+Line feeds + status (1-2 numbers?) + command echo (9) % expect a message 1576 characters long for full scan? response = fread(s1,1); while response~='G' response = fread(s1,1) end response = fread(s1, 88); %1st 8 are echo of original command, LF(8), error message(10?)? % can error message be 2 digits? if char(response(10))~='0' disp('error taking scan?') char(response(9)) char(response(10)) char(response(11)) %return % see manual, but their error messages don't make sense end % next line feed (code 10) begins raneg info lineFeeds = find(10 == response); nonLineFeeds = find(10 ~= response); startIndexRange = lineFeeds(2)+1; endIndexrange = length(response); %removing all line feeds RangeRaw = response(nonLineFeeds); % starting after second line feed % subtract offset of 30 base 16 RangeRaw = double(uint8(RangeRaw(startIndexRange-2:end)))-3*16; % one range is two numbers representing second 6 bits, then 1st 6 bits for i = 1:2:length(RangeRaw)-1 range_cm( (i+1)/2) = .1*(RangeRaw(i)*64 + RangeRaw(i+1)); % These are the cryptic error codes. 0-2 if range_cm( (i+1)/2) < 2 err((i+1)/2) = 10*range_cm( (i+1)/2); if range_cm( (i+1)/2) == 0 % Says range might be less than min dist % but I observe thsi is really a low intensity return % code range_cm( (i+1)/2) = maxedOut; elseif (range_cm( (i+1)/2) == 1.6)||(range_cm( (i+1)/2) == 0.6) % might be more than max dist range_cm( (i+1)/2) = maxedOut; elseif (range_cm( (i+1)/2) == .1)||(range_cm( (i+1)/2) == 0.2)||(range_cm( (i+1)/2) == .3)||(range_cm( (i+1)/2) == 0.4)||(range_cm( (i+1)/2) == 0.5) % Hmmm this woudl include the "Low Light" Codes range_cm( (i+1)/2) = maxedOut; else % may have error code in previous or last time just use % value from prev step if i~=1 range_cm( (i+1)/2) = range_cm( (i-1)/2); else range_cm( (i+1)/2) = maxedOut; end end end % Big digit is 1-5 small digit fluctuates up to 63 % Not sure these lines are correct %Intensity( (i+5)/6) = (RangeRaw(i+2)*1024 + RangeRaw(i+3)*16 ); %AGC( (i+5)/6) = (RangeRaw(i+4)*64 + RangeRaw(i+5) ); end catch disp('Warning: Laser did not respond. Returning max values.'); end disp('Flush buffer....') N = s1.BytesAvailable(); while (N~=0) fread(s1,N); N = s1.BytesAvailable(); end