19 #ifndef SNARK_SENSORS_VELODYNE_STREAM_H_
20 #define SNARK_SENSORS_VELODYNE_STREAM_H_
23 #include <boost/noncopyable.hpp>
24 #include <boost/optional.hpp>
25 #include <boost/scoped_ptr.hpp>
26 #include <boost/date_time/posix_time/posix_time.hpp>
27 #include <comma/math/compare.h>
28 #include <snark/sensors/velodyne/db.h>
29 #include <snark/sensors/velodyne/laser_return.h>
30 #include <snark/sensors/velodyne/packet.h>
31 #include <snark/sensors/velodyne/impl/stream_traits.h>
32 #include <snark/sensors/velodyne/impl/get_laser_return.h>
34 namespace snark {
namespace velodyne {
37 template <
typename S >
38 class stream :
public boost::noncopyable
42 stream( S*
stream,
unsigned int rpm,
bool outputInvalid =
false,
bool outputRaw =
false );
45 stream( S* stream,
bool outputInvalid =
false,
bool outputRaw =
false );
55 unsigned int scan()
const;
61 boost::optional< double > m_angularSpeed;
64 boost::scoped_ptr< S > m_stream;
65 boost::posix_time::ptime m_timestamp;
66 const packet* m_packet;
67 enum { m_size = 12 * 32 };
73 index() : idx( 0 ), block( 0 ), laser( 0 ) {}
74 const index& operator++()
80 if( laser < 32 ) { --block; }
else { laser = 0; ++block; }
88 bool operator==(
const index& rhs )
const {
return idx == rhs.idx; }
95 double angularSpeed();
98 template <
typename S >
100 : m_angularSpeed( ( 360 / 60 ) * rpm )
101 , m_outputInvalid( outputInvalid )
102 , m_outputRaw( outputRaw )
108 m_index.idx = m_size;
111 template <
typename S >
113 : m_outputInvalid( outputInvalid )
114 , m_outputRaw( outputRaw )
120 m_index.idx = m_size;
123 template <
typename S >
126 if( m_angularSpeed ) {
return *m_angularSpeed; }
127 double da = double( m_packet->blocks[0].rotation() - m_packet->blocks[11].rotation() ) / 100;
128 double dt = double( ( impl::time_offset( 0, 0 ) - impl::time_offset( 11, 0 ) ).total_microseconds() ) / 1e6;
132 template <
typename S >
137 if( m_index.idx >= m_size )
140 m_packet =
reinterpret_cast< const packet*
>( impl::stream_traits< S >::read( *m_stream,
sizeof( packet ) ) );
141 if( m_packet == NULL ) {
return NULL; }
142 m_timestamp = impl::stream_traits< S >::timestamp( *m_stream );
147 m_laserReturn = impl::getlaser_return( *m_packet, m_index.block, m_index.laser, m_timestamp, angularSpeed(), m_outputRaw );
149 bool valid = !comma::math::equal( m_laserReturn.range, 0 );
150 if( m_count > 100 && valid && m_laserReturn.azimuth < 5 ) { ++m_scan; m_count = 0; }
151 if( valid || m_outputInvalid ) {
return &m_laserReturn; }
156 template <
typename S >
159 template <
typename S >
162 template <
typename S >
168 m_packet =
reinterpret_cast< const packet*
>( impl::stream_traits< S >::read( *m_stream,
sizeof( packet ) ) );
169 if( m_packet == NULL ) {
return; }
170 m_timestamp = impl::stream_traits< S >::timestamp( *m_stream );
173 if( m_count < 100 ) {
continue; }
174 while( m_index.idx < m_size )
176 m_laserReturn = impl::getlaser_return( *m_packet, m_index.block, m_index.laser, m_timestamp, angularSpeed(), m_outputRaw );
178 if( comma::math::equal( m_laserReturn.range, 0 ) ) {
continue; }
179 if( m_laserReturn.azimuth > 5 ) {
break; }