5 #ifndef SPIDAR_SYSTEM_HPP 6 #define SPIDAR_SYSTEM_HPP 27 typedef typename TraitsType::SpecType
SpecType;
33 typedef typename TraitsType::PoseType
PoseType;
48 double deltaTime(
void)
const {
return timer_.avgDeltaTime(); }
51 ValueType
gripRadius(
void)
const {
return estimator_.gripRadius(); }
78 void gripPose(VectorType& position, QuaternionType& rotation,
79 VectorType& velocity, VectorType& angularVelocity)
const;
81 bool setForce(
const VectorType& force, ValueType forceK, ValueType forceB,
82 const VectorType& torque, ValueType torqueK, ValueType torqueB,
83 bool lerp,
bool cascade =
false);
94 static void threadFunc(
void* param);
96 void outputLog(
const std::string& filename);
99 ControllerType controller_;
102 PoseEstimationType estimator_;
103 ForceDecompositionType decomposer_;
105 DataLoggerType dataLogger_;
111 bool cascadeControl_;
118 ValueType cascadeGain_;
119 ValueType cascadeSpringK_;
124 uint16_t cascadeRatioKB_;
128 uint16_t velocityFilterGain_;
130 uint16_t forceFilterGain_;
134 VectorType targetForce_;
135 VectorType targetTorque_;
137 VectorType resultantForce_;
138 VectorType resultantTorque_;
148 initialized_(false), haptics_(false), cascadeControl_(false), cascadeGain_(1), cascadeSpringK_(0), cascadeRatioKB_(0)
179 if (!controller_.initialize(spec.serialNumber))
return false;
182 if (!estimator_.initialize(spec, controller_.controlFrequency()))
return false;
183 if (!decomposer_.initialize(spec))
return false;
188 if (spec.speedConstant[i] == 0)
190 velocityGain_[i] = 0;
194 double dutyPerVoltage = controller_.maxPulseWidth() / spec.terminalVoltage[i];
195 double pulsePerSecond = spec.encoderResolution[i] * spec.speedConstant[i] / 60;
197 double value = controller_.cascadeFrequency() * dutyPerVoltage / pulsePerSecond;
199 velocityGain_[i] =
static_cast<int16_t
>(-value * spec.encoderDirection[i]);
203 velocityFilterGain_ =
static_cast<uint16_t
>(spec.minorLoopVelocityFilterGain);
208 double pulseWidthLimit = decomposer_.tensionToDuty(i) * decomposer_.maxTension(i) * controller_.maxPulseWidth();
209 pulseWidthLimit_[i] =
static_cast<uint16_t
>(pulseWidthLimit);
213 const double PI = 3.14159265358979323846;
217 double lengthPerCount = spec.pulleyRadius[i] * 2.0 * PI / spec.encoderResolution[i];
219 double maxCurrent = spec.terminalVoltage[i] / spec.terminalResistance[i];
221 double maxTension = spec.torqueConstant[i] / spec.pulleyRadius[i] * maxCurrent;
223 double pulseWidthPerNewton = controller_.maxPulseWidth() / maxTension;
225 springKToPulseRatio_[i] =
static_cast<ValueType>(pulseWidthPerNewton * lengthPerCount * spec.encoderDirection[i]);
228 forceFilterGain_ =
static_cast<uint16_t
>(spec.minorLoopForceFilterGain);
243 if (!initialized_)
return true;
249 if (!controller_.terminate())
return false;
251 initialized_ =
false;
289 if (!initialized_ || thread_)
return;
293 thread_ =
new ThreadType(threadFunc, static_cast<void*>(
this));
304 if (!initialized_ || !thread_)
return;
314 outputLog(
"C:/SPIDAR/log.txt");
324 if (!initialized_ || kill_)
return;
326 clearEncoder_ =
true;
343 if (!initialized_)
return;
345 position = estimator_.pose().position;
346 rotation = estimator_.pose().rotation;
347 velocity = estimator_.pose().velocity;
348 angularVelocity = estimator_.pose().angularVelocity;
369 if (!initialized_)
return false;
371 model_.setParameter(forceK, forceB, torqueK, torqueB);
372 model_.setOrigin(estimator_.pose(), force, torque, lerp);
374 cascadeControl_ = cascade;
375 cascadeSpringK_ = forceK;
377 if (forceB == 0) cascadeRatioKB_ = 0;
378 else cascadeRatioKB_ =
static_cast<uint16_t
>(forceK / forceB);
392 if (!initialized_)
return;
394 for (
size_t i = 0; i <
MOTOR_COUNT; ++i) count[i] = encoderCount_[i];
406 if (!initialized_)
return 0;
408 return controller_.gpioValue();
428 size_t forceCount = 0;
430 const size_t collisionThreshold =
static_cast<const size_t>(1000 * decomposer_.maxDuration());
432 const size_t maxCollisionCount = collisionThreshold + 1000;
438 controller_.writePulseWidthLimit(pulseWidthLimit_);
439 controller_.writeVelocityGain(velocityGain_);
440 controller_.writeVelocityFilterGain(velocityFilterGain_);
441 controller_.writeForceFilterGain(forceFilterGain_);
444 for (
size_t i = 0; i <
MOTOR_COUNT; ++i) encoderCount_[i] = 0;
448 model_.setFrequency(static_cast<ValueType>(controller_.controlFrequency()), 60);
452 clearEncoder_ =
true;
453 size_t clearEncoderCount = 0;
456 controller_.enableMotorControl();
459 timer_.initialize(controller_.controlFrequency());
467 resultantForce_ = targetForce_ = force;
468 resultantTorque_ = targetTorque_ = torque;
475 controller_.clearEncoderCount();
476 controller_.readEncoderCount(count);
477 clearEncoder_ =
false;
481 if (clearEncoderCount < 10)
483 controller_.readEncoderCount(count);
488 clearEncoderCount = 0;
489 controller_.readEncoderCount(count);
490 estimator_.calibrate(count);
499 controller_.readEncoderCount(count);
501 for (
size_t i = 0; i <
MOTOR_COUNT; ++i) encoderCount_[i] = count[i];
504 estimator_.estimate(count);
511 model_.calcModel(estimator_.pose(), force, torque);
513 if (force.norm() != 0 || torque.norm() != 0)
516 if (forceCount < maxCollisionCount) ++forceCount;
518 if (forceCount > collisionThreshold)
520 float temp = 0.001f * (forceCount - collisionThreshold);
522 force *= (1.0f - temp);
523 torque *= (1.0f - temp);
532 targetForce_ = force;
533 targetTorque_ = torque;
539 if (haptics_ && forceCount != 0) decomposer_.decompose(estimator_.wireVector(), force, torque);
543 resultantForce_ = decomposer_.force();
544 resultantTorque_ = decomposer_.torque();
548 if (!haptics_ || forceCount == 0)
552 double temp = (decomposer_.minTension(i) - decomposer_.springTension(i)) * decomposer_.tensionToDuty(i);
560 double temp = (decomposer_.wireTension(i) - decomposer_.springTension(i)) * decomposer_.tensionToDuty(i);
566 if (!cascadeControl_)
568 controller_.writeDutyCycle(duty);
576 springK[i] =
static_cast<int32_t
>(springKToPulseRatio_[i] * cascadeGain_ * cascadeSpringK_);
579 controller_.writeDutyCycle(duty, springK, cascadeRatioKB_);
583 if (dataLogger_.started())
586 log.position = estimator_.pose().position;
587 log.velocity = estimator_.pose().velocity;
589 log.targetForce = targetForce_;
590 log.resultantForce = resultantForce_;
593 log.rotation = estimator_.pose().rotation;
594 log.angularVelocity = estimator_.pose().angularVelocity;
595 log.targetTorque = targetTorque_;
596 log.resultantTorque = resultantTorque_;
600 log.tension[i] = decomposer_.wireTension(i);
602 dataLogger_.add(log);
610 for (
size_t i = 0; i<
MOTOR_COUNT; ++i) duty[i] = 0;
612 controller_.writeDutyCycle(duty);
615 controller_.disableMotorControl();
649 if (dataLogger_.started()) dataLogger_.output(filename);
655 #endif // SPIDAR_SYSTEM_HPP void gripPose(VectorType &position, QuaternionType &rotation, VectorType &velocity, VectorType &angularVelocity) const
グリップの姿勢を取得します.
void startLog(void)
ログの記録を開始します.
TraitsType::ThreadType ThreadType
スレッドの型
TraitsType::PoseType PoseType
グリップ姿勢の型
void encoderCount(int32_t(&count)[MOTOR_COUNT]) const
エンコーダ値を取得します.
double deltaTime(void) const
更新時間間隔を取得します.
bool terminate(void)
システムを終了します.
TraitsType::ValueType ValueType
値の型
ValueType cascadeGain(void) const
カスケード制御のマイナーループのゲインを取得します.
void calibrate(void)
グリップ姿勢のキャリブレーションを行います.
TraitsType::QuaternionType QuaternionType
四元数の型
VectorType resultantForce(void) const
並進力の出力値を取得します.
VectorType targetForce(void) const
並進力の目標値を取得します.
~SpidarSystem(void)
デストラクタ.
static const size_t MOTOR_COUNT
モータの数(=ワイヤの本数)
VectorType targetTorque(void) const
回転力の目標値を取得します.
void setHaptics(bool enable)
力提示のON/OFFを設定します.
TraitsType::PoseEstimationType PoseEstimationType
姿勢推定オブジェクトの型
uint32_t gpioValue(void) const
GPIOの値を取得します.
TraitsType::TimerType TimerType
タイマーの型
TraitsType::DataLoggerType DataLoggerType
データロガーの型
TraitsType::VectorType VectorType
ベクトルの型
SpidarSystem(void)
コンストラクタ.
ValueType gripRadius(void) const
グリップ半径を取得します.
TraitsType::ControllerType ControllerType
コントローラの型
void start(void)
システムの動作を開始します.
bool initialize(const SpecType &spec)
システムを初期化します.
VectorType resultantTorque(void) const
回転力の出力値を取得します.
TraitsType::ForceDecompositionType ForceDecompositionType
張力分配オブジェクトの型
bool setForce(const VectorType &force, ValueType forceK, ValueType forceB, const VectorType &torque, ValueType torqueK, ValueType torqueB, bool lerp, bool cascade=false)
提示力の目標値を設定します.
TraitsType::LogDataType LogDataType
ログデータの型
TraitsType::ModelType ModelType
バネダンパモデルの型
TraitsType::SpecType SpecType
デバイス情報の型
void setCascadeGain(ValueType gain)
カスケード制御用ゲインを設定します.
void stop(void)
システムの動作を停止します.