Hi, i'm trying to run with ROBOC 3.51 a very interesting program of dead reckoning published by Mikep on his blog http://www.spiked3.com/?p=410#comment-185:
#pragma config(Sensor, S2, COMPASS, sensorI2CCustom9V)
#pragma config(Motor, motorB, LEFT, tmotorNormal, PIDControl, encoder)
#pragma config(Motor, motorC, RIGHT, tmotorNormal, PIDControl, encoder)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
// Xander's driver suite
#include "hitechnic-compass.h"
//**********************************************************//
//* *//
//* PoseNXC - LEGO NXT Robotics with Pose *//
//* *//
//**********************************************************//
#define __POSE_DEBUG__
#include "pose.h"
// shorthand for the typing lazy
intrinsic void _T(const string sFormatString, ...)
asm(opcdStringOps, strOpDebugStreamFormat, variableRefString(sFormatString), varArgList);
intrinsic void _TL(const string sFormatString, ...)
asm(opcdStringOps, strOpDebugStreamFormatWithNewLine, variableRefString(sFormatString), varArgList);
task DisplayPose()
{
while (true)
{
nxtDisplayTextLine(3, "# Pose@ %d", PoseClock);
nxtDisplayTextLine(4, "#-x,y %1.1f, %1.1f", PoseX, PoseY);
nxtDisplayTextLine(5, "#-hdg %d", PoseHdg);
nxtDisplayTextLine(6, "#-spd %1.1f", PoseVelocity);
wait1Msec(500);
}
}
void ShowPose(string t)
{
#ifdef _DEBUG
_TL("-%s", t);
_TL("--x,y %1.1f, %1.1f", PoseX, PoseY);
_TL("--hdg %d, %d", PoseHdg, HTMCreadRelativeHeading(COMPASS));
#endif
}
//**********************************************************//
//* *//
//* Main task *//
//* *//
//**********************************************************//
task main()
{
eraseDisplay();
nxtDisplayCenteredBigTextLine(0, "PoseNXT1");
_TL("");
_TL("***PoseNXT1");
time1[T1] = 0;
// should help to actually measure the tire, LEGO specs it at 81.6
// (float wheelDiameter, float wheelBase, float finalGearRatio, tMotor left, tMotor right, TSynchedMotors useForSynch, int movePower, int turnPower, int updateRate = 5)
PoseStartTask(81.6, 120.0, (float)(16/16), LEFT, RIGHT, synchBC, 50, 30);
StartTask(DisplayPose);
HTMCsetTarget(COMPASS);
PlaySound(soundBeepBeep);
// PilotMove(250.0);
// wait1Msec(500);
// PilotMove(-250.0);
// a lap done with moves and turns
for (int i = 0; i < 4; i++)
{
ShowPose("*move");
PilotMove(200.0);
PilotWaitDrivesIdle();
ShowPose("#move");
// simple
// PilotTurn(90);
// using corrected Turn
// PilotTurn(PilotQuickestTurnTo(PoseHdg, (i+1)*90));
// using TurnTo (which will internally correct)
// correct PoseHdg before we turn if compass available (will work with or without)
PoseHdg = PilotHdg360(HTMCreadRelativeHeading(COMPASS));
PilotTurnTo((i+1)*90);
wait1Msec(50); // give it as little time to update Pose
ShowPose("#turn");
}
// another lap done with GoTo
// PilotGoTo(0.0, 200.0);
// PilotGoTo(200.0, 200.0);
// PilotGoTo(200.0, 0.0);
// PilotGoTo(0.0, 0.0);
// PilotTurnTo(0);
PlaySound(soundBeepBeep);
bFloatDuringInactiveMotorPWM = true;
motor[LEFT] = 0;
motor[RIGHT] = 0;
ShowPose("final");
StopTask(PoseUpdate);
while (bSoundActive)
wait1Msec(100);
_TL("###PoseNXT");
while(true)
EndTimeSlice(); // use dark grey button to exit
}
The program was written for a previous version of ROBOTC and mikep kindly modified the library pose.h in this way to work under 3.5 version:
/changes
// 9/12/12 - update to work with robotc 3.5
bool _hasBeenInitialized = false;
// geometry info
float _wheelDiameter; // in some global unit
float _finalGearRatio; // generally spur / pinion
float _wheelBase;
int _PoseUpdateRate; // times per second
int _movePower, _turnPower;
tMotor _left, _right;
TSynchedMotors _useForSynch;
float _wheelTravelPerRevolution;
int _ticksPerWheelRevolution;
float _wheelBaseDiameter;
int _ticksForFullPilotTurn;
// Global Pose Variables
long PoseClock = 0; /*!< time (in ticks) the last update occurred */
short PoseHdg = 0; /*!< current heading in degrees */
float PoseX = 0.0, /*!< current X location */
PoseY = 0.0, /*!< current Y location */
PoseVelocity; /*!< current velocity */
task PoseUpdate();
/*!
* Initialize geomtery variables, Performs one time calculations, and starts the task PoseUpdate().
* All measurements must be in the same units, angles are in degrees. The example uses MM.
* @param wheelDiameter wheel diameter
* @param wheelBase wheel base
* @param finalGearRatio usually calculated as spur (the gear on the wheel) / pinion (the gear on the motor)
* @param left the motor that is driving the left wheel
* @param right the motor that is driving the right wheel
* @param useForSynch the syncMode to use for robotc, typically synchBC
* @param movePower the power to apply for a straight line move
* @param turnPower the power to apply when rotating to a new heading
* @param updateRate times per second the pose should be updated, the default is 5
*/
void PoseStartTask(float wheelDiameter, float wheelBase, float finalGearRatio, tMotor left, tMotor right, TSynchedMotors useForSynch, int movePower, int turnPower, int updateRate = 5)
{
_wheelDiameter = wheelDiameter;
_wheelBase = wheelBase;
_finalGearRatio = finalGearRatio;
_useForSynch = useForSynch;
_movePower = movePower;
_turnPower = turnPower;
_PoseUpdateRate = updateRate; // times per second
//_CompassInterval = compassInterval;
_left = left;
_right = right;
// one time calculated values
_wheelTravelPerRevolution = _wheelDiameter * PI;
_ticksPerWheelRevolution = 360 * _finalGearRatio;
_wheelBaseDiameter = _wheelBase * PI;
_ticksForFullPilotTurn = _wheelBaseDiameter * _ticksPerWheelRevolution / _wheelTravelPerRevolution;
#ifdef __POSE_DEBUG__
writeDebugStreamLine("PoseStartTask");
writeDebugStreamLine("wd %1.1f", _wheelDiameter);
writeDebugStreamLine("wb %1.1f", _wheelBase);
writeDebugStreamLine("fgr %1.1f", _finalGearRatio);
writeDebugStreamLine("wtpr %1.1f", _wheelTravelPerRevolution);
writeDebugStreamLine("tpwr %d", _ticksPerWheelRevolution);
writeDebugStreamLine("wbd %1.1f", _wheelBaseDiameter);
writeDebugStreamLine("tfft %d", _ticksForFullPilotTurn);
#endif
_hasBeenInitialized = true;
StartTask(PoseUpdate);
}
void PoseException()
{
hogCPU();
eraseDisplay();
PlaySound(soundException);
nxtDisplayCenteredTextLine(0, "Missing call to");
nxtDisplayCenteredTextLine(1, "PoseStartTask");
nxtDisplayCenteredTextLine(2, "Program aborted");
writeDebugStreamLine("Missing call to");
writeDebugStreamLine("PoseStartTask");
writeDebugStreamLine("Program aborted");
wait1Msec(10000);
StopAllTasks();
}
/*!
* This task is called by the NXT OS and will update the global pose variables to their current value.
* PoseStartTask() must be called before this task is started, and is automatically initially started by it.
* This task may be stopped and restarted by the user, and it will re-initialize Pose information.
*/
task PoseUpdate()
{
long lastEncoderLeft = 0;
long lastEncoderRight = 0;
long nowEncoderLeft;
long nowEncoderRight;
float leftDistance;
float rightDistance;
float poseTheta = 0.0;
float distance;
float xChange, yChange;
long deltaLeft, deltaRight;
if (!_hasBeenInitialized)
PoseException();
nSchedulePriority = 10; // we are pretty important
PoseX = 0.0;
PoseY = 0.0;
PoseHdg = 0;
PoseVelocity = 0.0;
nSyncedMotors = synchNone; // so we can reset both encoders
nMotorEncoder[_left] = 0;
nMotorEncoder[_right] = 0;
nSyncedMotors = _useForSynch; // back to 'normal' mode
while (true)
{
long elapsedTime;
hogCPU();
long nowTime = time1[T1];
elapsedTime = nowTime - PoseClock;
PoseClock = nowTime;
nowEncoderLeft = nMotorEncoder[_left];
nowEncoderRight = nMotorEncoder[_right];
deltaLeft = nowEncoderLeft - lastEncoderLeft;
deltaRight = nowEncoderRight - lastEncoderRight;
leftDistance = deltaLeft * _wheelTravelPerRevolution / (float)_ticksPerWheelRevolution;
rightDistance = deltaRight * _wheelTravelPerRevolution / (float)_ticksPerWheelRevolution;
distance = (leftDistance + rightDistance) / 2.0;
PoseVelocity = distance / elapsedTime / 1000;
//float poseTheta1 = MSIMUreadGyroZAxis(AIMU)/ 100.0; // using IMU gyro in radians
float poseTheta2 = ((leftDistance - rightDistance ) / _wheelBase); // using odemetry, in radians
poseTheta += poseTheta2;
// these (trig functions) are reversed from normal thinking,
// compass direction of 0 indicates North = a movement up the Y axis
xChange = distance * sin(poseTheta);
yChange = distance * cos(poseTheta);
PoseX += xChange;
PoseY += yChange;
PoseHdg = poseTheta * 180.0 / PI; // in degrees
lastEncoderLeft = nowEncoderLeft;
lastEncoderRight = nowEncoderRight;
releaseCPU();
wait1Msec(1000 / _PoseUpdateRate);
}
}
void PilotChangePower(int movePower, int turnPower)
{
_movePower = movePower;
_turnPower = turnPower;
}
void PilotChangePower(int movePower)
{
_movePower = movePower;
}
int PilotHdg360(int degrees)
{
while (degrees < 0)
degrees += 360;
return degrees % 360;
}
int PilotHdg180(int degrees)
{
degrees = PilotHdg360(degrees);
return degrees > 180 ? degrees - 360: degrees;
}
int PilotQuickestTurnTo(int hdgNow, int hdgNew)
{
hdgNow = PilotHdg360(hdgNow);
hdgNew = PilotHdg360(hdgNew);
if (hdgNow < hdgNew)
hdgNow += 360;
int left = hdgNow - hdgNew;
return (left < 181 ? -left : 360 - left);
}
void PilotWaitDrivesIdle()
{
if (!_hasBeenInitialized)
PoseException();
wait1Msec(20);
bool done = false;
while(!done)
{
done = (nMotorRunState[_left] == runStateIdle && nMotorRunState[_right] == runStateIdle);
EndTimeSlice();
}
wait1Msec(20);
}
void PilotMoveAsync(float distance)
{
long ticks;
if (!_hasBeenInitialized)
PoseException();
ticks = abs(distance * (float)_ticksPerWheelRevolution / _wheelTravelPerRevolution);
#ifdef __POSE_DEBUG__
writeDebugStreamLine("PilotMove:ticks %d", ticks);
#endif
nSyncedTurnRatio = 100;
nSyncedMotors = _useForSynch;
nMotorEncoderTarget[_left] = ticks;
motor[_left] = _movePower * sgn(distance);
}
void PilotTurnAsync(int degrees)
{
// this function is sensitive to which motor pairs we are using and in their order
// degrees may be flipped for BC or BA
long delta;
if (!_hasBeenInitialized)
PoseException();
// test this before uncommenting
// if (_useForSynch == synchBA || _useForSynch == synchCA || _useForSynch == synchCB)
// degrees = -degrees; ??
delta = (degrees * _ticksForFullPilotTurn / 360.0);
#ifdef __POSE_DEBUG__
writeDebugStreamLine("PilotTurn:%d", degrees);
writeDebugStreamLine(" LRe %d %d", nMotorEncoder[_left], nMotorEncoder[_right]);
writeDebugStreamLine(" ticks %d", delta);
#endif
nSyncedMotors = _useForSynch;
nSyncedTurnRatio = -100; // always turn opposite
nMotorEncoderTarget[_left] = abs(delta);
motor[_left] = _turnPower * sgn(delta);
}
void PilotTurnToAsync(int heading)
{
if (!_hasBeenInitialized)
PoseException();
PilotTurnAsync(PilotQuickestTurnTo(PoseHdg, heading));
}
void PilotGoToAsync(float x, float y)
{
float distance, hdgRadians;
int hdg;
distance = sqrt( (PoseX - x) * (PoseX - x) + (PoseY - y) * (PoseY - y) );
hdgRadians = atan2((y - PoseY), (x - PoseX)); // relative to 0,0
hdg = (int)(hdgRadians * 180.0 / PI);
#ifdef __POSE_DEBUG__
writeDebugStreamLine("GoTo: %1.1f, %1.1f", x, y);
writeDebugStreamLine(" frm: %1.1f, %1.1f", PoseX, PoseY);
writeDebugStreamLine(" hdgR: %1.1f", hdgRadians);
writeDebugStreamLine("dst hdg: %1.1f, %d", distance, hdg);
#endif
PilotTurnToAsync(hdg);
PilotWaitDrivesIdle(); //go to wait before we start moving
PilotMoveAsync(distance);
}
void PilotMove(float distance)
{
PilotMoveAsync(distance);
PilotWaitDrivesIdle();
}
void PilotTurn(int degrees)
{
PilotTurnAsync(degrees);
PilotWaitDrivesIdle();
}
void PilotTurnTo(int heading)
{
PilotTurnToAsync(heading);
PilotWaitDrivesIdle();
}
void PilotGoTo(float x, float y)
{
PilotGoToAsync(x,y);
PilotWaitDrivesIdle();
}
I tryed to run the program but i received these errors:
**Error**:Undefined variable 'strOpDebugStreamFormat'. 'short' assumed.
**Error**:Undefined variable 'varArgList'. 'short' assumed.
**Error**:Undefined variable 'strOpDebugStreamFormatWithNewLine'. 'short' assumed.
**Error**:Calling procedure 'ShowPose'. 'const' expressions does not fit. Parameter: 'string & t'. Expression: '"*move"'. Type: 'char *'
**Error**:Calling procedure 'ShowPose'. 'const' expressions does not fit. Parameter: 'string & t'. Expression: '"#move"'. Type: 'char *'
**Error**:Calling procedure 'ShowPose'. 'const' expressions does not fit. Parameter: 'string & t'. Expression: '"#turn"'. Type: 'char *'
**Error**:Calling procedure 'ShowPose'. 'const' expressions does not fit. Parameter: 'string & t'. Expression: '"final"'. Type: 'char *'
Can you help me to fix the problem?
I'd like to test my robot!!
Thank you in advance
flatino
dead reckoning program by spiked3.com
-
- Posts: 290
- Joined: 03 Oct 2011, 00:06
- Location: Gallifrey
- Contact:
Re: dead reckoning program by spiked3.com
Hi flatino,
This is probably best asked on the RobotC forums [LINK], as only a few people are using/are experienced with RobotC here.
P.S. In the future, please use the[/code] tags for code, as it preserves the spacing.
This is probably best asked on the RobotC forums [LINK], as only a few people are using/are experienced with RobotC here.
P.S. In the future, please use the
Code: Select all
[code]
A.K.A. NeXT-Generation.
"A kingdom of heaven for RobotC now has recursion!"
"A kingdom of heaven for RobotC now has recursion!"
Re: dead reckoning program by spiked3.com
hi inxt-generation,
thank you for the answer. I'll post it in the right place
sorry for my errors
flatino
thank you for the answer. I'll post it in the right place
sorry for my errors
flatino
Who is online
Users browsing this forum: No registered users and 12 guests