BGE #18665: Servo control and relative motion

Servo control motion actuator did not work as expected when the object
is moving on a moving platform. 

This patch introduces a new Ref field in the servo motion actuator
to set a reference object for the velocity calculation.
You can set the object during the game using the actuator "reference"
attribute; use an object name or an object reference.

The servo controller takes into account the angular velocity of the
reference object to compute the relative local velocity.
This commit is contained in:
Benoit Bolsee 2009-05-18 08:22:51 +00:00
parent 3bda88babf
commit 07fc2aa526
8 changed files with 154 additions and 29 deletions

@ -579,6 +579,10 @@ void set_sca_new_poins_ob(Object *ob)
bCameraActuator *ca= act->data; bCameraActuator *ca= act->data;
ID_NEW(ca->ob); ID_NEW(ca->ob);
} }
else if(act->type==ACT_OBJECT) {
bObjectActuator *oa= act->data;
ID_NEW(oa->reference);
}
else if(act->type==ACT_SCENE) { else if(act->type==ACT_SCENE) {
bSceneActuator *sca= act->data; bSceneActuator *sca= act->data;
ID_NEW(sca->camera); ID_NEW(sca->camera);
@ -606,6 +610,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob)
bMessageSensor *ms; bMessageSensor *ms;
bActuator *act; bActuator *act;
bCameraActuator *ca; bCameraActuator *ca;
bObjectActuator *oa;
bSceneActuator *sa; bSceneActuator *sa;
bEditObjectActuator *eoa; bEditObjectActuator *eoa;
bPropertyActuator *pa; bPropertyActuator *pa;
@ -628,6 +633,10 @@ void sca_remove_ob_poin(Object *obt, Object *ob)
ca= act->data; ca= act->data;
if(ca->ob==ob) ca->ob= NULL; if(ca->ob==ob) ca->ob= NULL;
break; break;
case ACT_OBJECT:
oa= act->data;
if(oa->reference==ob) oa->reference= NULL;
break;
case ACT_PROPERTY: case ACT_PROPERTY:
pa= act->data; pa= act->data;
if(pa->ob==ob) pa->ob= NULL; if(pa->ob==ob) pa->ob= NULL;

@ -3077,6 +3077,10 @@ static void lib_link_object(FileData *fd, Main *main)
bAddObjectActuator *eoa= act->data; bAddObjectActuator *eoa= act->data;
if(eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob); if(eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
} }
else if(act->type==ACT_OBJECT) {
bObjectActuator *oa= act->data;
oa->reference= newlibadr(fd, ob->id.lib, oa->reference);
}
else if(act->type==ACT_EDIT_OBJECT) { else if(act->type==ACT_EDIT_OBJECT) {
bEditObjectActuator *eoa= act->data; bEditObjectActuator *eoa= act->data;
if(eoa==NULL) { if(eoa==NULL) {
@ -3087,6 +3091,15 @@ static void lib_link_object(FileData *fd, Main *main)
eoa->me= newlibadr(fd, ob->id.lib, eoa->me); eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
} }
} }
else if(act->type==ACT_OBJECT) {
bObjectActuator *oa= act->data;
if(oa==NULL) {
init_actuator(act);
}
else {
oa->reference= newlibadr(fd, ob->id.lib, oa->reference);
}
}
else if(act->type==ACT_SCENE) { else if(act->type==ACT_SCENE) {
bSceneActuator *sa= act->data; bSceneActuator *sa= act->data;
sa->camera= newlibadr(fd, ob->id.lib, sa->camera); sa->camera= newlibadr(fd, ob->id.lib, sa->camera);
@ -8862,6 +8875,10 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, eoa->me); expand_doit(fd, mainvar, eoa->me);
} }
} }
else if(act->type==ACT_OBJECT) {
bObjectActuator *oa= act->data;
expand_doit(fd, mainvar, oa->reference);
}
else if(act->type==ACT_SCENE) { else if(act->type==ACT_SCENE) {
bSceneActuator *sa= act->data; bSceneActuator *sa= act->data;
expand_doit(fd, mainvar, sa->camera); expand_doit(fd, mainvar, sa->camera);

@ -107,6 +107,7 @@ typedef struct bObjectActuator {
float loc[3], rot[3]; float loc[3], rot[3];
float dloc[3], drot[3]; float dloc[3], drot[3];
float linearvelocity[3], angularvelocity[3]; float linearvelocity[3], angularvelocity[3];
struct Object *reference;
} bObjectActuator; } bObjectActuator;
typedef struct bIpoActuator { typedef struct bIpoActuator {

@ -1830,42 +1830,44 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
} }
} else if (oa->type == ACT_OBJECT_SERVO) } else if (oa->type == ACT_OBJECT_SERVO)
{ {
ysize= 172; ysize= 195;
glRects(xco, yco-ysize, xco+width, yco); glRects(xco, yco-ysize, xco+width, yco);
uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
uiDefBut(block, LABEL, 0, "linV", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "Sets the target linear velocity, it will be achieve by automatic application of force. Null velocity is a valid target"); uiDefBut(block, LABEL, 0, "Ref", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "");
uiDefButF(block, NUM, 0, "", xco+45, yco-45, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, ""); uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+45, yco-45, wval*3, 19, &(oa->reference), "Reference object for velocity calculation, leave empty for world reference");
uiDefButF(block, NUM, 0, "", xco+45+wval, yco-45, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, NULL, 0, 0, 0, 0, "Sets the target relative linear velocity, it will be achieve by automatic application of force. Null velocity is a valid target");
uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-45, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Velocity is defined in local coordinates"); uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-68, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Velocity is defined in local coordinates");
uiDefBut(block, LABEL, 0, "Limit", xco, yco-68, 45, 19, NULL, 0, 0, 0, 0, "Select if the force need to be limited along certain axis (local or global depending on LinV Local flag)"); uiDefBut(block, LABEL, 0, "Limit", xco, yco-91, 45, 19, NULL, 0, 0, 0, 0, "Select if the force need to be limited along certain axis (local or global depending on LinV Local flag)");
uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_X, B_REDR, "X", xco+45, yco-68, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the X axis"); uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_X, B_REDR, "X", xco+45, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the X axis");
uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Y, B_REDR, "Y", xco+45+wval, yco-68, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Y axis"); uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Y, B_REDR, "Y", xco+45+wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Y axis");
uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Z, B_REDR, "Z", xco+45+2*wval, yco-68, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Z axis"); uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Z, B_REDR, "Z", xco+45+2*wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Z axis");
uiDefBut(block, LABEL, 0, "Max", xco, yco-87, 45, 19, NULL, 0, 0, 0, 0, "Set the upper limit for force"); uiDefBut(block, LABEL, 0, "Max", xco, yco-110, 45, 19, NULL, 0, 0, 0, 0, "Set the upper limit for force");
uiDefBut(block, LABEL, 0, "Min", xco, yco-106, 45, 19, NULL, 0, 0, 0, 0, "Set the lower limit for force"); uiDefBut(block, LABEL, 0, "Min", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Set the lower limit for force");
if (oa->flag & ACT_SERVO_LIMIT_X) { if (oa->flag & ACT_SERVO_LIMIT_X) {
uiDefButF(block, NUM, 0, "", xco+45, yco-87, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45, yco-110, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
} }
if (oa->flag & ACT_SERVO_LIMIT_Y) { if (oa->flag & ACT_SERVO_LIMIT_Y) {
uiDefButF(block, NUM, 0, "", xco+45+wval, yco-87, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+wval, yco-110, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
} }
if (oa->flag & ACT_SERVO_LIMIT_Z) { if (oa->flag & ACT_SERVO_LIMIT_Z) {
uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-87, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-110, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
} }
uiDefBut(block, LABEL, 0, "Servo", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Coefficients of the PID servo controller"); uiDefBut(block, LABEL, 0, "Servo", xco, yco-152, 45, 19, NULL, 0, 0, 0, 0, "Coefficients of the PID servo controller");
uiDefButF(block, NUMSLI, B_REDR, "P: ", xco+45, yco-129, wval*3, 19, oa->forcerot, 0.00, 200.0, 100, 0, "Proportional coefficient, typical value is 60x Integral coefficient"); uiDefButF(block, NUMSLI, B_REDR, "P: ", xco+45, yco-152, wval*3, 19, oa->forcerot, 0.00, 200.0, 100, 0, "Proportional coefficient, typical value is 60x Integral coefficient");
uiDefBut(block, LABEL, 0, "Slow", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Low value of I coefficient correspond to slow response"); uiDefBut(block, LABEL, 0, "Slow", xco, yco-152, 45, 19, NULL, 0, 0, 0, 0, "Low value of I coefficient correspond to slow response");
but = uiDefButF(block, NUMSLI, B_REDR, " I : ", xco+45, yco-148, wval*3, 19, oa->forcerot+1, 0.0, 3.0, 1, 0, "Integral coefficient, low value (0.01) for slow response, high value (0.5) for fast response"); but = uiDefButF(block, NUMSLI, B_REDR, " I : ", xco+45, yco-171, wval*3, 19, oa->forcerot+1, 0.0, 3.0, 1, 0, "Integral coefficient, low value (0.01) for slow response, high value (0.5) for fast response");
uiButSetFunc(but, update_object_actuator_PID, oa, NULL); uiButSetFunc(but, update_object_actuator_PID, oa, NULL);
uiDefBut(block, LABEL, 0, "Fast", xco+45+3*wval, yco-148, 45, 19, NULL, 0, 0, 0, 0, "High value of I coefficient correspond to fast response"); uiDefBut(block, LABEL, 0, "Fast", xco+45+3*wval, yco-171, 45, 19, NULL, 0, 0, 0, 0, "High value of I coefficient correspond to fast response");
uiDefButF(block, NUMSLI, B_REDR, "D: ", xco+45, yco-167, wval*3, 19, oa->forcerot+2, -100.0, 100.0, 100, 0, "Derivate coefficient, not required, high values can cause instability"); uiDefButF(block, NUMSLI, B_REDR, "D: ", xco+45, yco-190, wval*3, 19, oa->forcerot+2, -100.0, 100.0, 100, 0, "Derivate coefficient, not required, high values can cause instability");
} }
str= "Motion Type %t|Simple motion %x0|Servo Control %x1"; str= "Motion Type %t|Simple motion %x0|Servo Control %x1";
but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &oa->type, 0.0, 0.0, 0, 0, ""); but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &oa->type, 0.0, 0.0, 0, 0, "");
@ -3788,7 +3790,7 @@ void logic_buts(void)
uiBlockSetEmboss(block, UI_EMBOSSM); uiBlockSetEmboss(block, UI_EMBOSSM);
uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller"); uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller");
uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings");
uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Bookmarl controller to run before all other non-bookmarked controllers on each logic frame"); uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Bookmarl controller to run before all other non-bookmarked controllers");
uiBlockSetEmboss(block, UI_EMBOSSP); uiBlockSetEmboss(block, UI_EMBOSSP);
sprintf(name, "%d", first_bit(cont->state_mask)+1); sprintf(name, "%d", first_bit(cont->state_mask)+1);
uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)"); uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)");

