Main MRPT website > C++ reference for MRPT 1.5.7
CServoeNeck.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
12 #include <mrpt/utils/net_utils.h>
14 #include <mrpt/system/threads.h>
15 
16 //const double MAX_VALUE = 10000; // ICR value in the ATMEGA16
17 
18 using namespace mrpt::utils;
19 using namespace mrpt::hwdrivers;
20 using namespace mrpt::math;
21 
22 /*-------------------------------------------------------------
23  default constructor
24 -------------------------------------------------------------*/
25 CServoeNeck::CServoeNeck() :
26  m_usbSerialNumber("eNeck001"),
27  m_MaxValue(10000),
28  m_TruncateFactor(0.5),
29  m_PrevAngles(0),
30  m_NumPrevAngles(5)
31 {
32  m_offsets.resize(3,0);
33 } // end-constructor
34 /*-------------------------------------------------------------
35  default destructor
36 -------------------------------------------------------------*/
38 {}
39 
40 /*-------------------------------------------------------------
41  queryFirmwareVersion
42 -------------------------------------------------------------*/
43 bool CServoeNeck::queryFirmwareVersion( std::string &out_firmwareVersion )
44 {
45  try
46  {
47  utils::CMessage msg,msgRx;
48 
49  // Try to connect to the device:
51  return false;
52 
53 
54  msg.type = 0x10;
55  sendMessage( msg );
56 
57  if (receiveMessage( msgRx ) )
58  {
59  msgRx.getContentAsString( out_firmwareVersion );
61  return true;
62  }
63  else
64  return false;
65 
66  }
67  catch(...)
68  {
69  Close();
70  return false;
71  }
72 } // end-queryFirmwareVersion
73 
74 /*-------------------------------------------------------------
75  angle2RegValue
76 -------------------------------------------------------------*/
77 unsigned int CServoeNeck::angle2RegValue( const double angle /* rad */ )
78 {
79  const uint16_t reg = 1250+(1000/M_PI)*(angle-M_PI*0.5); // equation: v = s*(a-a0) + v0 where s = 450/pi; a0 = 0 and v0 = 750
80  //cout << "Reg: " << reg << endl;
81  return ( reg );
82 
83  //return ( (uint16_t)( (m_MaxValue/20)*(-2*angle/M_PI+1.5) ) ); // equation: v = s*(a-a0) + v0 where s = 450/pi; a0 = 0 and v0 = 750
84  //return ( (uint16_t)( (m_MaxValue/20)*(2*angle/M_PI+1.5) ) ); // equation: v = s*(a-a0) + v0 where s = 450/pi; a0 = 0 and v0 = 750
85  //return ( (uint16_t)( (900/M_PI)*nangle + 750 ) ); // equation: v = s*(a-a0) + v0 where s = 450/pi; a0 = 0 and v0 = 750
86 } // end-angle2RegValue
87 
88 /*-------------------------------------------------------------
89  regValue2angle
90 -------------------------------------------------------------*/
92 {
93  double angle = M_PI*0.5+(M_PI/1000)*(value-1250);
94  return angle;
95 
96  //return ( -M_PI*0.5*(20*value/m_MaxValue-1.5) ); // equation: angle = (pi/2)*(20*OCR/ICR-1.5)
97  //return ( -M_PI*0.25+(M_PI/1800)*(value-1050) ); // equation: angle = (pi/2)*(20*OCR/ICR-1.5)
98  // return ( M_PI*0.5*(20*value/m_MaxValue-1.5) ); // equation: angle = (pi/2)*(20*OCR/ICR-1.5)
99  // return ( (value-750)/(900/M_PI) );
100 } // end-regValue2angle
101 
102 /*-------------------------------------------------------------
103  setRegisterValue
104 -------------------------------------------------------------*/
105 bool CServoeNeck::setRegisterValue( const uint16_t value, const uint8_t servo, bool fast )
106 {
107  try
108  {
109  if (!isOpen())
110  return false;
111 
112  utils::CMessage msg,msgRx;
113 
114  // Send cmd for setting the value of the register:
115  // ------------------------------------------------
116  if( fast )
117  msg.type = 0x15;
118  else
119  msg.type = 0x11;
120  msg.content.resize( 3 );
121  msg.content[2] = (uint8_t)value; // Low byte
122  msg.content[1] = (uint8_t)(value>>8); // High byte
123  msg.content[0] = servo; // Servo number
124 
125  sendMessage(msg);
126  if (!receiveMessage(msgRx) )
127  return false; // Error
128 
129  mrpt::system::sleep(200);
130  return true;
131  }
132  catch(...)
133  {
134  // Error opening device:
135  Close();
136  return false;
137  }
138 
139 } // end-setRegisterValue
140 
141 /*-------------------------------------------------------------
142  setRegisterValue
143 -------------------------------------------------------------*/
144 bool CServoeNeck::setRegisterValueAndSpeed( const uint16_t value, const uint8_t servo, const uint16_t speed )
145 {
146  try
147  {
148  if (!isOpen())
149  return false;
150 
151  utils::CMessage msg,msgRx;
152 
153  // Send cmd for setting the value of the register:
154  // ------------------------------------------------
155  msg.type = 0x16;
156  msg.content.resize(5);
157  msg.content[4] = (uint8_t)speed; // Low byte of the speed of the servo
158  msg.content[3] = (uint8_t)(speed>>8); // High byte of the speed of the servo
159  msg.content[2] = (uint8_t)value; // Low byte
160  msg.content[1] = (uint8_t)(value>>8); // High byte
161  msg.content[0] = servo; // Servo number
162 
163  sendMessage(msg);
164  if (!receiveMessage(msgRx) )
165  return false; // Error
166 
167  mrpt::system::sleep(200);
168  return true;
169  }
170  catch(...)
171  {
172  // Error opening device:
173  Close();
174  return false;
175  }
176 
177 } // end-setRegisterValue
178 
179 /*-------------------------------------------------------------
180  getRegisterValue
181 -------------------------------------------------------------*/
183 {
184  try
185  {
186  if (!isOpen())
187  return false;
188 
189  utils::CMessage msg,msgRx;
190 
191  // Send cmd for obtaining the value of the OCR1A register:
192  // --------------------------------------------------------
193  msg.type = 0x12;
194  msg.content.resize( 1 );
195  msg.content[0] = servo;
196 
197  sendMessage( msg );
198  if (receiveMessage(msgRx) )
199  {
200  if ( msgRx.content.size() != 2 )
201  return false;
202 
203  value = (msgRx.content[0] << 8) + msgRx.content[1];
204  return true;
205  }
206  else
207  return false;
208 
209  return true;
210  }
211  catch(...)
212  {
213  // Error opening device:
214  Close();
215  return false;
216  }
217 
218 } // end-getRegisterValue
219 
220 /*-------------------------------------------------------------
221  getCurrentAngle
222 -------------------------------------------------------------*/
223 bool CServoeNeck::getCurrentAngle( double &angle, const uint8_t servo )
224 {
225  uint16_t value;
226  if( getRegisterValue( value, servo ) )
227  {
228  angle = regValue2angle( value );
229  return true;
230  }
231  else
232  return false;
233 } // end-getCurrentAngle
234 
235 /*-------------------------------------------------------------
236  setAngle
237 -------------------------------------------------------------*/
238 bool CServoeNeck::setAngle( double angle, const uint8_t servo, bool fast )
239 {
240  //double nangle = -angle;
241 
242  //if( nangle < -m_TruncateFactor*M_PI/2 ) nangle = -m_TruncateFactor*M_PI/2;
243  //if( nangle > m_TruncateFactor*M_PI/2 ) nangle = m_TruncateFactor*M_PI/2;
244 
245  //unsigned int reg = angle2RegValue( nangle );
246 
247  //std::cout << "Angle: " << RAD2DEG( nangle ) << " - Reg: " << reg << std::endl;
248  //return setRegisterValue( reg, servo );
249 
250  if( angle < -m_TruncateFactor*M_PI/2 ) angle = -m_TruncateFactor*M_PI/2;
251  if( angle > m_TruncateFactor*M_PI/2 ) angle = m_TruncateFactor*M_PI/2;
252 
253  unsigned int reg = angle2RegValue( m_offsets[servo]+angle );
254 
255  std::cout << "Angle: " << RAD2DEG( angle ) << " - Reg: " << reg << std::endl;
256  return setRegisterValue( reg, servo, fast );
257 
258 } // end-getCurrentAngle
259 
260 /*-------------------------------------------------------------
261  setAngleAndSpeed
262 -------------------------------------------------------------*/
263 bool CServoeNeck::setAngleAndSpeed( double angle, const uint8_t servo, const uint8_t speed )
264 {
265  // speed in the range 15/s-250/s
266  if( angle < -m_TruncateFactor*M_PI/2 ) angle = -m_TruncateFactor*M_PI/2;
267  if( angle > m_TruncateFactor*M_PI/2 ) angle = m_TruncateFactor*M_PI/2;
268 
269  unsigned int reg = angle2RegValue( m_offsets[servo]+angle );
270  uint8_t thisSpeed = speed < 15 ? 15 : speed > 250 ? 250 : speed;
271  uint16_t delSpeed = uint16_t(0.25*1000000/(500+1000*(thisSpeed/180.0f-0.5)));
272  //cout << "Speed: " << int(speed) << " -> " << delSpeed << endl;
273  //std::cout << "Angle: " << RAD2DEG( angle ) << " - Reg: " << reg << std::endl;
274  return setRegisterValueAndSpeed( reg, servo, delSpeed );
275 
276 } // end-getCurrentAngle
277 
278 /*-------------------------------------------------------------
279  setAngleWithFilter
280 -------------------------------------------------------------*/
281 bool CServoeNeck::setAngleWithFilter( double angle, const uint8_t servo, bool fast )
282 {
283  double nangle = 0;
284  if( m_PrevAngles.size() == m_NumPrevAngles && m_NumPrevAngles != 0) // If the deque is full populated
285  m_PrevAngles.erase( m_PrevAngles.begin() ); // Erase the first angle of the deque
286 
287  m_PrevAngles.push_back( angle ); // Push back the new angle
288 
290  for( it = m_PrevAngles.begin(); it != m_PrevAngles.end(); ++it ) // Sum up all the elements in the deque
291  nangle += *it;
292  nangle /= m_PrevAngles.size(); // Mean angle
293 
294  return ( setAngle( nangle, servo, fast ) );
295 }
296 
297 /*-------------------------------------------------------------
298  disableServo
299 -------------------------------------------------------------*/
301 {
302  try
303  {
304  if (!isOpen())
305  return false;
306 
307  utils::CMessage msg,msgRx;
308 
309  // Send cmd for disabling servo:
310  // ----------------------------
311  msg.type = 0x13;
312  msg.content.resize( 1 );
313  msg.content[0] = servo; // Servo number
314 
315  sendMessage(msg);
316  if (!receiveMessage(msgRx) )
317  return false; // Error
318 
319  return true;
320  }
321  catch(...)
322  {
323  // Error opening device:
324  Close();
325  return false;
326  }
327 
328 } // end-getCurrentAngle
329 
330 /*-------------------------------------------------------------
331  enableServo
332 -------------------------------------------------------------*/
334 {
335  try
336  {
337  if (!isOpen())
338  return false;
339 
340  utils::CMessage msg,msgRx;
341 
342  // Send cmd for enabling the servo:
343  // --------------------------------
344  msg.type = 0x14;
345  msg.content.resize( 1 );
346  msg.content[0] = servo; // Servo number
347 
348  sendMessage(msg);
349  if (!receiveMessage(msgRx) )
350  return false; // Error
351 
352  return true;
353  }
354  catch(...)
355  {
356  // Error opening device:
357  Close();
358  return false;
359  }
360 
361 } // end-getCurrentAngle
362 
363 /*-------------------------------------------------------------
364  Center
365 -------------------------------------------------------------*/
366 bool CServoeNeck::center( const uint8_t servo )
367 {
368  unsigned int value = angle2RegValue( m_offsets[servo] );
369  return setRegisterValue( value, servo );
370 } // end-Center
371 
372 /*-------------------------------------------------------------
373  checkConnectionAndConnect
374 -------------------------------------------------------------*/
376 {
377  if( isOpen() )
378  return true;
379 
380  try
381  {
384  Purge();
386  SetLatencyTimer(1);
387  SetTimeouts(300,100);
388  return true;
389  }
390  catch(...)
391  {
392  // Error opening device:
393  Close();
394  return false;
395  }
396 } // end-checkConnectionAndConnect
397 
398 /*-------------------------------------------------------------
399  setOffsets
400 -------------------------------------------------------------*/
401 void CServoeNeck::setOffsets(float offset0, float offset1, float offset2)
402 {
403  m_offsets.resize(3);
404  m_offsets[0] = offset0;
405  m_offsets[1] = offset1;
406  m_offsets[2] = offset2;
407 }
void SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
Change read & write timeouts, in milliseconds.
unsigned int angle2RegValue(const double angle)
Converts from a decimal angle (in radians) to the corresponding register value for the ATMEGA16 contr...
Definition: CServoeNeck.cpp:77
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
unsigned __int16 uint16_t
Definition: rptypes.h:46
bool setRegisterValueAndSpeed(const uint16_t value, const uint8_t servo, const uint16_t speed)
bool setAngle(double angle, const uint8_t servo=0, bool fast=false)
Turns the servo up to the specified angle (in radians in the range -pi,pi, other values will be satur...
bool checkConnectionAndConnect()
Tries to connect to the USB device (if disconnected).
bool queryFirmwareVersion(std::string &out_firmwareVersion)
Gets the firmware version of the eNeck board.
Definition: CServoeNeck.cpp:43
void OpenBySerialNumber(const std::string &serialNumber)
Open by device serial number.
Scalar * iterator
Definition: eigen_plugins.h:23
bool isOpen()
Checks whether the chip has been successfully open.
Contains classes for various device interfaces.
#define M_PI
Definition: bits.h:78
unsigned int m_NumPrevAngles
Number of previous angles to store for averaging.
Definition: CServoeNeck.h:108
bool center(const uint8_t servo=0)
Centers the servo at zero position.
bool setAngleWithFilter(double angle, const uint8_t servo=0, bool fast=false)
Turns the servo up to the specified angle (in radians in the range -pi,pi) filtered by average with t...
std::vector< float > m_offsets
The offset used for each servo.
Definition: CServoeNeck.h:109
unsigned char uint8_t
Definition: rptypes.h:43
void Purge()
Purge the I/O buffers.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
bool getCurrentAngle(double &angle, const uint8_t servo=0)
Gets the current angle of the servo (in radians within (-pi,pi))
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time...
Definition: threads.cpp:57
bool disableServo(const uint8_t servo=0)
Disables the servo so the neck will be loose.
bool enableServo(const uint8_t servo=0)
Enables the servo so the neck will be tight.
GLsizei const GLchar ** string
Definition: glext.h:3919
void setOffsets(float offset0, float offset1, float offset2)
Load the Offset values for each servo.
#define RAD2DEG
void getContentAsString(std::string &str)
Gets the contents of the message as a string.
bool receiveMessage(utils::CMessage &msg)
Tries to receive a message from the device.
Definition: CStream.cpp:590
void SetLatencyTimer(unsigned char latency_ms)
Change the latency timer (in milliseconds) implemented on the FTDI chip: for a few ms...
std::string m_usbSerialNumber
A copy of the device serial number (to open the USB FTDI chip).
Definition: CServoeNeck.h:104
void sendMessage(const utils::CMessage &msg)
Send a message to the device.
Definition: CStream.cpp:556
bool getRegisterValue(uint16_t &value, const uint8_t servo=0)
std::vector< uint8_t > content
The contents of the message (memory is automatically handled by the std::vector object) ...
Definition: CMessage.h:33
double m_TruncateFactor
The range of turn of the servo will be truncated to "+-m_truncate_factor*(pi/2)". ...
Definition: CServoeNeck.h:106
GLsizei const GLfloat * value
Definition: glext.h:3929
bool setAngleAndSpeed(double angle, const uint8_t servo, const uint8_t speed)
Turns the servo up to the specified angle (in radians in the range -pi,pi, other values will be satur...
std::deque< double > m_PrevAngles
A vector containing the last N angles which where passed to the servo (for averaging) ...
Definition: CServoeNeck.h:107
double regValue2angle(const uint16_t value)
Converts from a certain value of the ATMEGA16 PWM register to the corresponding decimal angle (for in...
Definition: CServoeNeck.cpp:91
A class that contain generic messages, that can be sent and received from a "CClientTCPSocket" object...
Definition: CMessage.h:29
uint32_t type
An identifier of the message type (only the least-sig byte is typically sent)
Definition: CMessage.h:32
bool setRegisterValue(const uint16_t value, const uint8_t servo=0, bool fast=false)
void Close()
Close the USB device.



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019