implement experimental ccdik
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include "StateMachine.h"
|
#include "StateMachine.h"
|
||||||
#include "ArmSegment.h"
|
#include "ArmSegment.h"
|
||||||
#include "Scene_CCDIK.h"
|
#include "Scene_CCDIK.h"
|
||||||
|
#include "Scene_JointSpaceControl.h"
|
||||||
|
|
||||||
MainLoop::MainLoop() noexcept :
|
MainLoop::MainLoop() noexcept :
|
||||||
arm(L"COM4")
|
arm(L"COM4")
|
||||||
@@ -33,7 +34,8 @@ void MainLoop::run()
|
|||||||
static std::chrono::steady_clock::time_point lastBegin =
|
static std::chrono::steady_clock::time_point lastBegin =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
Scene_CCDIK sceneCCDIK(arm);
|
Scene_CCDIK scene(arm);
|
||||||
|
//Scene_JointSpaceControl scene(arm);
|
||||||
|
|
||||||
while (isRunning)
|
while (isRunning)
|
||||||
{
|
{
|
||||||
@@ -52,7 +54,7 @@ void MainLoop::run()
|
|||||||
case StateMachine::STATE::IDLING:
|
case StateMachine::STATE::IDLING:
|
||||||
case StateMachine::STATE::MOVING: {
|
case StateMachine::STATE::MOVING: {
|
||||||
// HERE SCENE UPDATE
|
// HERE SCENE UPDATE
|
||||||
sceneCCDIK.update(frametime);
|
scene.update(frametime);
|
||||||
|
|
||||||
// Unset MOVING to IDLING state if no arm is moving
|
// Unset MOVING to IDLING state if no arm is moving
|
||||||
if (StateMachine::getInstance().getState() == StateMachine::STATE::MOVING && !arm.isMoving()) {
|
if (StateMachine::getInstance().getState() == StateMachine::STATE::MOVING && !arm.isMoving()) {
|
||||||
|
|||||||
+176
-13
@@ -1,5 +1,9 @@
|
|||||||
#include "Scene_CCDIK.h"
|
#include "Scene_CCDIK.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
Scene_CCDIK::Scene_CCDIK(Arm& arm) :
|
Scene_CCDIK::Scene_CCDIK(Arm& arm) :
|
||||||
arm{ arm },
|
arm{ arm },
|
||||||
@@ -14,14 +18,8 @@ Scene_CCDIK::Scene_CCDIK(Arm& arm) :
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
leftVKB(L" VKBsim Gladiator EVO L "),
|
leftVKB(L" VKBsim Gladiator EVO L "),
|
||||||
cursor3d(0,0,0)
|
cursor3d(0, 300, 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!arm.assumeHomePoseImmediate()) {
|
|
||||||
std::cerr << "Unable to move arm to home!" << std::endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!leftVKB.connect()) {
|
if (!leftVKB.connect()) {
|
||||||
std::cerr << "Unable to connect to left VKB controller!" << std::endl;
|
std::cerr << "Unable to connect to left VKB controller!" << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -32,20 +30,185 @@ void Scene_CCDIK::update(double frametime)
|
|||||||
{
|
{
|
||||||
vkbi = leftVKB.get();
|
vkbi = leftVKB.get();
|
||||||
|
|
||||||
constexpr double speed = 5000;
|
update3dCursorSquare(frametime);
|
||||||
VkbInputs vkbi = leftVKB.get();
|
//update3dCursorByVKBI(frametime);
|
||||||
|
performCcdIK(cursor3d);
|
||||||
|
|
||||||
update3dCursor(frametime);
|
const double error = (cursor3d - arm.getEndEffectorJoint().getTargetedGlobalEndpoint()).magnitude();
|
||||||
|
//std::cout
|
||||||
|
// << std::fixed
|
||||||
|
// << std::setprecision(1)
|
||||||
|
// << std::noshowpos
|
||||||
|
// << "Cursor: "
|
||||||
|
// //<< arm.getEndEffectorJoint().getTargetedGlobalEndpoint()
|
||||||
|
// << cursor3d
|
||||||
|
// << std::endl;
|
||||||
|
|
||||||
arm.update(frametime);
|
arm.update(frametime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene_CCDIK::update3dCursor(double frametime)
|
void Scene_CCDIK::update3dCursorByVKBI(double frametime)
|
||||||
{
|
{
|
||||||
constexpr double cursorSpeed = 1.0;
|
constexpr double cursorSpeed = 50000.0;
|
||||||
cursor3d += Vector3d(
|
cursor3d += Vector3d(
|
||||||
vkbi.roll * cursorSpeed * frametime,
|
vkbi.roll * cursorSpeed * frametime,
|
||||||
vkbi.yaw * cursorSpeed * frametime,
|
vkbi.yaw * cursorSpeed * frametime,
|
||||||
-vkbi.pitch * cursorSpeed * frametime
|
vkbi.pitch * cursorSpeed * frametime
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene_CCDIK::update3dCursorSquare(double frametime)
|
||||||
|
{
|
||||||
|
static double t = 0.0;
|
||||||
|
t += frametime;
|
||||||
|
|
||||||
|
const double centerX = 0.0;
|
||||||
|
const double centerY = 200.0;
|
||||||
|
const double zPlane = 100.0;
|
||||||
|
|
||||||
|
const double halfWidth = 150.0; // X range: [-150, +150]
|
||||||
|
const double halfHeight = 100.0; // Y range: [100, 300] SAFE
|
||||||
|
|
||||||
|
const double speed = 20.0;
|
||||||
|
|
||||||
|
double phase = std::fmod(t * speed, 1.0);
|
||||||
|
|
||||||
|
if (phase < 0.25)
|
||||||
|
{
|
||||||
|
double u = phase / 0.25;
|
||||||
|
cursor3d = Vector3d(
|
||||||
|
centerX - halfWidth + 2.0 * halfWidth * u,
|
||||||
|
centerY - halfHeight,
|
||||||
|
zPlane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (phase < 0.50)
|
||||||
|
{
|
||||||
|
double u = (phase - 0.25) / 0.25;
|
||||||
|
cursor3d = Vector3d(
|
||||||
|
centerX + halfWidth,
|
||||||
|
centerY - halfHeight + 2.0 * halfHeight * u,
|
||||||
|
zPlane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (phase < 0.75)
|
||||||
|
{
|
||||||
|
double u = (phase - 0.50) / 0.25;
|
||||||
|
cursor3d = Vector3d(
|
||||||
|
centerX + halfWidth - 2.0 * halfWidth * u,
|
||||||
|
centerY + halfHeight,
|
||||||
|
zPlane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double u = (phase - 0.75) / 0.25;
|
||||||
|
cursor3d = Vector3d(
|
||||||
|
centerX - halfWidth,
|
||||||
|
centerY + halfHeight - 2.0 * halfHeight * u,
|
||||||
|
zPlane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline double clampd(double v, double lo, double hi)
|
||||||
|
{
|
||||||
|
return std::max(lo, std::min(v, hi));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proof of concept, this method not my code
|
||||||
|
void Scene_CCDIK::performCcdIK(const Vector3d& target)
|
||||||
|
{
|
||||||
|
const int MAX_ITERS = 25;
|
||||||
|
const double POS_EPS = 0.002;
|
||||||
|
const double ANG_EPS = 1e-4;
|
||||||
|
const double MAX_STEP = 0.35;
|
||||||
|
const double GAIN = 0.85;
|
||||||
|
|
||||||
|
auto& joints = arm.getJoints();
|
||||||
|
|
||||||
|
auto jointOrigin = [&](std::size_t i) -> Vector3d
|
||||||
|
{
|
||||||
|
const ArmSegment* p = joints[i].getParent();
|
||||||
|
return p ? p->getTargetedGlobalEndpoint()
|
||||||
|
: Vector3d{ 0.0, 0.0, 0.0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
auto endEffector = [&]() -> Vector3d
|
||||||
|
{
|
||||||
|
return joints.back().getTargetedGlobalEndpoint();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int iter = 0; iter < MAX_ITERS; ++iter)
|
||||||
|
{
|
||||||
|
if ((target - endEffector()).magnitude() <= POS_EPS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int ji = static_cast<int>(NUM_JOINTS) - 1; ji >= 0; --ji)
|
||||||
|
{
|
||||||
|
ArmSegment& j = joints[static_cast<std::size_t>(ji)];
|
||||||
|
|
||||||
|
const Vector3d origin = jointOrigin(static_cast<std::size_t>(ji));
|
||||||
|
const Vector3d eePos = endEffector();
|
||||||
|
|
||||||
|
Vector3d r1 = eePos - origin;
|
||||||
|
Vector3d r2 = target - origin;
|
||||||
|
|
||||||
|
double r1l = r1.magnitude();
|
||||||
|
double r2l = r2.magnitude();
|
||||||
|
if (r1l < 1e-9 || r2l < 1e-9)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r1 /= r1l;
|
||||||
|
r2 /= r2l;
|
||||||
|
|
||||||
|
const double theta0 = j.getTargetPosition();
|
||||||
|
|
||||||
|
j.stageAngle(theta0 + ANG_EPS);
|
||||||
|
const Vector3d eePlus = endEffector();
|
||||||
|
j.stageAngle(theta0);
|
||||||
|
|
||||||
|
Vector3d dEe = (eePlus - eePos) / ANG_EPS;
|
||||||
|
|
||||||
|
Vector3d rVec = eePos - origin;
|
||||||
|
Vector3d axis = rVec.cross(dEe);
|
||||||
|
double axisLen = axis.magnitude();
|
||||||
|
if (axisLen < 1e-12)
|
||||||
|
continue;
|
||||||
|
axis /= axisLen;
|
||||||
|
|
||||||
|
Vector3d p1 = r1 - axis * r1.dot(axis);
|
||||||
|
Vector3d p2 = r2 - axis * r2.dot(axis);
|
||||||
|
|
||||||
|
double p1l = p1.magnitude();
|
||||||
|
double p2l = p2.magnitude();
|
||||||
|
if (p1l < 1e-9 || p2l < 1e-9)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p1 /= p1l;
|
||||||
|
p2 /= p2l;
|
||||||
|
|
||||||
|
double c = clampd(p1.dot(p2), -1.0, 1.0);
|
||||||
|
double s = axis.dot(p1.cross(p2));
|
||||||
|
double dTheta = std::atan2(s, c);
|
||||||
|
|
||||||
|
dTheta *= GAIN;
|
||||||
|
dTheta = clampd(dTheta, -MAX_STEP, MAX_STEP);
|
||||||
|
|
||||||
|
double newTheta = theta0 + dTheta;
|
||||||
|
newTheta = clampd(newTheta, j.getMinAngle(), j.getMaxAngle());
|
||||||
|
|
||||||
|
j.stageAngle(newTheta);
|
||||||
|
|
||||||
|
arm.rollbackJointsBasedOnValidRange();
|
||||||
|
if (!arm.checkJointCollisions(deadzones))
|
||||||
|
arm.rollbackPose();
|
||||||
|
|
||||||
|
if ((target - endEffector()).magnitude() <= POS_EPS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arm.commitPose();
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ public:
|
|||||||
void update(double frametime);
|
void update(double frametime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update3dCursor(double frametime);
|
void update3dCursorByVKBI(double frametime);
|
||||||
|
void update3dCursorSquare(double frametime);
|
||||||
|
void performCcdIK(const Vector3d& target);
|
||||||
|
|
||||||
Arm& arm;
|
Arm& arm;
|
||||||
std::array<AxisAlignedBoundingBox, 2> deadzones;
|
std::array<AxisAlignedBoundingBox, 2> deadzones;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Scene_JointSpaceControl::Scene_JointSpaceControl(Arm& arm):
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
leftVKB(L" VKBsim Gladiator EVO L "),
|
leftVKB(L" VKBsim Gladiator EVO L "),
|
||||||
plot(-200, 200, 20, 2)
|
plot(-400, 400, 20, 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!arm.assumeHomePoseImmediate()) {
|
if (!arm.assumeHomePoseImmediate()) {
|
||||||
@@ -67,5 +67,29 @@ void Scene_JointSpaceControl::update(double frametime)
|
|||||||
//std::cout << arm.getJ3().getCurrentPosition() << std::endl;
|
//std::cout << arm.getJ3().getCurrentPosition() << std::endl;
|
||||||
plot.draw(ef);
|
plot.draw(ef);
|
||||||
|
|
||||||
|
//std::cout
|
||||||
|
// << std::fixed
|
||||||
|
// << std::setprecision(1)
|
||||||
|
// << std::noshowpos
|
||||||
|
// << "j0: "
|
||||||
|
// << j0Pos
|
||||||
|
// << std::endl
|
||||||
|
// << "j1: "
|
||||||
|
// << j1Pos
|
||||||
|
// << std::endl
|
||||||
|
// << "j2: "
|
||||||
|
// << j2Pos
|
||||||
|
// << std::endl
|
||||||
|
// << "j3: "
|
||||||
|
// << j3Pos
|
||||||
|
// << std::endl
|
||||||
|
// << "j4: "
|
||||||
|
// << j4Pos
|
||||||
|
// << std::endl
|
||||||
|
// << "j5: "
|
||||||
|
// << j5Pos
|
||||||
|
// << std::endl;
|
||||||
|
//system("cls");
|
||||||
|
|
||||||
arm.update(frametime);
|
arm.update(frametime);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user