@ -134,6 +134,7 @@ void BL_ConvertActuators(char* maggiename,
case ACT_OBJECT: case ACT_OBJECT:
{ {
bObjectActuator* obact = (bObjectActuator*) bact->data; bObjectActuator* obact = (bObjectActuator*) bact->data;
KX_GameObject* obref = NULL;
MT_Vector3 forcevec(KX_BLENDERTRUNC(obact->forceloc[0]), MT_Vector3 forcevec(KX_BLENDERTRUNC(obact->forceloc[0]),
KX_BLENDERTRUNC(obact->forceloc[1]), KX_BLENDERTRUNC(obact->forceloc[1]),
KX_BLENDERTRUNC(obact->forceloc[2])); KX_BLENDERTRUNC(obact->forceloc[2]));
@ -171,9 +172,13 @@ void BL_ConvertActuators(char* maggiename,
bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0); bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0);
bitLocalFlag.ServoControl = bool(obact->type == ACT_OBJECT_SERVO); bitLocalFlag.ServoControl = bool(obact->type == ACT_OBJECT_SERVO);
bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0); bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0);
if (obact->reference && bitLocalFlag.ServoControl)
{
obref = converter->FindGameObject(obact->reference);
}
KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator(gameobj, KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator(gameobj,
obref,
forcevec.getValue(), forcevec.getValue(),
torquevec.getValue(), torquevec.getValue(),
dlocvec.getValue(), dlocvec.getValue(),

@ -45,6 +45,7 @@
KX_ObjectActuator:: KX_ObjectActuator::
KX_ObjectActuator( KX_ObjectActuator(
SCA_IObject* gameobj, SCA_IObject* gameobj,
KX_GameObject* refobj,
const MT_Vector3& force, const MT_Vector3& force,
const MT_Vector3& torque, const MT_Vector3& torque,
const MT_Vector3& dloc, const MT_Vector3& dloc,
@ -69,6 +70,7 @@ KX_ObjectActuator(
m_previous_error(0.0,0.0,0.0), m_previous_error(0.0,0.0,0.0),
m_error_accumulator(0.0,0.0,0.0), m_error_accumulator(0.0,0.0,0.0),
m_bitLocalFlag (flag), m_bitLocalFlag (flag),
m_reference(refobj),
m_active_combined_velocity (false), m_active_combined_velocity (false),
m_linear_damping_active(false), m_linear_damping_active(false),
m_angular_damping_active(false) m_angular_damping_active(false)
@ -80,10 +82,17 @@ KX_ObjectActuator(
m_pid = m_torque; m_pid = m_torque;
} }
if (m_reference)
m_reference->RegisterActuator(this);
UpdateFuzzyFlags(); UpdateFuzzyFlags();
} }
KX_ObjectActuator::~KX_ObjectActuator()
{
if (m_reference)
m_reference->UnregisterActuator(this);
}
bool KX_ObjectActuator::Update() bool KX_ObjectActuator::Update()
{ {
@ -132,6 +141,18 @@ bool KX_ObjectActuator::Update()
if (mass < MT_EPSILON) if (mass < MT_EPSILON)
return false; return false;
MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
if (m_reference)
{
const MT_Point3& mypos = parent->NodeGetWorldPosition();
const MT_Point3& refpos = m_reference->NodeGetWorldPosition();
MT_Point3 relpos;
relpos = (mypos-refpos);
MT_Vector3 vel= m_reference->GetVelocity(relpos);
if (m_bitLocalFlag.LinearVelocity)
// must convert in local space
vel = parent->NodeGetWorldOrientation().transposed()*vel;
v -= vel;
}
MT_Vector3 e = m_linear_velocity - v; MT_Vector3 e = m_linear_velocity - v;
MT_Vector3 dv = e - m_previous_error; MT_Vector3 dv = e - m_previous_error;
MT_Vector3 I = m_error_accumulator + e; MT_Vector3 I = m_error_accumulator + e;
@ -260,7 +281,34 @@ CValue* KX_ObjectActuator::GetReplica()
return replica; return replica;
} }
void KX_ObjectActuator::ProcessReplica()
{
SCA_IActuator::ProcessReplica();
if (m_reference)
m_reference->RegisterActuator(this);
}
bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj)
{
if (clientobj == (SCA_IObject*)m_reference)
{
// this object is being deleted, we cannot continue to use it as reference.
m_reference = NULL;
return true;
}
return false;
}
void KX_ObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
{
void **h_obj = (*obj_map)[m_reference];
if (h_obj) {
if (m_reference)
m_reference->UnregisterActuator(this);
m_reference = (KX_GameObject*)(*h_obj);
m_reference->RegisterActuator(this);
}
}
/* some 'standard' utilities... */ /* some 'standard' utilities... */
bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type) bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
@ -357,6 +405,7 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY), KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY),
KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ), KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ),
KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid), KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid),
KX_PYATTRIBUTE_RW_FUNCTION("reference", KX_ObjectActuator,pyattr_get_reference,pyattr_set_reference),
{ NULL } //Sentinel { NULL } //Sentinel
}; };
@ -484,6 +533,38 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE
return PY_SET_ATTR_FAIL; return PY_SET_ATTR_FAIL;
} }
PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
if (!actuator->m_reference)
Py_RETURN_NONE;
return actuator->m_reference->GetProxy();
}
int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
KX_GameObject *refOb;
if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator"))
return PY_SET_ATTR_FAIL;
if (actuator->m_reference)
actuator->m_reference->UnregisterActuator(actuator);
if(refOb==NULL) {
actuator->m_reference= NULL;
}
else {
actuator->m_reference = refOb;
actuator->m_reference->RegisterActuator(actuator);
}
return PY_SET_ATTR_SUCCESS;
}
/* 1. set ------------------------------------------------------------------ */ /* 1. set ------------------------------------------------------------------ */
/* Removed! */ /* Removed! */

