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
- 
				inxt-generation
- 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: Semrush [Bot] and 9 guests