Welcome to mirror list, hosted at ThFree Co, Russian Federation.

MovingFrame.cpp « itasc « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 90ebe091eb53f730bdaf9a5e48cb8826cb3f2fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/** \file itasc/MovingFrame.cpp
 *  \ingroup itasc
 */
/*
 * MovingFrame.cpp
 *
 *  Created on: Feb 10, 2009
 *      Author: benoitbolsee
 */

#include "MovingFrame.hpp"
#include <string.h>
namespace iTaSC{

static const unsigned int frameCacheSize = (sizeof(((Frame*)0)->p.data)+sizeof(((Frame*)0)->M.data))/sizeof(double);

MovingFrame::MovingFrame(const Frame& frame):UncontrolledObject(),
	m_function(NULL), m_param(NULL), m_velocity(), m_poseCCh(-1), m_poseCTs(0)
{
	m_internalPose = m_nextPose = frame;
	initialize(6, 1);
	e_matrix& Ju = m_JuArray[0];
	Ju = e_identity_matrix(6,6);
}

MovingFrame::~MovingFrame()
{
}

bool MovingFrame::finalize()
{
	updateJacobian();
	return true;
}

void MovingFrame::initCache(Cache *_cache)
{
	m_cache = _cache;
	m_poseCCh = -1;
	if (m_cache) {
		m_poseCCh = m_cache->addChannel(this,"pose",frameCacheSize*sizeof(double));
		// don't store the initial pose, it's causing unnecessary large velocity on the first step
		//pushInternalFrame(0);
	}
}

void MovingFrame::pushInternalFrame(CacheTS timestamp)
{
	if (m_poseCCh >= 0) {
		double buf[frameCacheSize];
		memcpy(buf, m_internalPose.p.data, sizeof(m_internalPose.p.data));
		memcpy(&buf[sizeof(m_internalPose.p.data)/sizeof(double)], m_internalPose.M.data, sizeof(m_internalPose.M.data));

		m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, frameCacheSize, KDL::epsilon);
		m_poseCTs = timestamp;
	}
}

// load pose just preceding timestamp
// return false if no cache position was found
bool MovingFrame::popInternalFrame(CacheTS timestamp)
{
	if (m_poseCCh >= 0) {
		char *item;
		item = (char *)m_cache->getPreviousCacheItem(this, m_poseCCh, &timestamp);
		if (item && m_poseCTs != timestamp) {
			memcpy(m_internalPose.p.data, item, sizeof(m_internalPose.p.data));
			item += sizeof(m_internalPose.p.data);
			memcpy(m_internalPose.M.data, item, sizeof(m_internalPose.M.data));
			m_poseCTs = timestamp;
			// changing the starting pose, recompute the jacobian
			updateJacobian();
		}
		return (item) ? true : false;
	}
	// in case of no cache, there is always a previous position
	return true;
}

bool MovingFrame::setFrame(const Frame& frame)
{
	m_internalPose = m_nextPose = frame;
	return true;
}

bool MovingFrame::setCallback(MovingFrameCallback _function, void* _param)
{
	m_function = _function;
	m_param = _param;
	return true;
}

void MovingFrame::updateCoordinates(const Timestamp& timestamp)
{
	// don't compute the velocity during substepping, it is assumed constant.
	if (!timestamp.substep) {
		bool cacheAvail = true;
		if (!timestamp.reiterate) {
			cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
			if (m_function)
				(*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
		}
		// only compute velocity if we have a previous pose
		if (cacheAvail && timestamp.interpolate) {
			unsigned int iXu;
			m_velocity = diff(m_internalPose, m_nextPose, timestamp.realTimestep);
			for (iXu=0; iXu<6; iXu++)
				m_xudot(iXu) = m_velocity(iXu);
		} else if (!timestamp.reiterate) {
			// new position is forced, no velocity as we cannot interpolate
			m_internalPose = m_nextPose;
			m_velocity = Twist::Zero();
			m_xudot = e_zero_vector(6);
			// recompute the jacobian
			updateJacobian();
		}
	}
}

void MovingFrame::pushCache(const Timestamp& timestamp)
{
	if (!timestamp.substep && timestamp.cache)
		pushInternalFrame(timestamp.cacheTimestamp);
}

void MovingFrame::updateKinematics(const Timestamp& timestamp)
{
	if (timestamp.interpolate) {
		if (timestamp.substep) {
			// during substepping, update the internal pose from velocity information
			Twist localvel = m_internalPose.M.Inverse(m_velocity);
			m_internalPose.Integrate(localvel, 1.0/timestamp.realTimestep);
		} else {
			m_internalPose = m_nextPose;
		}
		// m_internalPose is updated, recompute the jacobian
		updateJacobian();
	}
	pushCache(timestamp);
}

void MovingFrame::updateJacobian()
{
	Twist m_jac;
	e_matrix& Ju = m_JuArray[0];

    //Jacobian is always identity at position on the object, 
	//we ust change the reference to the world.
	//instead of going through complicated jacobian operation, implemented direct formula
	Ju(1,3) = m_internalPose.p.z();
	Ju(2,3) = -m_internalPose.p.y();
	Ju(0,4) = -m_internalPose.p.z();
	Ju(2,4) = m_internalPose.p.x();
	Ju(0,5) = m_internalPose.p.y();
	Ju(1,5) = -m_internalPose.p.x();
	// remember that this object has moved
	m_updated = true;
}

}