NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
tgKinematicActuator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
26 // This Module
27 #include "tgKinematicActuator.h"
28 // The NTRT Core libary
30 #include "core/tgModelVisitor.h"
31 #include "core/tgWorld.h"
32 // The Bullet Physics Library
33 #include "LinearMath/btQuickprof.h"
34 
35 // The C++ Standard Library
36 #include <cmath>
37 #include <deque> // For history
38 #include <iostream>
39 #include <stdexcept>
40 
41 using namespace std;
42 
43 tgKinematicActuator::Config::Config(double s,
44  double d,
45  double p,
46  double rad,
47  double moFric,
48  double moInert,
49  bool back,
50  bool h,
51  double mf,
52  double tVel,
53  double mnAL,
54  double mnRL,
55  double rot) :
56  tgSpringCableActuator::Config::Config(s, d, p, h,
57  mf, tVel, mnAL, mnRL, rot),
58  radius(rad),
59  motorFriction(moFric),
60  motorInertia(moInert),
61  backdrivable(back),
62  maxOmega(tVel / rad),
63  maxTorque(mf / rad)
64 {
65  if (rad <= 0.0)
66  {
67  throw std::invalid_argument("Radius is non-positive");
68  }
69  else if (moFric < 0.0)
70  {
71  throw std::invalid_argument("Motor friction is negative.");
72  }
73  else if (moInert <= 0.0)
74  {
75  throw std::invalid_argument("Motor inertia is non-positive");
76  }
77 }
78 
79 void tgKinematicActuator::constructorAux()
80 {
81  // Precondition
82  assert(m_pHistory != NULL);
83  prevVel = 0.0;
84  if (m_springCable == NULL)
85  {
86  throw std::invalid_argument("Pointer to tgBulletSpringCable is NULL.");
87  }
88  else if (m_config.targetVelocity < 0.0)
89  {
90  throw std::invalid_argument("Target velocity is negative.");
91  }
92  else if (m_config.minActualLength < 0.0)
93  {
94  throw std::invalid_argument("Minimum length is negative.");
95  }
96  else
97  {
98  logHistory();
99  }
100 }
102  const tgTags& tags,
103  tgKinematicActuator::Config& config) :
104  m_motorVel(0.0),
105  m_motorAcc(0.0),
106  m_appliedTorque(0.0),
107  m_config(config),
108  tgSpringCableActuator(muscle, tags, config)
109 {
110  constructorAux();
111 
112  // Postcondition
113  assert(invariant());
114 }
115 
117 {
118  //std::cout << "deleting kinematic spring cable" << std::endl;
119  // Should have already torn down.
120 }
121 
123 {
124  // This needs to be called here in case the controller needs to cast
125  notifySetup();
126  tgModel::setup(world);
127 }
128 
130 {
131  // Do not notify teardown. The controller has already been deleted.
133 }
134 
136 {
137 #ifndef BT_NO_PROFILE
138  BT_PROFILE("tgKinematicActuator::step");
139 #endif //BT_NO_PROFILE
140  if (dt <= 0.0)
141  {
142  throw std::invalid_argument("dt is not positive.");
143  }
144  else
145  {
146  // Want to update any controls before applying forces
147  notifyStep(dt);
148  // Adjust rest length based on muscle dynamics
150  m_springCable->step(dt);
151  logHistory();
152  tgModel::step(dt);
153  }
154 
155  // Reset and wait for next control input
156  m_desiredTorque = 0.0;
157 }
158 
160 {
161 #ifndef BT_NO_PROFILE
162  BT_PROFILE("tgKinematicActuator::onVisit");
163 #endif //BT_NO_PROFILE
164  r.render(*this);
165 }
166 
167 void tgKinematicActuator::logHistory()
168 {
170 
171  if (m_config.hist)
172  {
174  m_pHistory->lastVelocities.push_back(m_motorVel);
177  m_pHistory->tensionHistory.push_back(m_appliedTorque);
178  }
179 }
180 
182 {
183  return m_motorVel * m_config.radius;
184 }
185 
187 {
188  double tension = getTension();
189  m_appliedTorque = getAppliedTorque(m_desiredTorque);
190  // motorVel will always cause opposite acc, but tension can only
191  // cause lengthening (positive Acc)
192  m_motorAcc = (m_appliedTorque - m_config.motorFriction * m_motorVel
193  + tension * m_config.radius) / m_config.motorInertia;
194 
195  if (!m_config.backdrivable && m_motorAcc * m_appliedTorque <= 0.0)
196  {
197  // Stop undesired lengthing if the motor is not backdrivable
198  m_motorVel = m_motorVel + m_motorAcc * dt > 0.0 ? 0.0 : m_motorVel + m_motorAcc * dt;
199  }
200  else
201  {
202  m_motorVel += m_motorAcc * dt;
203  }
204 
205  // semi-implicit Euler integration
206  m_restLength += m_config.radius * m_motorVel * dt;
207 
209 
210  m_restLength =
211  (m_restLength > m_config.minRestLength) ? m_restLength : m_config.minRestLength;
212 
214 }
215 
216 double tgKinematicActuator::getAppliedTorque(double desiredTorque) const
217 {
218  double maxTorque = m_config.maxTens * m_config.radius *
219  (1.0 - m_config.radius * abs(m_motorVel) / m_config.targetVelocity);
220 
221  maxTorque = maxTorque < 0.0 ? 0.0 : maxTorque;
222 
223  return abs(desiredTorque) < maxTorque ? desiredTorque :
224  desiredTorque / abs(desiredTorque) * maxTorque;
225 }
226 
228 {
229  m_desiredTorque = input;
230 }
231 
233 {
234  return *m_pHistory;
235 }
236 
237 bool tgKinematicActuator::invariant() const
238 {
239  return
240  (m_springCable != NULL) &&
241  (m_pHistory != NULL) &&
242  (m_config.targetVelocity >= 0.0) &&
243  (m_config.minActualLength >= 0.0);
244 }
virtual void setRestLength(const double newRestLength)
virtual void teardown()
Definition: tgModel.cpp:68
virtual void setup(tgWorld &world)
Definition: tgModel.cpp:57
virtual void setup(tgWorld &world)
virtual double getAppliedTorque(double desiredTorque) const
virtual const double getTension() const
virtual void step(double dt)
Definition: tgModel.cpp:84
virtual void setControlInput(double input)
virtual const double getRestLength() const
virtual void render(const tgRod &rod) const
Contains the definition of interface class tgModelVisitor.
tgKinematicActuator(tgBulletSpringCable *muscle, const tgTags &tags, tgKinematicActuator::Config &config)
virtual void integrateRestLength(double dt)
Contains the definition of class tgWorld $Id$.
virtual const double getVelocity() const
virtual const double getDamping() const
Contains the definition of class tgKinematicActuator.
Definitions of classes tgBulletSpringCable $Id$.
virtual void step(double dt)
virtual const double getActualLength() const =0
virtual const tgSpringCableActuator::SpringCableActuatorHistory & getHistory() const
virtual void onVisit(const tgModelVisitor &r) const
SpringCableActuatorHistory *const m_pHistory
virtual void step(double dt)=0
Definition: tgTags.h:44