AnimatLab  2
Test
RbDynamixelUSBServo.cpp
1 // RbDynamixelUSBServo.cpp: implementation of the RbDynamixelUSBServo class.
2 //
4 
5 #include "StdAfx.h"
6 #include <stdarg.h>
7 #include "RbMovableItem.h"
8 #include "RbBody.h"
9 #include "RbJoint.h"
10 #include "RbMotorizedJoint.h"
11 #include "RbHingeLimit.h"
12 #include "RbHinge.h"
13 #include "RbRigidBody.h"
14 #include "RbStructure.h"
15 #include "RbDynamixelUSB.h"
16 #include "RbDynamixelUSBServo.h"
17 
18 #define DYN_ID (2)
19 #define DYN_LENGTH (3)
20 #define DYN_INSTRUCTION (4)
21 #define DYN_ERRBIT (4)
22 #define DYN_PARAMETER (5)
23 #define DYN_DEFAULT_BAUDNUMBER (1)
24 
25 namespace RoboticsAnimatSim
26 {
27  namespace Robotics
28  {
29  namespace RobotIOControls
30  {
31  namespace DynamixelUSB
32  {
33 
35 // Construction/Destruction
37 
38 RbDynamixelUSBServo::RbDynamixelUSBServo()
39 {
41  m_iUpdateIdx = 0;
43 }
44 
45 RbDynamixelUSBServo::~RbDynamixelUSBServo()
46 {
47  try
48  {
49  }
50  catch(...)
51  {Std_TraceMsg(0, "Caught Error in desctructor of RbDynamixelUSBServo\r\n", "", -1, false, true);}
52 }
53 
54 void RbDynamixelUSBServo::IOComponentID(int iID)
55 {
56  Std_IsAboveMin((int) 0, iID, true, "ServoID");
57  RobotPartInterface::IOComponentID(iID);
59 }
60 
61 void RbDynamixelUSBServo::UpdateAllParamsCount(int iVal)
62 {
63  Std_IsAboveMin((int) 0, iVal, true, "UpdateAllParamsCount");
65 }
66 
67 int RbDynamixelUSBServo::UpdateAllParamsCount() {return m_iUpdateAllParamsCount;}
68 
69 int RbDynamixelUSBServo::UpdateQueueIndex() {return m_iUpdateQueueIndex;}
70 
71 void RbDynamixelUSBServo::UpdateQueueIndex(int iVal)
72 {
73  Std_IsAboveMin((int) -1, iVal, true, "UpdateQueueIndex", true);
74  m_iUpdateQueueIndex = iVal;
75 }
76 
77 void RbDynamixelUSBServo::SetRegister(unsigned char reg, unsigned char length, unsigned int value)
78 {
79  if(m_lpParentUSB)
80  m_lpParentUSB->SetRegister(m_iServoID, reg, length, value);
81 }
82 
83 int RbDynamixelUSBServo::GetRegister(unsigned char reg, unsigned char length)
84 {
85  if(m_lpParentUSB)
86  return m_lpParentUSB->GetRegister(m_iServoID, reg, length);
87  else
88  return -1;
89 }
90 
91 #pragma region DataAccesMethods
92 
93 float *RbDynamixelUSBServo::GetDataPointer(const std::string &strDataType)
94 {
95  float *fltVal = RbDynamixelServo::GetDataPointer(strDataType);
96  if(fltVal)
97  return fltVal;
98  else
99  return RobotPartInterface::GetDataPointer(strDataType);
100 }
101 
102 bool RbDynamixelUSBServo::SetData(const std::string &strDataType, const std::string &strValue, bool bThrowError)
103 {
104  std::string strType = Std_CheckString(strDataType);
105 
106  if(RobotPartInterface::SetData(strDataType, strValue, false))
107  return true;
108 
109  if(strType == "UPDATEALLPARAMSCOUNT")
110  {
111  UpdateAllParamsCount((int) atoi(strValue.c_str()));
112  return true;
113  }
114 
115  if(strType == "UPDATEQUEUEINDEX")
116  {
117  UpdateQueueIndex((int) atoi(strValue.c_str()));
118  return true;
119  }
120 
121  if(RbDynamixelServo::SetData(strDataType, strValue))
122  return true;
123 
124  //If it was not one of those above then we have a problem.
125  if(bThrowError)
126  THROW_PARAM_ERROR(Al_Err_lInvalidDataType, Al_Err_strInvalidDataType, "Data Type", strDataType);
127 
128  return false;
129 }
130 
131 void RbDynamixelUSBServo::QueryProperties(CStdPtrArray<TypeProperty> &aryProperties)
132 {
133  RobotPartInterface::QueryProperties(aryProperties);
134  RbDynamixelServo::QueryProperties(aryProperties);
135 
136  aryProperties.Add(new TypeProperty("UpdateAllParamsCount", AnimatPropertyType::Integer, AnimatPropertyDirection::Set));
137  aryProperties.Add(new TypeProperty("UpdateQueueIndex", AnimatPropertyType::Integer, AnimatPropertyDirection::Set));
138 }
139 
140 #pragma endregion
141 
142 void RbDynamixelUSBServo::MicroSleep(unsigned int iTime)
143 {
144  if(m_lpSim)
145  m_lpSim->MicroSleep(iTime);
146 }
147 
148 Simulator *RbDynamixelUSBServo::GetSimulator()
149 {
150  return m_lpSim;
151 }
152 
154 {
155  return RbDynamixelServo::QuantizeServoPosition(fltPos);
156 }
157 
159 {
160  return RbDynamixelServo::QuantizeServoVelocity(fltVel);
161 }
162 
163 bool RbDynamixelUSBServo::IncludeInPartsCycle() {return m_bQueryMotorData;}
164 
166 {
167  RobotPartInterface::Initialize();
168 
169  m_lpMotorJoint = dynamic_cast<MotorizedJoint *>(m_lpPart);
170  m_lpParentUSB = dynamic_cast<RbDynamixelUSB *>(m_lpParentIOControl);
171 
172  GetLimitValues();
173  RecalculateParams();
174 }
175 
177 {
179  {
182  InitMotorData();
183 
184  //Set the next goal positions to the current ones.
186 
188  }
189 }
190 
191 void RbDynamixelUSBServo::AddMotorUpdate(int iPos, int iSpeed)
192 {
193  if(!m_lpSim->InSimulation() && m_lpParentUSB)
194  {
195  m_lpParentUSB->m_aryMotorData.Add(new RbDynamixelMotorUpdateData(m_iServoID, iPos, iSpeed));
196  }
197 
198  IOValue(iSpeed);
199 }
200 
201 void RbDynamixelUSBServo::StepIO(int iPartIdx)
202 {
203  unsigned long long lStepStartTick = m_lpSim->GetTimerTick();
204 
205  if(!m_lpSim->InSimulation())
206  {
207  if(m_bQueryMotorData && (m_iUpdateQueueIndex == iPartIdx || m_iUpdateQueueIndex == -1))
208  {
210  ReadAllParams();
211  else
212  ReadKeyParams();
213  }
214 
215  }
216 
217  SetMotorPosVel();
218 
219  unsigned long long lEndStartTick = m_lpSim->GetTimerTick();
220  m_fltStepIODuration = m_lpSim->TimerDiff_m(lStepStartTick, lEndStartTick);
221 
222  m_iUpdateIdx++;
223 }
224 
226 {
227  ShutdownMotor();
228 }
229 
230 void RbDynamixelUSBServo::StepSimulation()
231 {
232  if(!m_lpSim->InSimulation())
233  {
234  RobotPartInterface::StepSimulation();
235  RbDynamixelServo::StepSimulation();
236  }
237 }
238 
240 {
242  RbDynamixelServo::ResetSimulation();
243 }
244 
245 void RbDynamixelUSBServo::Load(StdUtils::CStdXml &oXml)
246 {
247  RobotPartInterface::Load(oXml);
248  RbDynamixelServo::Load(oXml);
249 
250  oXml.IntoElem();
251  UpdateAllParamsCount(oXml.GetChildInt("UpdateAllParamsCount", m_iUpdateAllParamsCount));
252  UpdateQueueIndex(oXml.GetChildInt("UpdateQueueIndex", m_iUpdateQueueIndex));
253  oXml.OutOfElem();
254 }
255 
264 {
265  std::vector<int> aryData;
266  unsigned long long lStart = GetSimulator()->GetTimerTick(), lEnd;
267 
268  if(dxl_read_block(m_iServoID, P_PRESENT_POSITION_L, 8, aryData) && aryData.size() == 8)
269  {
270  m_iPresentPos = dxl_makeword(aryData[0], aryData[1]);
271  m_iPresentVelocity = dxl_makeword(aryData[2], aryData[3]);
272  m_iLoad = dxl_makeword(aryData[4], aryData[5]);
273  m_iVoltage = aryData[6];
274  m_iTemperature = aryData[7];
275 
276  m_fltPresentPos = ConvertPosFPToFloat(m_iPresentPos);
279  m_fltVoltage = m_iVoltage/100.0;
281  }
282 
283  lEnd = GetSimulator()->GetTimerTick();
284  m_fltReadParamTime = GetSimulator()->TimerDiff_m(lStart, lEnd);
285 }
286 
295 {
296  std::vector<int> aryData;
297  unsigned long long lStart = GetSimulator()->GetTimerTick(), lEnd;
298 
299  if(dxl_read_block(m_iServoID, P_PRESENT_POSITION_L, 6, aryData) && aryData.size() == 6)
300  {
301  m_iPresentPos = dxl_makeword(aryData[0], aryData[1]);
302  m_iPresentVelocity = dxl_makeword(aryData[2], aryData[3]);
303  m_iLoad = dxl_makeword(aryData[4], aryData[5]);
304 
305  m_fltPresentPos = ConvertPosFPToFloat(m_iPresentPos);
308  }
309 
310  lEnd = GetSimulator()->GetTimerTick();
311  m_fltReadParamTime = GetSimulator()->TimerDiff_m(lStart, lEnd);
312 }
313 
328 bool RbDynamixelUSBServo::dxl_read_block( int id, int address, int length, std::vector<int> &aryData)
329 {
330  // Make a packet to read a bunch of data at once.
331  dxl_set_txpacket_id(id);
332  dxl_set_txpacket_instruction(INST_READ);
333  dxl_set_txpacket_parameter(0, address);
334  dxl_set_txpacket_parameter(1, length);
335  dxl_set_txpacket_length(4);
336 
337  dxl_txrx_packet();
338 
339  int CommStatus = dxl_get_result();
340 
341  if(!CommStatus)
342  {
343  return false;
344  }
345 
346  aryData.clear();
347  for(int iIdx=0; iIdx<length; iIdx++)
348  {
349  int iParam = dxl_get_rxpacket_parameter(iIdx);
350  aryData.push_back(iParam);
351  }
352 
353  return true;
354 }
355 
365 {
366  if(dxl_get_rxpacket_error(ERRBIT_VOLTAGE) == 1)
367  return "Input voltage error!";
368 
369  if(dxl_get_rxpacket_error(ERRBIT_ANGLE) == 1)
370  return "Angle limit error!\n";
371 
372  if(dxl_get_rxpacket_error(ERRBIT_OVERHEAT) == 1)
373  return "Overheat error!\n";
374 
375  if(dxl_get_rxpacket_error(ERRBIT_RANGE) == 1)
376  return "Out of range error!\n";
377 
378  if(dxl_get_rxpacket_error(ERRBIT_CHECKSUM) == 1)
379  return "Checksum error!\n";
380 
381  if(dxl_get_rxpacket_error(ERRBIT_OVERLOAD) == 1)
382  return "Overload error!\n";
383 
384  if(dxl_get_rxpacket_error(ERRBIT_INSTRUCTION) == 1)
385  return "Instruction code error!\n";
386 
387  return "Unknown error";
388 }
389 
390 std::string RbDynamixelUSBServo::GetCommStatus(int CommStatus)
391 {
392  switch(CommStatus)
393  {
394  case COMM_TXFAIL:
395  return "COMM_TXFAIL: Failed transmit instruction packet!";
396  break;
397 
398  case COMM_TXERROR:
399  return "COMM_TXERROR: Incorrect instruction packet!";
400  break;
401 
402  case COMM_RXFAIL:
403  return "COMM_RXFAIL: Failed get status packet from device!";
404  break;
405 
406  case COMM_RXWAITING:
407  return "COMM_RXWAITING: Now recieving status packet!";
408  break;
409 
410  case COMM_RXTIMEOUT:
411  return "COMM_RXTIMEOUT: There is no status packet!";
412  break;
413 
414  case COMM_RXCORRUPT:
415  return "COMM_RXCORRUPT: Incorrect status packet!";
416  break;
417 
418  default:
419  return "This is unknown error code!";
420  break;
421  }
422 }
423 
424  } //DynamixelUSB
425  } //RobotIOControls
426  } // Robotics
427 } //RoboticsAnimatSim
428 
virtual float ConvertFPVelocity(int iVel)
Gets the floating point value of the servo actual velocity. The fixed point value is retrieved from t...
virtual bool InSimulation()
Used to determine if we are running in a simulation, or in a real control mode.
Definition: Simulator.cpp:1673
virtual void ReadAllParams()
Reads all major data parameters from the servo in one read packet. This include present position...
virtual void ShutdownIO()
This method is called just before the IO thread is closed down. It gives the IO objects a chance to d...
Simulator * m_lpSim
The pointer to a Simulation.
Definition: AnimatBase.h:43
virtual float QuantizeServoPosition(float fltPos)
If this is a servo controller interface then it will take a continuous positon and return back a vali...
virtual bool IntoElem()
Goes into the next element where the cursor is located.
Definition: StdXml.cpp:42
int m_iVoltage
The current voltage that was last read in for this servo.
virtual float ConvertFPLoad(int iLoad)
Gets the floating point value of the servo load. The fixed point value is retrieved from the servo an...
int m_iLastGoalVelocity
Keeps track of the last servo goal velocity that we set.
int m_iServoID
ID used for communications with this servo.
int m_iNextGoalVelocity
This is the goal velocity that you would like to use in the next time step.
int m_iLastGoalPos
Keeps track of the last servo goal position that we set.
virtual int GetChildInt(std::string strElementName)
Gets an integer value from the element with the specified name.
Definition: StdXml.cpp:456
bool Std_IsAboveMin(int iMinVal, int iVal, bool bThrowError, std::string strParamName, bool bInclusiveLimit)
Tests if a number is above a minimum value.
float m_fltPresentPos
The current position that was last read in for this servo.
int m_iUpdateIdx
Keeps track of the number of update loops that have occurred since we last updated all params...
int m_iTemperature
The current temperature that was last read in for this servo.
virtual int ServoID()
Gets the servo ID being used for communications.
int m_iPresentPos
The current position that was last read in for this servo.
virtual float * GetDataPointer(const std::string &strDataType)
Returns a float pointer to a data item of interest in this object.
virtual void ShutdownMotor()
Shuts the motor down cleanly and ensures that it is not continuing to move after processing has stopp...
Declares the vortex structure class.
virtual void StepIO(int iPartIdx)
This method is used to send/recieve the actual IO. This will often be in a seperate thread than the S...
float m_fltReadParamTime
The time taken to read the params of this motor for the current step.
int m_iNextGoalPos
This is the goal position that you would like to use in the next time step.
Declares the vortex hinge class.
A standard xml manipulation class.
Definition: StdXml.h:19
int m_iLoad
The current load that was last read in for this servo.
virtual void ReadKeyParams()
Reads only the key data parameters from the servo in one read packet. This include present position a...
float m_fltPresentVelocity
The current velocity that was last read in for this servo.
MotorizedJoint * m_lpMotorJoint
Pointer to an associated motorized joint.
float m_fltLoad
The current load that was last read in for this servo.
void Std_TraceMsg(const int iLevel, std::string strMessage, std::string strSourceFile, int iSourceLine, bool bLogToFile, bool bPrintHeader)
Traces a message to the debugger window.
virtual void ResetSimulation()
Resets the simulation back to time 0.
virtual void SetMaxSimPos(float fltVal)
Sets the maximum position that the simulation will allow for this joint in radians.
virtual void SetMinSimPos(float fltVal)
Sets the minimum position that the simulation will allow for this joint in radians.
virtual bool dxl_read_block(int id, int address, int length, std::vector< int > &aryData)
Reads an entire block of data from a dynamixel servo. This is used to allow us to read back a number ...
virtual bool OutOfElem()
Goes out of the element where the cursor is located.
Definition: StdXml.cpp:56
float m_fltVoltage
The current voltage that was last read in for this servo.
std::string Std_CheckString(std::string strVal)
Converts a string to upper case and trims it.
virtual std::string GetErrorCode()
Checks the error code and returns an associated error message.
virtual void InitMotorData()
Initializes the internal data on position and velocity from the actual motor.
virtual void SetupIO()
This method is called after all connections to whatever control board have been made. It is meant to be used to setup connection information specific to this part. For example, We connect to a Firmata microcontroller like an Arduino, and then do a setup that could take some time. We should not attempt to setup any of the pins until after the board itself has been setup. After that we need to loop through and setup all the parts. That is what this method is for.
virtual bool SetData(const std::string &strDataType, const std::string &strValue, bool bThrowError=true)
Set a variable based on a string data type name.
virtual float QuantizeServoVelocity(float fltVel)
If this is a servo controller interface then it will take a continuous velocity and return back a val...
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
float m_fltTemperature
The current temperature that was last read in for this servo.
int m_iPresentVelocity
The current velocity that was last read in for this servo.