@ -35,6 +35,8 @@
#include "SCA_IActuator.h" #include "SCA_IActuator.h"
#include "MT_Vector3.h" #include "MT_Vector3.h"
class KX_GameObject;
// //
// Stores the flags for each CValue derived class // Stores the flags for each CValue derived class
// //
@ -92,7 +94,7 @@ class KX_ObjectActuator : public SCA_IActuator
MT_Vector3 m_previous_error; MT_Vector3 m_previous_error;
MT_Vector3 m_error_accumulator; MT_Vector3 m_error_accumulator;
KX_LocalFlags m_bitLocalFlag; KX_LocalFlags m_bitLocalFlag;
KX_GameObject* m_reference;
// A hack bool -- oh no sorry everyone // A hack bool -- oh no sorry everyone
// This bool is used to check if we have informed // This bool is used to check if we have informed
// the physics object that we are no longer // the physics object that we are no longer
@ -121,6 +123,7 @@ public:
KX_ObjectActuator( KX_ObjectActuator(
SCA_IObject* gameobj, SCA_IObject* gameobj,
KX_GameObject* refobj,
const MT_Vector3& force, const MT_Vector3& force,
const MT_Vector3& torque, const MT_Vector3& torque,
const MT_Vector3& dloc, const MT_Vector3& dloc,
@ -131,8 +134,11 @@ public:
const KX_LocalFlags& flag, const KX_LocalFlags& flag,
PyTypeObject* T=&Type PyTypeObject* T=&Type
); );
~KX_ObjectActuator();
CValue* GetReplica(); CValue* GetReplica();
void ProcessReplica();
bool UnlinkObject(SCA_IObject* clientobj);
void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
void SetForceLoc(const double force[3]) { /*m_force=force;*/ } void SetForceLoc(const double force[3]) { /*m_force=force;*/ }
void UpdateFuzzyFlags() void UpdateFuzzyFlags()
@ -188,6 +194,8 @@ public:
static int pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
// This lets the attribute macros use UpdateFuzzyFlags() // This lets the attribute macros use UpdateFuzzyFlags()
static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef) static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef)

@ -2668,6 +2668,8 @@ class KX_ObjectActuator(SCA_IActuator):
@ivar pid: The PID coefficients of the servo controller @ivar pid: The PID coefficients of the servo controller
@type pid: list of floats [proportional, integral, derivate] @type pid: list of floats [proportional, integral, derivate]
@ivar reference: The object that is used as reference to compute the velocity for the servo controller.
@type reference: KX_GameObject or None
@group Deprecated: getForce, setForce, getTorque, setTorque, getDLoc, setDLoc, getDRot, setDRot, getLinearVelocity, setLinearVelocity, getAngularVelocity, @group Deprecated: getForce, setForce, getTorque, setTorque, getDLoc, setDLoc, getDRot, setDRot, getLinearVelocity, setLinearVelocity, getAngularVelocity,
setAngularVelocity, getDamping, setDamping, getForceLimitX, setForceLimitX, getForceLimitY, setForceLimitY, getForceLimitZ, setForceLimitZ, setAngularVelocity, getDamping, setDamping, getForceLimitX, setForceLimitX, getForceLimitY, setForceLimitY, getForceLimitZ, setForceLimitZ,