Resurgence (PY2022)
Codebase for the Husky Robotics 2021-2022 rover Resurgence
Loading...
Searching...
No Matches
JacobianVelController.h
1#pragma once
2
3#include "../filters/StateSpaceUtil.h"
4#include "../navtypes.h"
5#include "../utils/math.h"
6#include "../utils/time.h"
7#include "../world_interface/data.h"
8
9#include <functional>
10#include <loguru.hpp>
11#include <optional>
12
13#include <Eigen/Core>
14
23template <int outputDim, int inputDim>
25public:
35 const std::function<navtypes::Vectord<outputDim>(const navtypes::Vectord<inputDim>&)>&
36 kinematicsFunc,
37 const std::function<navtypes::Matrixd<outputDim, inputDim>(
38 const navtypes::Vectord<inputDim>&)>& jacobianFunc)
39 : kinematicsFunc(kinematicsFunc),
40 jacobianFunc(jacobianFunc ? jacobianFunc
41 : std::bind(util::numericalJacobian, kinematicsFunc,
42 std::placeholders::_1, outputDim)) {
43 CHECK_NOTNULL_F(this->kinematicsFunc);
44 CHECK_NOTNULL_F(this->jacobianFunc);
45 }
46
55 navtypes::Vectord<inputDim> getCommand(robot::types::datatime_t currTime,
56 const navtypes::Vectord<inputDim>& currPos) {
57 double unused;
58 return getCommand(currTime, currPos, unused);
59 }
60
72 navtypes::Vectord<inputDim> getCommand(robot::types::datatime_t currTime,
73 const navtypes::Vectord<inputDim>& currPos,
74 double& cosineSim) {
75 if (!controllerState) {
76 return currPos;
77 }
78
79 // The jacobian of the kinematics function represents a linearization of the kinematics
80 // around the current position. We then use this approximation to find the position
81 // delta in the input space that yields the required position delta in the output space
82 // This is similar to JacobianController, but the command position is calculated
83 // from a velocity instead of a profile.
84
85 navtypes::Vectord<outputDim> currPosOutput = kinematicsFunc(currPos);
86 state_t state = controllerState.value();
87 double dt = util::durationToSec(currTime - state.timestamp);
88 navtypes::Vectord<outputDim> lastTarget = state.lastTarget.value_or(currPosOutput);
89 navtypes::Vectord<outputDim> currTarget = lastTarget + dt * state.targetVel;
90 navtypes::Vectord<outputDim> outputPosDiff = currTarget - currPosOutput;
91 navtypes::Matrixd<outputDim, inputDim> jacobian = jacobianFunc(currPos);
92 navtypes::Vectord<inputDim> inputPosDiff =
93 jacobian.colPivHouseholderQr().solve(outputPosDiff);
94
95 // the cosine similarity of the actual and required position deltas in the output space
96 // is metric of how much the kinematics allows the commanded movement.
97 navtypes::Vectord<outputDim> trueOutputPosDiff = jacobian * inputPosDiff;
98 cosineSim = outputPosDiff.dot(trueOutputPosDiff) /
99 (outputPosDiff.norm() * trueOutputPosDiff.norm());
100
101 state_t newState = {
102 .timestamp = currTime, .targetVel = state.targetVel, .lastTarget = currTarget};
103 controllerState = newState;
104
105 return currPos + inputPosDiff;
106 }
107
115 const navtypes::Vectord<outputDim>& targetVel) {
116 state_t state = {.timestamp = currTime, .targetVel = targetVel, .lastTarget = {}};
117 this->controllerState = state;
118 }
119
125 bool hasTarget() {
126 return controllerState.has_value();
127 }
128
132 void reset() {
133 controllerState.reset();
134 }
135
136private:
137 struct state_t {
138 robot::types::datatime_t timestamp;
139 navtypes::Vectord<outputDim> targetVel;
140 std::optional<navtypes::Vectord<outputDim>> lastTarget;
141 };
142
143 std::function<navtypes::Vectord<outputDim>(const navtypes::Vectord<inputDim>&)>
144 kinematicsFunc;
145 std::function<navtypes::Matrixd<outputDim, inputDim>(const navtypes::Vectord<inputDim>&)>
146 jacobianFunc;
147 std::optional<state_t> controllerState;
148};
_Bind_helper< __is_socketlike< _Func >::value, _Func, _BoundArgs... >::type bind(_Func &&__f, _BoundArgs &&... __args)
navtypes::Vectord< inputDim > getCommand(robot::types::datatime_t currTime, const navtypes::Vectord< inputDim > &currPos, double &cosineSim)
Get the current target position.
Definition JacobianVelController.h:72
navtypes::Vectord< inputDim > getCommand(robot::types::datatime_t currTime, const navtypes::Vectord< inputDim > &currPos)
Get the current target position.
Definition JacobianVelController.h:55
JacobianVelController(const std::function< navtypes::Vectord< outputDim >(const navtypes::Vectord< inputDim > &)> &kinematicsFunc, const std::function< navtypes::Matrixd< outputDim, inputDim >(const navtypes::Vectord< inputDim > &)> &jacobianFunc)
Construct a new controller.
Definition JacobianVelController.h:34
void setTarget(robot::types::datatime_t currTime, const navtypes::Vectord< outputDim > &targetVel)
Set the target velocity.
Definition JacobianVelController.h:114
bool hasTarget()
Check if a target velocity has been set.
Definition JacobianVelController.h:125
void reset()
Reset the controller, unsetting the current command.
Definition JacobianVelController.h:132
std::chrono::time_point< dataclock > datatime_t
A point in time as measured by dataclock.
Definition data.h:31
A collection of utility functions and classes with common use-cases.
Definition SwerveController.cpp:145
double durationToSec(std::chrono::duration< Rep, Period > dur)
Convert a duration to seconds, as a double.
Definition time.h:18