NTRT Simulator  v1.1
 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_config(config),
107  tgSpringCableActuator(muscle, tags, config)
108 {
109  constructorAux();
110 
111  // Postcondition
112  assert(invariant());
113 }
114 
116 {
117  //std::cout << "deleting kinematic spring cable" << std::endl;
118  // Should have already torn down.
119 }
120 
122 {
123  // This needs to be called here in case the controller needs to cast
124  notifySetup();
125  tgModel::setup(world);
126 }
127 
129 {
130  // Do not notify teardown. The controller has already been deleted.
132 }
133 
135 {
136 #ifndef BT_NO_PROFILE
137  BT_PROFILE("tgKinematicActuator::step");
138 #endif //BT_NO_PROFILE
139  if (dt <= 0.0)
140  {
141  throw std::invalid_argument("dt is not positive.");
142  }
143  else
144  {
145  // Want to update any controls before applying forces
146  notifyStep(dt);
147  // Adjust rest length based on muscle dynamics
149  m_springCable->step(dt);
150  logHistory();
151  tgModel::step(dt);
152  }
153 
154  // Reset and wait for next control input
155  m_desiredTorque = 0.0;
156 }
157 
159 {
160 #ifndef BT_NO_PROFILE
161  BT_PROFILE("tgKinematicActuator::onVisit");
162 #endif //BT_NO_PROFILE
163  r.render(*this);
164 }
165 
166 void tgKinematicActuator::logHistory()
167 {
169 
170  if (m_config.hist)
171  {
177  }
178 }
179 
181 {
182  return m_motorVel * m_config.radius;
183 }
184 
186 {
187  double tension = getTension();
188  double appliedTorque = getAppliedTorque(m_desiredTorque);
189  // motorVel will always cause opposite acc, but tension can only
190  // cause lengthening (positive Acc)
191  m_motorAcc = (appliedTorque - m_config.motorFriction * m_motorVel
192  + tension * m_config.radius) / m_config.motorInertia;
193 
194  if (!m_config.backdrivable && m_motorAcc * appliedTorque <= 0.0)
195  {
196  // Stop undesired lengthing if the motor is not backdrivable
197  m_motorVel = m_motorVel + m_motorAcc * dt > 0.0 ? 0.0 : m_motorVel + m_motorAcc * dt;
198  }
199  else
200  {
201  m_motorVel += m_motorAcc * dt;
202  }
203 
204  // semi-implicit Euler integration
205  m_restLength += m_motorVel * dt;
206 
208 
209  m_restLength =
210  (m_restLength > m_config.minRestLength) ? m_restLength : m_config.minRestLength;
211 
213 }
214 
215 double tgKinematicActuator::getAppliedTorque(double desiredTorque) const
216 {
217  double maxTorque = m_config.maxTens * m_config.radius *
218  (1.0 - m_config.radius * abs(m_motorVel) / m_config.targetVelocity);
219 
220  maxTorque = maxTorque < 0.0 ? 0.0 : maxTorque;
221 
222  return abs(desiredTorque) < maxTorque ? desiredTorque :
223  desiredTorque / abs(desiredTorque) * maxTorque;
224 }
225 
227 {
228  m_desiredTorque = input;
229 }
230 
232 {
233  return *m_pHistory;
234 }
235 
236 bool tgKinematicActuator::invariant() const
237 {
238  return
239  (m_springCable != NULL) &&
240  (m_pHistory != NULL) &&
241  (m_config.targetVelocity >= 0.0) &&
242  (m_config.minActualLength >= 0.0);
243 }
virtual void setRestLength(const double newRestLength)
virtual void teardown()
Definition: tgModel.cpp:68
virtual void setup(tgWorld &world)
Definition: tgModel.cpp:57
virtual const double getVelocity() const
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 getTension() const =0
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