Hey guys,
So Zenta had pretty much convinced me to buy the T7C heli transmitter and receiver, anyway very cool remote, it’s too bad that the remote cant use more switches at once as when used as 4 switches become dead when only configured for this type of usage…
I guess all the other channels are used for mixing… I do not own a heli or a plane so I don’t know… Anyway down to business.
Zenta has shared with me this code that was originally made by "Xan and numerous other people who chipped in "allows me to use the un modified T7C transmitter “7 Channel” for controlling the phoenix with bb2 and ssc32 basically the configuration is as follows
Left stick Horizontal = phoenix turns on its Z axis
Left stick Vertical = Raises and lowers Phoenix
Right stick Vertical = moves phoenix forward
Right stick Horizontal = Moves phoenix left and right
Channel 5:
3 state switch controls which mode the pheonix is in
mode 1: walk mode
mode 2: not walk mode but stands still and allows you to rotate and yaw and pitch while legs are locked to the ground
mode 3: GPmode plays sequences if you have the extra eeprom chip in the ssc32 for pre programmed moves and such.
channel 6:
VR pot that controls how fast the gait is executed
900-2100 output 900 being slow 2100 being max… "My opinion I don’t think this is really necessary as you should be able to simply use the right vertical stick to control the speed of the phoenix…but that’s just me…
Channel 7 is a momentary 2 state switch it is either at around 900 or 2100 decimal out via when read by the pulsin command “1500 is centered and this switch will never see 1500 value out on channel 7”
when in mode 1, pressing channel 7 will change gait type.
when in mode 2, pressing channel 7 will change something I forget but there are only 2 modes.
when in mode 3, this also does something “I do not have the eeprom chip in my ssc32 to be able to tell what it does although this is commented in the code quite a lot!”
So what I have done with this code is cannibalized mode 3 the original code has been commented out with ; the things I have commented out have two ;; so you can tell what I have done.
The goal of me hacking up his code is to want individual control of a leg for remote tentacle action per say… zenta had modified the ps2 remote code so RC could be used here is a video of him using his remote and showing it off
youtube.com/watch?v=72MY5GuHSpA
Anyway to activate this you would put the switch in state 3 and the robot would be stopped and moving the right analog stick one leg would be RC control and the code would just loop though controlling those 3 servos and the remaining 5 legs would be stuck to the ground.
In zenta’s video he is in mode 2 to make the phoenix lean backwards then went to mode 3 to get individual leg control propped up that leg onto the boxes and then switched back to mode 2 and wiggled a bit to let people know that that leg is locked in 3D space "as you can tell the plastic boxes don’t slide around when he tessellates the phoenix.
After that leg control is accomplished I would really like using that channel 7 momentary switch when in mode 3 “individual leg control” to change which of the 6 feet would be individually controlled.
the idea is to try and cram a lot of features use full or not into this robot without having to have the end user modify his transmitter.
I managed to find an 8 State rotary dial that stacking the correct resistors “zenta used 150 Ohm ones” you should be able to take the channel 6 VR pot and switch it on and off so that you have 8 roughly stable values when read with the pulsin command on channel 6. I still feel with the OEM setup a 3 state switch on channel 5 and a 2 state momentary on channel 7 you can program in an awfull lot of features without having to tear open your transmitter “No offense zenta” I love taking things apart like the rest of the gang
with that part said above here is the problem I face.
Using the original code Zenta has provided me is special code he wrote for someone on the other tossin robotics forum to use the T7C but not modified like his controller preciously which code I would like to start with after playing with this code I realized that mode3 which was GP player completely crashed the BB2 and it had to be reset after some looking into it zenta had mentioned to me I needed to pick up an eeprom for that socket in the ssc32… well frankly this feature didn’t really fancy my taste buds and I wanted to do the individual leg control as I explained above so I decided to remove this code and use mode 3 for that.
When I had cannibalized his code I could no longer raise and lower the phoenix channel 3 was un responsive and I really had no idea why.
I have a feeling its something very very easy that I am missing, but it has to do with nested loops that I have a hard time keeping track of “I’m sure every programmer does” anyway enough of me babbling here is zenta’s orignal code untouched by me.
;Project Lynxmotion Phoenix
;Description: Phoenix, controlled by a Futaba T7C remote
;Software version: V1.3
;Date: 20-10-2008
;Programmer: Jeroen Janssen (aka Xan)
;
;Hardware setup: ABB2 with ATOM 28 Pro, SSC32 V2, PS2 remote (See further for connections)
;
;NEW IN V1.3
; - Changed controls L1+ right stick
; - Balance calculations Thanks to KÃ¥re Halvorsen (aka Zenta)
;
;RC control:
;Select between walking, movement and GP player mode with the 3-state switch
;Use the two-state switch to toogle between the different gaits, movement or GPsequences
;In GPMode start GP player by moving the right stick upwards
;
;KNOWN BUGS:
; - None at the moment ;)
;
;====================================================================
;[CONSTANDS]
TRUE con 1
FALSE con 0
BUTTON_DOWN con 0
BUTTON_UP con 1
;--------------------------------------------------------------------
;[SERIAL CONNECTIONS]
SSC_LM_SETUP con 1 ;Changes the SSC pins corresponding to the setup
;1 = Setup with connector to the front
;0 = Setup with connector to the back
SSC_OUT con P11 ;Output pin for (SSC32 RX) on BotBoard (Yellow)
SSC_IN con P10 ;Input pin for (SSC32 TX) on BotBoard (Blue)
SSC_BAUTE con i38400 ;SSC32 Baute rate
;--------------------------------------------------------------------
;[RC Controller] Futaba T7C Heli
RCCh0 con P0 ;RC Remote Right Stick Left/Right (ch1 on T7C)
RCCh1 con P1 ;RC Remote Right Stick Up/Down (ch2 on T7C)
RCCh2 con P2 ;RC Remote Left Stick Up/Down (ch3 on T7C)
RCCh3 con P3 ;RC Remote Left Stick Left/Right (ch4 on T7C)
RCCh4 con P4 ;RC Remote E-switch (G switch on A model) 3-state (ch5 on T7C)
RCCh5 con P5 ;RC Remote Vr-pot (ch6 on T7C)
RCCh6 con P6 ;RC Remote H-switch (B switch on A model) 2-state (ch7 on T7C)
;--------------------------------------------------------------------
;[PIN NUMBERS]
#IF SSC_LM_SETUP ;Connector to the front
RRCoxaPin con P0 ;Rear Right leg Hip Horizontal
RRFemurPin con P1 ;Rear Right leg Hip Vertical
RRTibiaPin con P2 ;Rear Right leg Knee
RMCoxaPin con P4 ;Middle Right leg Hip Horizontal
RMFemurPin con P5 ;Middle Right leg Hip Vertical
RMTibiaPin con P6 ;Middle Right leg Knee
RFCoxaPin con P8 ;Front Right leg Hip Horizontal
RFFemurPin con P9 ;Front Right leg Hip Vertical
RFTibiaPin con P10 ;Front Right leg Knee
LRCoxaPin con P16 ;Rear Left leg Hip Horizontal
LRFemurPin con P17 ;Rear Left leg Hip Vertical
LRTibiaPin con P18 ;Rear Left leg Knee
LMCoxaPin con P20 ;Middle Left leg Hip Horizontal
LMFemurPin con P21 ;Middle Left leg Hip Vertical
LMTibiaPin con P22 ;Middle Left leg Knee
LFCoxaPin con P24 ;Front Left leg Hip Horizontal
LFFemurPin con P25 ;Front Left leg Hip Vertical
LFTibiaPin con P26 ;Front Left leg Knee
#ELSE ;Connector to the back
RFCoxaPin con P2 ;Front Right leg Hip Horizontal
RFFemurPin con P1 ;Front Right leg Hip Vertical
RFTibiaPin con P0 ;Front Right leg Knee
RMCoxaPin con P6 ;Middle Right leg Hip Horizontal
RMFemurPin con P5 ;Middle Right leg Hip Vertical
RMTibiaPin con P4 ;Middle Right leg Knee
RRCoxaPin con P10 ;Rear Right leg Hip Horizontal
RRFemurPin con P9 ;Rear Right leg Hip Vertical
RRTibiaPin con P8 ;Rear Right leg Knee
LFCoxaPin con P18 ;Front Left leg Hip Horizontal
LFFemurPin con P17 ;Front Left leg Hip Vertical
LFTibiaPin con P16 ;Front Left leg Knee
LMCoxaPin con P22 ;Middle Left leg Hip Horizontal
LMFemurPin con P21 ;Middle Left leg Hip Vertical
LMTibiaPin con P20 ;Middle Left leg Knee
LRCoxaPin con P26 ;Rear Left leg Hip Horizontal
LRFemurPin con P25 ;Rear Left leg Hip Vertical
LRTibiaPin con P24 ;Rear Left leg Knee
#ENDIF
;--------------------------------------------------------------------
;[MIN/MAX ANGLES]
RRCoxa_MIN con -26 ;Mechanical limits of the Right Rear Leg
RRCoxa_MAX con 74
RRFemur_MIN con -101
RRFemur_MAX con 95
RRTibia_MIN con -106
RRTibia_MAX con 77
RMCoxa_MIN con -53 ;Mechanical limits of the Right Middle Leg
RMCoxa_MAX con 53
RMFemur_MIN con -101
RMFemur_MAX con 95
RMTibia_MIN con -106
RMTibia_MAX con 77
RFCoxa_MIN con -58 ;Mechanical limits of the Right Front Leg
RFCoxa_MAX con 74
RFFemur_MIN con -101
RFFemur_MAX con 95
RFTibia_MIN con -106
RFTibia_MAX con 77
LRCoxa_MIN con -74 ;Mechanical limits of the Left Rear Leg
LRCoxa_MAX con 26
LRFemur_MIN con -95
LRFemur_MAX con 101
LRTibia_MIN con -77
LRTibia_MAX con 106
LMCoxa_MIN con -53 ;Mechanical limits of the Left Middle Leg
LMCoxa_MAX con 53
LMFemur_MIN con -95
LMFemur_MAX con 101
LMTibia_MIN con -77
LMTibia_MAX con 106
LFCoxa_MIN con -74 ;Mechanical limits of the Left Front Leg
LFCoxa_MAX con 58
LFFemur_MIN con -95
LFFemur_MAX con 101
LFTibia_MIN con -77
LFTibia_MAX con 106
;--------------------------------------------------------------------
;[BODY DIMENSIONS]
CoxaLength con 29 ;Length of the Coxa [mm]
FemurLength con 76 ;Length of the Femur [mm]
TibiaLength con 113;106 ;Lenght of the Tibia [mm]
CoxaAngle con 60 ;Default Coxa setup angle
RFOffsetX con -43 ;Distance X from center of the body to the Right Front coxa
RFOffsetZ con -82 ;Distance Z from center of the body to the Right Front coxa
RMOffsetX con -63 ;Distance X from center of the body to the Right Middle coxa
RMOffsetZ con 0 ;Distance Z from center of the body to the Right Middle coxa
RROffsetX con -43 ;Distance X from center of the body to the Right Rear coxa
RROffsetZ con 82 ;Distance Z from center of the body to the Right Rear coxa
LFOffsetX con 43 ;Distance X from center of the body to the Left Front coxa
LFOffsetZ con -82 ;Distance Z from center of the body to the Left Front coxa
LMOffsetX con 63 ;Distance X from center of the body to the Left Middle coxa
LMOffsetZ con 0 ;Distance Z from center of the body to the Left Middle coxa
LROffsetX con 43 ;Distance X from center of the body to the Left Rear coxa
LROffsetZ con 82 ;Distance Z from center of the body to the Left Rear coxa
;--------------------------------------------------------------------
;[REMOTE]
TravelDeadZone con 4 ;The deadzone for the analog input from the remote
;====================================================================
;[ANGLES]
RFCoxaAngle var sword ;Actual Angle of the Right Front Leg
RFFemurAngle var sword
RFTibiaAngle var sword
RMCoxaAngle var sword ;Actual Angle of the Right Middle Leg
RMFemurAngle var sword
RMTibiaAngle var sword
RRCoxaAngle var sword ;Actual Angle of the Right Rear Leg
RRFemurAngle var sword
RRTibiaAngle var sword
LFCoxaAngle var sword ;Actual Angle of the Left Front Leg
LFFemurAngle var sword
LFTibiaAngle var sword
LMCoxaAngle var sword ;Actual Angle of the Left Middle Leg
LMFemurAngle var sword
LMTibiaAngle var sword
LRCoxaAngle var sword ;Actual Angle of the Left Rear Leg
LRFemurAngle var sword
LRTibiaAngle var sword
;--------------------------------------------------------------------
;[POSITIONS]
RFPosX var sword ;Actual Position of the Right Front Leg
RFPosY var sword
RFPosZ var sword
RMPosX var sword ;Actual Position of the Right Middle Leg
RMPosY var sword
RMPosZ var sword
RRPosX var sword ;Actual Position of the Right Rear Leg
RRPosY var sword
RRPosZ var sword
LFPosX var sword ;Actual Position of the Left Front Leg
LFPosY var sword
LFPosZ var sword
LMPosX var sword ;Actual Position of the Left Middle Leg
LMPosY var sword
LMPosZ var sword
LRPosX var sword ;Actual Position of the Left Rear Leg
LRPosY var sword
LRPosZ var sword
;--------------------------------------------------------------------
;[INPUTS]
butA var bit
butB var bit
butC var bit
prev_butA var bit
prev_butB var bit
prev_butC var bit
;--------------------------------------------------------------------
;[OUTPUTS]
LedA var bit ;Red
LedB var bit ;Green
LedC var bit ;Orange
;--------------------------------------------------------------------
;[VARIABLES]
Index var byte ;Index used for freeing the servos
SSCDone var byte ;Char to check if SSC is done
;GetSinCos
AngleDeg var float ;Input Angle in degrees
ABSAngleDeg var float ;Absolute value of the Angle in Degrees
AngleRad var float ;Angle in Radian
sinA var float ;Output Sinus of the given Angle
cosA var float ;Output Cosinus of the given Angle
;GetBoogTan
BoogTanX var sword ;Input X
BoogTanY var sword ;Input Y
BoogTan var float ;Output BOOGTAN2(X/Y)
;Body position
BodyPosX var sbyte ;Global Input for the position of the body
BodyPosY var sword
BodyPosZ var sbyte
;Body Inverse Kinematics
BodyRotX var sbyte ;Global Input pitch of the body
BodyRotY var sbyte ;Global Input rotation of the body
BodyRotZ var sbyte ;Global Input roll of the body
PosX var sword ;Input position of the feet X
PosZ var sword ;Input position of the feet Z
PosY var sword ;Input position of the feet Y
RotationY var sbyte ;Input for rotation of a single feet for the gait
BodyOffsetX var sbyte ;Input Offset betweeen the body and Coxa X
BodyOffsetZ var sbyte ;Input Offset betweeen the body and Coxa Z
sinB var float ;Sin buffer for BodyRotX calculations
cosB var float ;Cos buffer for BodyRotX calculations
sinG var float ;Sin buffer for BodyRotZ calculations
cosG var float ;Cos buffer for BodyRotZ calculations
TotalX var sword ;Total X distance between the center of the body and the feet
TotalZ var sword ;Total Z distance between the center of the body and the feet
DistCenterBodyFeet var float ;Total distance between the center of the body and the feet
AngleCenterBodyFeetX var float ;Angle between the center of the body and the feet
BodyIKPosX var sword ;Output Position X of feet with Rotation
BodyIKPosY var sword ;Output Position Y of feet with Rotation
BodyIKPosZ var sword ;Output Position Z of feet with Rotation
;Leg Inverse Kinematics
IKFeetPosX var sword ;Input position of the Feet X
IKFeetPosY var sword ;Input position of the Feet Y
IKFeetPosZ var sword ;Input Position of the Feet Z
IKFeetPosXZ var sword ;Length between the coxa and feet
IKSW var float ;Length between shoulder and wrist
IKA1 var float ;Angle between SW line and the ground in rad
IKA2 var float ;?
IKSolution var bit ;Output true if the solution is possible
IKSolutionWarning var bit ;Output true if the solution is NEARLY possible
IKSolutionError var bit ;Output true if the solution is NOT possible
IKFemurAngle var sword ;Output Angle of Femur in degrees
IKTibiaAngle var sword ;Output Angle of Tibia in degrees
IKCoxaAngle var sword ;Output Angle of Coxa in degrees
;--------------------------------------------------------------------
;[GP player]
GPByte0 var Byte
GPByte1 var Byte
GPByte2 var Byte
GPByte3 var Byte
GPIsPlaying var bit
GPSeqToBePlayed var Byte
GPoccupied var bit
GPLastStep var Byte
GPSpeed var Byte
GPCounter var byte
;--------------------------------------------------------------------
;[RC Remote]
RCInput var word(7)
Buttons var byte
LastButtons var byte
StickMode var nib
Alive var byte
WalkMode var bit ;ch5 Mode switch (Switch E on Futaba T7C H)
MoveMode var bit
GPModeON var bit
TwoStateSW var bit ;ch 7 ,2-state switch
ToogleMovement var bit
;--------------------------------------------------------------------
;[TIMING]
lTimerWOverflowCnt var long ;used in WTimer overflow. Will keep a 16 bit overflow so we have a 32 bit timer
lCurrentTime var long
lTimerStart var long ;Start time of the calculation cycles
lTimerEnd var long ;End time of the calculation cycles
CycleTime var byte ;Total Cycle time
SSCTime var word ;Time for servo updates
PrevSSCTime var word ;Previous time for the servo updates
InputTimeDelay var byte ;Delay that depends on the input to get the "sneaking" effect
;--------------------------------------------------------------------
;[GLOABAL]
HexOn var bit ;Switch to turn on Phoenix
TurnOff var bit ;Mark to turn off Phoenix
;--------------------------------------------------------------------
;[Balance]
BalanceMode var bit
TravelHeightY var sword
TotalTransX var sword
TotalTransZ var sword
TotalTransY var sword
TotalYbal var sword
TotalXBal var sword
TotalZBal var sword
TotalY var sword ;Total Y distance between the center of the body and the feet
;[gait]
GaitType var byte ;Gait type
NomGaitSpeed var byte ;Nominal speed of the gait
LegLiftHeight var byte ;Current Travel height
TravelLengthX var sword ;Current Travel length X
TravelLengthZ var sword ;Current Travel length Z
TravelRotationY var sword ;Current Travel Rotation Y
TLDivFactor var byte ;Number of steps that a leg is on the floor while walking
NrLiftedPos var nib ;Number of positions that a single leg is lifted (1-3)
HalfLiftHeigth var bit ;If TRUE the outer positions of the ligted legs will be half height
GaitInMotion var bit ;Temp to check if the gait is in motion
StepsInGait var byte ;Number of steps in gait
LastLeg var bit ;TRUE when the current leg is the last leg of the sequence
GaitStep var byte ;Actual Gait step
RFGaitLegNr var byte ;Init position of the leg
RMGaitLegNr var byte ;Init position of the leg
RRGaitLegNr var byte ;Init position of the leg
LFGaitLegNr var byte ;Init position of the leg
LMGaitLegNr var byte ;Init position of the leg
LRGaitLegNr var byte ;Init position of the leg
GaitLegNr var byte ;Input Number of the leg
TravelMulti var sbyte ;Multiplier for the length of the step
RFGaitPosX var sbyte ;Relative position corresponding to the Gait
RFGaitPosY var sbyte
RFGaitPosZ var sbyte
RFGaitRotY var sbyte ;Relative rotation corresponding to the Gait
RMGaitPosX var sbyte
RMGaitPosY var sbyte
RMGaitPosZ var sbyte
RMGaitRotY var sbyte
RRGaitPosX var sbyte
RRGaitPosY var sbyte
RRGaitPosZ var sbyte
RRGaitRotY var sbyte
LFGaitPosX var sbyte
LFGaitPosY var sbyte
LFGaitPosZ var sbyte
LFGaitRotY var sbyte
LMGaitPosX var sbyte
LMGaitPosY var sbyte
LMGaitPosZ var sbyte
LMGaitRotY var sbyte
LRGaitPosX var sbyte
LRGaitPosY var sbyte
LRGaitPosZ var sbyte
LRGaitRotY var sbyte
GaitPosX var sbyte ;In-/Output Pos X of feet
GaitPosY var sword ;In-/Output Pos Y of feet
GaitPosZ var sbyte ;In-/Output Pos Z of feet
GaitRotY var sbyte ;In-/Output Rotation Y of feet
;====================================================================
;[TIMER INTERRUPT INIT]
ONASMINTERRUPT TIMERWINT, Handle_TIMERW
;====================================================================
;[INIT]
;Turning off all the leds
LedA = 0
LedB = 0
LedC = 0
'Feet Positions
RFPosX = 53 ;Start positions of the Right Front leg
RFPosY = 25
RFPosZ = -91
RMPosX = 105 ;Start positions of the Right Middle leg
RMPosY = 25
RMPosZ = 0
RRPosX = 53 ;Start positions of the Right Rear leg
RRPosY = 25
RRPosZ = 91
LFPosX = 53 ;Start positions of the Left Front leg
LFPosY = 25
LFPosZ = -91
LMPosX = 105 ;Start positions of the Left Middle leg
LMPosY = 25
LMPosZ = 0
LRPosX = 53 ;Start positions of the Left Rear leg
LRPosY = 25
LRPosZ = 91
;Body Positions
BodyPosX = 0
BodyPosY = 0
BodyPosZ = 0
;Body Rotations
BodyRotX = 0
BodyRotY = 0
BodyRotZ = 0
;GP mode
GPIsPlaying = FALSE
GPoccupied = TRUE
;Gait
GaitType = 0
BalanceMode = 0
LegLiftHeight = 50
GaitStep = 1
GOSUB GaitSelect
;Timer
WTIMERTICSPERMS con 2000; we have 16 clocks per ms and we are incrementing every 8 so divide again by 2
TCRW = 0x30 ;clears TCNT and sets the timer to inc clock cycle / 8
TMRW = 0x80 ;starts the timer counting
lTimerWOverflowCnt = 0
enable TIMERWINT_OVF
;SSC
SSCTime = 150
HexOn = True 'KÃ¥re turned it on..
;====================================================================
;[MAIN]
main:
'Start time
GOSUB GetCurrentTime], lTimerStart
;Read input
GOSUB RCInput1
'Check if we are in GPMode
if (GPModeON OR GPIsPlaying) = FALSE then
'Reset IKsolution indicators
IKSolution = False
IKSolutionWarning = False
IKSolutionError = False
;Gait
GOSUB GaitSeq
;Balance calculations
TotalTransX = 0 'reset values used for calculation of balance
TotalTransZ = 0
TotalTransY = 0
TotalXBal = 0
TotalYBal = 0
TotalZBal = 0
IF (BalanceMode>0) THEN
gosub BalCalcOneLeg -RFPosX+BodyPosX+RFGaitPosX, RFPosZ+BodyPosZ+RFGaitPosZ,RFGaitPosY, RFOffsetX, RFOffsetZ]
gosub BalCalcOneLeg -RMPosX+BodyPosX+RMGaitPosX, RMPosZ+BodyPosZ+RMGaitPosZ,RMGaitPosY, RMOffsetX, RMOffsetZ]
gosub BalCalcOneLeg -RRPosX+BodyPosX+RRGaitPosX, RRPosZ+BodyPosZ+RRGaitPosZ,RRGaitPosY, RROffsetX, RROffsetZ]
gosub BalCalcOneLeg [LFPosX-BodyPosX+LFGaitPosX, LFPosZ+BodyPosZ+LFGaitPosZ,LFGaitPosY, LFOffsetX, LFOffsetZ]
gosub BalCalcOneLeg [LMPosX-BodyPosX+LMGaitPosX, LMPosZ+BodyPosZ+LMGaitPosZ,LMGaitPosY, LMOffsetX, LMOffsetZ]
gosub BalCalcOneLeg [LRPosX-BodyPosX+LRGaitPosX, LRPosZ+BodyPosZ+LRGaitPosZ,LRGaitPosY, LROffsetX, LROffsetZ]
gosub BalanceBody
ENDIF
'Reset IKsolution indicators
IKSolution = False
IKSolutionWarning = False
IKSolutionError = False
;Right Front leg
GOSUB BodyIK -RFPosX+BodyPosX+RFGaitPosX, RFPosZ+BodyPosZ+RFGaitPosZ,RFPosY+BodyPosY+RFGaitPosY, RFOffsetX, RFOffsetZ, RFGaitRotY]
GOSUB LegIK [RFPosX-BodyPosX+BodyIKPosX-RFGaitPosX, RFPosY+BodyPosY-BodyIKPosY+RFGaitPosY, RFPosZ+BodyPosZ-BodyIKPosZ+RFGaitPosZ]
RFCoxaAngle = IKCoxaAngle + CoxaAngle ;Angle for the basic setup for the front leg
RFFemurAngle = IKFemurAngle
RFTibiaAngle = IKTibiaAngle
;Right Middle leg
GOSUB BodyIK -RMPosX+BodyPosX+RMGaitPosX, RMPosZ+BodyPosZ+RMGaitPosZ,RMPosY+BodyPosY+RMGaitPosY, RMOffsetX, RMOffsetZ, RMGaitRotY]
GOSUB LegIK [RMPosX-BodyPosX+BodyIKPosX-RMGaitPosX, RMPosY+BodyPosY-BodyIKPosY+RMGaitPosY, RMPosZ+BodyPosZ-BodyIKPosZ+RMGaitPosZ]
RMCoxaAngle = IKCoxaAngle
RMFemurAngle = IKFemurAngle
RMTibiaAngle = IKTibiaAngle
;Right Rear leg
GOSUB BodyIK -RRPosX+BodyPosX+RRGaitPosX, RRPosZ+BodyPosZ+RRGaitPosZ,RRPosY+BodyPosY+RRGaitPosY, RROffsetX, RROffsetZ, RRGaitRotY]
GOSUB LegIK [RRPosX-BodyPosX+BodyIKPosX-RRGaitPosX, RRPosY+BodyPosY-BodyIKPosY+RRGaitPosY, RRPosZ+BodyPosZ-BodyIKPosZ+RRGaitPosZ]
RRCoxaAngle = IKCoxaAngle - CoxaAngle ;Angle for the basic setup for the front leg
RRFemurAngle = IKFemurAngle
RRTibiaAngle = IKTibiaAngle
;Left Front leg
GOSUB BodyIK [LFPosX-BodyPosX+LFGaitPosX, LFPosZ+BodyPosZ+LFGaitPosZ,LFPosY+BodyPosY+LFGaitPosY, LFOffsetX, LFOffsetZ, LFGaitRotY]
GOSUB LegIK [LFPosX+BodyPosX-BodyIKPosX+LFGaitPosX, LFPosY+BodyPosY-BodyIKPosY+LFGaitPosY, LFPosZ+BodyPosZ-BodyIKPosZ+LFGaitPosZ]
LFCoxaAngle = IKCoxaAngle + CoxaAngle ;Angle for the basic setup for the front leg
LFFemurAngle = IKFemurAngle
LFTibiaAngle = IKTibiaAngle
;Left Middle leg
GOSUB BodyIK [LMPosX-BodyPosX+LMGaitPosX, LMPosZ+BodyPosZ+LMGaitPosZ,LMPosY+BodyPosY+LMGaitPosY, LMOffsetX, LMOffsetZ, LMGaitRotY]
GOSUB LegIK [LMPosX+BodyPosX-BodyIKPosX+LMGaitPosX, LMPosY+BodyPosY-BodyIKPosY+LMGaitPosY, LMPosZ+BodyPosZ-BodyIKPosZ+LMGaitPosZ]
LMCoxaAngle = IKCoxaAngle
LMFemurAngle = IKFemurAngle
LMTibiaAngle = IKTibiaAngle
;Left Rear leg
GOSUB BodyIK [LRPosX-BodyPosX+LRGaitPosX, LRPosZ+BodyPosZ+LRGaitPosZ,LRPosY+BodyPosY+LRGaitPosY, LROffsetX, LROffsetZ, LRGaitRotY]
GOSUB LegIK [LRPosX+BodyPosX-BodyIKPosX+LRGaitPosX, LRPosY+BodyPosY-BodyIKPosY+LRGaitPosY, LRPosZ+BodyPosZ-BodyIKPosZ+LRGaitPosZ]
LRCoxaAngle = IKCoxaAngle - CoxaAngle ;Angle for the basic setup for the front leg
LRFemurAngle = IKFemurAngle
LRTibiaAngle = IKTibiaAngle
GOSUB CheckAngles
LedC = IKSolutionWarning
LedA = IKSolutionError
;Get endtime and calculate wait time
GOSUB GetCurrentTime], lTimerEnd
CycleTime = (lTimerEnd-lTimerStart)/WTIMERTICSPERMS
serout s_out, i38400, [dec HexOn, " ", sdec bodyposy, " "]
IF(HexOn)THEN
;Wait for previous commands to be completed while walking
IF(ABS(TravelLengthX)>TravelDeadZone | ABS(TravelLengthZ)>TravelDeadZone | ABS(TravelRotationY*2)>TravelDeadZone) THEN
pause (PrevSSCTime - CycleTime -50) MIN 1 ; Min 1 ensures that there alway is a value in the pause command
IF(BalanceMode=0)THEN
SSCTime = NomGaitSpeed + (InputTimeDelay*2)
ELSE
SSCTime = NomGaitSpeed + (InputTimeDelay*2) + 100
ENDIF
ELSE
SSCTime = 200 ;NomGaitSpeed
ENDIF
GOSUB ServoDriver
;Turn the bot off
IF TurnOff THEN
;pause 200
;GOSUB FreeServos
HexOn=FALSE
ENDIF
ENDIF
'We are in GPMode:
else
gosub GPPlayer
pause 60
endif
'serout s_out, i38400, [sdec bodyposy, 13]
goto main
;====================================================================
;[ReadButtons] Reading input buttons from the ABB
ReadButtons:
input P4
input P5
input P6
prev_butA = butA
prev_butB = butB
prev_butC = butC
butA = IN4
butB = IN5
butC = IN6
return
;--------------------------------------------------------------------
;[WriteLEDs] Updates the state of the leds
WriteLEDs:
if ledA = 1 THEN
low p4
ENDIF
if ledB = 1 THEN
low p5
ENDIF
if ledC = 1 THEN
low p6
ENDIF
return
;--------------------------------------------------------------------
;[RCInput] reads the input data from the RC-Remote and processes the
;data to the parameters.
RCInput1:
;Read input pulse lengths in the correct order that take shortest time
PULSIN RCCh0, 0, RCInput(0)
PULSIN RCCh2, 0, RCInput(2)
PULSIN RCCh4, 0, RCInput(4)
PULSIN RCCh5, 0, RCInput(5)
PULSIN RCCh1, 0, RCInput(1)
PULSIN RCCh3, 0, RCInput(3)
PULSIN RCCh6, 0, RCInput(6)
WalkMode = False
MoveMode = False
GPModeON = False
BalanceMode = False
if RCInput(4) < 1100 then
WalkMode = True
elseif ((RCInput(4) > 1400) & (RCInput(4) < 1600))
MoveMode = True
else
GPModeON = True
endif
if RCInput(6) < 1500 then
TwoStateSW = False
else
TwoStateSW = True
endif
;***********************************************************************************
;*** Walking mode, toogle between the different walking gait with 2-state button ***
;***********************************************************************************
if WalkMode then
if RCInput(5) < 1750 then 'Select BalanceMode with VR-pot at slower speed
BalanceMode = TRUE
else
BalanceMode = FALSE
endif
if TwoStateSW then 'Toggle gait method:
if GaitType < 7 then 'so far we have 8 gait methods
GaitType = GaitType +1
sound P9,[150\(800+(GaitType*100))]
else
GaitType = 0
sound P9,[100\1900,150\2100]
endif
gosub GaitSelect
endif
TravelLengthX = (RCInput(0)-1500)/4
TravelLengthZ = (RCInput(1)-1500)/4
TravelRotationY = (RCInput(3)-1500)/12
;***********************************************************************************
;*** Move mode, toogle between translating and rotating body with 2-state button ***
;***********************************************************************************
elseif MoveMode
if TwoStateSw then 'Toogle movement method
if ToogleMovement then
ToogleMovement = False
sound P9,[100\800,150\1800]
else
ToogleMovement = True
sound P9,[100\1800,150\800]
endif
endif
if ToogleMovement then
'Body translate:
BodyPosX = -(RCInput(0)-1500)/10
BodyPosZ = -(RCInput(1)-1500)/8
BodyRotY = -(RCInput(3)-1500)/20
else
'Body rotate:
BodyRotX = -(RCInput(1)-1500)/20
BodyRotY = -(RCInput(3)-1500)/20
BodyRotZ = (RCInput(0)-1500)/20
endif
;*************************************************************************************
;*** GP sequencer player mode choose between two different seq with 2-state button ***
;*************************************************************************************
elseif GPModeON
'GPoccupied = TRUE
if TwoStateSW then 'Use 2-state switch to toogle between every sequence
if GPIsPlaying = FALSE then
if GPSeqToBePlayed < 2 then
GPSeqToBePlayed = GPSeqToBePlayed +1
else
GPSeqToBePlayed = 0 'Selected GP sequence
endif
for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
pause 150
sound P9,[70\1200]
next
endif
endif
if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
GPoccupied = FALSE
sound P9,[30\800,30\1000,30\1200,30\1400]
endif
GPSpeed = 100
endif
BodyPosY = (RCInput(2)-1000)/8 'adjust body height
;Calculate walking time delay
InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-1010)/8)
'ENDIF
return
;--------------------------------------------------------------------
;[GAIT Select]
GaitSelect
;Gait selector
IF (GaitType = 0) THEN ;Ripple Gait 6 steps
LRGaitLegNr = 1
RFGaitLegNr = 2
LMGaitLegNr = 3
RRGaitLegNr = 4
LFGaitLegNr = 5
RMGaitLegNr = 6
NrLiftedPos = 1
TLDivFactor = 4
StepsInGait = 6
NomGaitSpeed = 150
ENDIF
IF (GaitType = 1) THEN ;Ripple Gait 12 steps
LRGaitLegNr = 1
RFGaitLegNr = 3
LMGaitLegNr = 5
RRGaitLegNr = 7
LFGaitLegNr = 9
RMGaitLegNr = 11
NrLiftedPos = 3
HalfLiftHeigth = TRUE
TLDivFactor = 8
StepsInGait = 12
NomGaitSpeed = 100
ENDIF
IF (GaitType = 2) THEN ;Quadripple 9 steps
LRGaitLegNr = 1
RFGaitLegNr = 2
LMGaitLegNr = 4
RRGaitLegNr = 5
LFGaitLegNr = 7
RMGaitLegNr = 8
NrLiftedPos = 2
HalfLiftHeigth = FALSE
TLDivFactor = 6
StepsInGait = 9
NomGaitSpeed = 150
ENDIF
IF (GaitType = 3) THEN ;Tripod 4 steps
LRGaitLegNr = 3
RFGaitLegNr = 1
LMGaitLegNr = 1
RRGaitLegNr = 1
LFGaitLegNr = 3
RMGaitLegNr = 3
NrLiftedPos = 1
TLDivFactor = 2
StepsInGait = 4
NomGaitSpeed = 150
ENDIF
IF (GaitType = 4) THEN ;Tripod 6 steps
LRGaitLegNr = 4
RFGaitLegNr = 1
LMGaitLegNr = 1
RRGaitLegNr = 1
LFGaitLegNr = 4
RMGaitLegNr = 4
NrLiftedPos = 2
HalfLiftHeigth = FALSE
TLDivFactor = 4
StepsInGait = 6
NomGaitSpeed = 150
ENDIF
IF (GaitType = 5) THEN ;Tripod 8 steps
LRGaitLegNr = 5
RFGaitLegNr = 1
LMGaitLegNr = 1
RRGaitLegNr = 1
LFGaitLegNr = 5
RMGaitLegNr = 5
NrLiftedPos = 3
HalfLiftHeigth = TRUE
TLDivFactor = 4
StepsInGait = 8
NomGaitSpeed = 110
ENDIF
IF (GaitType = 6) THEN ;Wave 12 steps
LRGaitLegNr = 7
RFGaitLegNr = 1
LMGaitLegNr = 9
RRGaitLegNr = 5
LFGaitLegNr = 11
RMGaitLegNr = 3
NrLiftedPos = 1
HalfLiftHeigth = FALSE
TLDivFactor = 10
StepsInGait = 12
NomGaitSpeed = 120
ENDIF
IF (GaitType = 7) THEN ;Wave 18 steps
LRGaitLegNr = 10
RFGaitLegNr = 1
LMGaitLegNr = 13
RRGaitLegNr = 7
LFGaitLegNr = 16
RMGaitLegNr = 4
NrLiftedPos = 2
HalfLiftHeigth = FALSE
TLDivFactor = 16
StepsInGait = 18
NomGaitSpeed = 100
ENDIF
return
;--------------------------------------------------------------------
;[GAIT Sequence]
GaitSeq
;Calculate Gait sequence
LastLeg = FALSE
GOSUB Gait [LRGaitLegNr, LRGaitPosX, LRGaitPosY, LRGaitPosZ, LRGaitRotY]
LRGaitPosX = GaitPosX
LRGaitPosY = GaitPosY
LRGaitPosZ = GaitPosZ
LRGaitRotY = GaitRotY
GOSUB Gait [RFGaitLegNr, RFGaitPosX, RFGaitPosY, RFGaitPosZ, RFGaitRotY]
RFGaitPosX = GaitPosX
RFGaitPosY = GaitPosY
RFGaitPosZ = GaitPosZ
RFGaitRotY = GaitRotY
GOSUB Gait [LMGaitLegNr, LMGaitPosX, LMGaitPosY, LMGaitPosZ, LMGaitRotY]
LMGaitPosX = GaitPosX
LMGaitPosY = GaitPosY
LMGaitPosZ = GaitPosZ
LMGaitRotY = GaitRotY
GOSUB Gait [RRGaitLegNr, RRGaitPosX, RRGaitPosY, RRGaitPosZ, RRGaitRotY]
RRGaitPosX = GaitPosX
RRGaitPosY = GaitPosY
RRGaitPosZ = GaitPosZ
RRGaitRotY = GaitRotY
GOSUB Gait [LFGaitLegNr, LFGaitPosX, LFGaitPosY, LFGaitPosZ, LFGaitRotY]
LFGaitPosX = GaitPosX
LFGaitPosY = GaitPosY
LFGaitPosZ = GaitPosZ
LFGaitRotY = GaitRotY
LastLeg = TRUE
GOSUB Gait [RMGaitLegNr, RMGaitPosX, RMGaitPosY, RMGaitPosZ, RMGaitRotY]
RMGaitPosX = GaitPosX
RMGaitPosY = GaitPosY
RMGaitPosZ = GaitPosZ
RMGaitRotY = GaitRotY
return
;--------------------------------------------------------------------
;[GAIT]
Gait [GaitLegNr, GaitPosX, GaitPosY, GaitPosZ, GaitRotY]
;Check IF the Gait is in motion
GaitInMotion = ((ABS(TravelLengthX)>TravelDeadZone) | (ABS(TravelLengthZ)>TravelDeadZone) | (ABS(TravelRotationY)>TravelDeadZone) )
;Leg middle up position
;Gait in motion Gait NOT in motion, return to home position
IF (GaitInMotion & (NrLiftedPos=1 | NrLiftedPos=3) & GaitStep=GaitLegNr) | (GaitInMotion=FALSE & GaitStep=GaitLegNr & ((ABS(GaitPosX)>2) | (ABS(GaitPosZ)>2) | (ABS(GaitRotY)>2))) THEN ;Up
GaitPosX = 0
GaitPosY = -LegLiftHeight
GaitPosZ = 0
GaitRotY = 0
ELSE
;Optional Half heigth Rear
IF ((NrLiftedPos=2 & GaitStep=GaitLegNr) | (NrLiftedPos=3 & (GaitStep=GaitLegNr-1 | GaitStep=GaitLegNr+(StepsInGait-1)))) & GaitInMotion THEN
GaitPosX = -TravelLengthX/2
GaitPosY = -LegLiftHeight/(HalfLiftHeigth+1)
GaitPosZ = -TravelLengthZ/2
GaitRotY = -TravelRotationY/2
ELSE
;Optional half heigth front
IF (NrLiftedPos>=2) & (GaitStep=GaitLegNr+1 | GaitStep=GaitLegNr-(StepsInGait-1)) & GaitInMotion THEN
GaitPosX = TravelLengthX/2
GaitPosY = -LegLiftHeight/(HalfLiftHeigth+1)
GaitPosZ = TravelLengthZ/2
GaitRotY = TravelRotationY/2
ELSE
;Leg front down position
IF (GaitStep=GaitLegNr+NrLiftedPos | GaitStep=GaitLegNr-(StepsInGait-NrLiftedPos)) & GaitPosY<0 THEN
GaitPosX = TravelLengthX/2
GaitPosY = 0
GaitPosZ = TravelLengthZ/2
GaitRotY = TravelRotationY/2
;Move body forward
ELSE
GaitPosX = GaitPosX - (TravelLengthX/TLDivFactor)
GaitPosY = 0
GaitPosZ = GaitPosZ - (TravelLengthZ/TLDivFactor)
GaitRotY = GaitRotY - (TravelRotationY/TLDivFactor)
ENDIF
ENDIF
ENDIF
ENDIF
;Advance to the next step
IF LastLeg THEN ;The last leg in this step
GaitStep = GaitStep+1
IF GaitStep>StepsInGait THEN
GaitStep = 1
ENDIF
ENDIF
return
;--------------------------------------------------------------------
;[BalCalcOneLeg]
BalCalcOneLeg [PosX, PosZ, PosY, BodyOffsetX, BodyOffsetZ]
;Calculating totals from center of the body to the feet
TotalZ = BodyOffsetZ+PosZ
TotalX = BodyOffsetX+PosX
TotalY = 150 + PosY' using the value 150 to lower the centerpoint of rotation 'BodyPosY +
TotalTransY = TotalTransY + PosY
TotalTransZ = TotalTransZ + TotalZ
TotalTransX = TotalTransX + TotalX
gosub GetBoogTan [TotalX, TotalZ]
TotalYbal = TotalYbal + TOINT((BoogTan*180.0) / 3.141592)
gosub GetBoogTan [TotalX, TotalY]
TotalZbal = TotalZbal + TOINT((BoogTan*180.0) / 3.141592)
gosub GetBoogTan [TotalZ, TotalY]
TotalXbal = TotalXbal + TOINT((BoogTan*180.0) / 3.141592)
'serout S_OUT, i9600, "BalOneLeg PosX=", sdec PosX," PosZ=", sdec PosZ," TotalXTransZ=", sdec TotalTransZ, 13]
return
;--------------------------------------------------------------------
;[BalanceBody]
BalanceBody:
TotalTransZ = TotalTransZ/6
TotalTransX = TotalTransX/6
TotalTransY = TotalTransY/6
if TotalYbal < -180 then 'Tangens fix caused by +/- 180 deg
TotalYbal = TotalYbal + 360
endif
if TotalZbal < -180 then 'Tangens fix caused by +/- 180 deg
TotalZbal = TotalZbal + 360
endif
if TotalXbal < -180 then 'Tangens fix caused by +/- 180 deg
TotalXbal = TotalXbal + 360
endif
;Balance rotation
TotalYBal = TotalYbal/6
TotalXBal = TotalXbal/6
TotalZBal = -TotalZbal/6
;Balance translation
LFGaitPosZ = LFGaitPosZ - TotalTransZ
LMGaitPosZ = LMGaitPosZ - TotalTransZ
LRGaitPosZ = LRGaitPosZ - TotalTransZ
RFGaitPosZ = RFGaitPosZ - TotalTransZ
RMGaitPosZ = RMGaitPosZ - TotalTransZ
RRGaitPosZ = RRGaitPosZ - TotalTransZ
LFGaitPosX = LFGaitPosX - TotalTransX
LMGaitPosX = LMGaitPosX - TotalTransX
LRGaitPosX = LRGaitPosX - TotalTransX
RFGaitPosX = RFGaitPosX - TotalTransX
RMGaitPosX = RMGaitPosX - TotalTransX
RRGaitPosX = RRGaitPosX - TotalTransX
LFGaitPosY = LFGaitPosY - TotalTransY
LMGaitPosY = LMGaitPosY - TotalTransY
LRGaitPosY = LRGaitPosY - TotalTransY
RFGaitPosY = RFGaitPosY - TotalTransY
RMGaitPosY = RMGaitPosY - TotalTransY
RRGaitPosY = RRGaitPosY - TotalTransY
return
;--------------------------------------------------------------------
;[GETSINCOS] Get the sinus and cosinus from the angle +/- multiple circles
;AngleDeg - Input Angle in degrees
;SinA - Output Sinus of AngleDeg
;CosA - Output Cosinus of AngleDeg
GetSinCos [AngleDeg]
;Get the absolute value of AngleDeg
IF AngleDeg < 0.0 THEN
ABSAngleDeg = AngleDeg *-1.0
ELSE
ABSAngleDeg = AngleDeg
ENDIF
;Shift rotation to a full circle of 360 deg -> AngleDeg // 360
IF AngleDeg < 0.0 THEN ;Negative values
AngleDeg = 360.0-(ABSAngleDeg-TOFLOAT(360*(TOINT(ABSAngleDeg/360.0))))
ELSE ;Positive values
AngleDeg = ABSAngleDeg-TOFLOAT(360*(TOINT(ABSAngleDeg/360.0)))
ENDIF
IF AngleDeg < 180.0 THEN ;Angle between 0 and 180
;Subtract 90 to shift range
AngleDeg = AngleDeg -90.0
;Convert degree to radials
AngleRad = (AngleDeg*3.141592)/180.0
SinA = FCOS(AngleRad) ;Sin o to 180 deg = cos(Angle Rad - 90deg)
CosA = -FSIN(AngleRad) ;Cos 0 to 180 deg = -sin(Angle Rad - 90deg)
ELSE ;Angle between 180 and 360
;Subtract 270 to shift range
AngleDeg = AngleDeg -270.0
;Convert degree to radials
AngleRad = (AngleDeg*3.141592)/180.0
SinA = -FCOS(AngleRad) ;Sin 180 to 360 deg = -cos(Angle Rad - 270deg)
CosA = FSIN(AngleRad) ;Cos 180 to 360 deg = sin(Angle Rad - 270deg)
ENDIF
return
;--------------------------------------------------------------------
;[BOOGTAN2] Gets the Inverse Tangus from X/Y with the where Y can be zero or negative
;BoogTanX - Input X
;BoogTanY - Input Y
;BoogTan - Output BOOGTAN2(X/Y)
GetBoogTan [BoogTanX, BoogTanY]
IF(BoogTanX = 0) THEN ; X=0 -> 0 or PI
IF(BoogTanY >= 0) THEN
BoogTan = 0.0
ELSE
BoogTan = 3.141592
ENDIF
ELSE
IF(BoogTanY = 0) THEN ; Y=0 -> +/- Pi/2
IF(BoogTanX > 0) THEN
BoogTan = 3.141592 / 2.0
ELSE
BoogTan = -3.141592 / 2.0
ENDIF
ELSE
IF(BoogTanY > 0) THEN ;BOOGTAN(X/Y)
BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY))
ELSE
IF(BoogTanX > 0) THEN ;BOOGTAN(X/Y) + PI
BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY)) + 3.141592
ELSE ;BOOGTAN(X/Y) - PI
BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY)) - 3.141592
ENDIF
ENDIF
ENDIF
ENDIF
return
;--------------------------------------------------------------------
;[BODY INVERSE KINEMATICS]
;BodyRotX - Global Input pitch of the body
;BodyRotY - Global Input rotation of the body
;BodyRotZ - Global Input roll of the body
;RotationY - Input Rotation for the gait
;PosX - Input position of the feet X
;PosZ - Input position of the feet Z
;BodyOffsetX - Input Offset betweeen the body and Coxa X
;BodyOffsetZ - Input Offset betweeen the body and Coxa Z
;SinB - Sin buffer for BodyRotX
;CosB - Cos buffer for BodyRotX
;SinG - Sin buffer for BodyRotZ
;CosG - Cos buffer for BodyRotZ
;BodyIKPosX - Output Position X of feet with Rotation
;BodyIKPosY - Output Position Y of feet with Rotation
;BodyIKPosZ - Output Position Z of feet with Rotation
BodyIK [PosX, PosZ, PosY, BodyOffsetX, BodyOffsetZ, RotationY]
;Calculating totals from center of the body to the feet
TotalZ = BodyOffsetZ+PosZ
TotalX = BodyOffsetX+PosX
;PosY are equal to a "TotalY"
;Successive global rotation matrix:
;Math shorts for rotation: Alfa (A) = Xrotate, Beta (B) = Zrotate, Gamma (G) = Yrotate
;Sinus Alfa = sinA, cosinus Alfa = cosA. and so on...
;First calculate sinus and cosinus for each rotation:
GOSUB GetSinCos [TOFLOAT(BodyRotX+TotalXBal)]
SinG = SinA
CosG = CosA
GOSUB GetSinCos [TOFLOAT(BodyRotZ+TotalZBal)]
SinB = SinA
CosB = CosA
GOSUB GetSinCos [TOFLOAT(BodyRotY+RotationY+TotalYBal)]
;Calcualtion of rotation matrix:
BodyIKPosX = TotalX-TOINT(TOFLOAT(TotalX)*CosA*CosB - TOFLOAT(TotalZ)*CosB*SinA + TOFLOAT(PosY)*SinB)
BodyIKPosZ = TotalZ-TOINT(TOFLOAT(TotalX)*CosG*SinA + TOFLOAT(TotalX)*CosA*SinB*SinG +TOFLOAT(TotalZ)*CosA*CosG-TOFLOAT(TotalZ)*SinA*SinB*SinG-TOFLOAT(PosY)*CosB*SinG)
BodyIKPosY = PosY - TOINT(TOFLOAT(TotalX)*SinA*SinG - TOFLOAT(TotalX)*CosA*CosG*SinB + TOFLOAT(TotalZ)*CosA*SinG + TOFLOAT(TotalZ)*CosG*SinA*SinB + TOFLOAT(PosY)*CosB*CosG)
return
;--------------------------------------------------------------------
;[LEG INVERSE KINEMATICS] Calculates the angles of the tibia and femur for the given position of the feet
;IKFeetPosX - Input position of the Feet X
;IKFeetPosY - Input position of the Feet Y
;IKFeetPosZ - Input Position of the Feet Z
;IKSolution - Output true IF the solution is possible
;IKSolutionWarning - Output true IF the solution is NEARLY possible
;IKSolutionError - Output true IF the solution is NOT possible
;IKFemurAngle - Output Angle of Femur in degrees
;IKTibiaAngle - Output Angle of Tibia in degrees
;IKCoxaAngle - Output Angle of Coxa in degrees
LegIK [IKFeetPosX, IKFeetPosY, IKFeetPosZ]
;Length between the Coxa and Feet
IKFeetPosXZ = TOINT(FSQRT(TOFLOAT((IKFeetPosX*IKFeetPosX)+(IKFeetPosZ*IKFeetPosZ))))
;IKSW - Length between shoulder and wrist
IKSW = FSQRT(TOFLOAT(((IKFeetPosXZ-CoxaLength)*(IKFeetPosXZ-CoxaLength))+(IKFeetPosY*IKFeetPosY)))
;IKA1 - Angle between SW line and the ground in rad
GOSUB GetBoogTan [IKFeetPosXZ-CoxaLength, IKFeetPosY]
IKA1 = BoogTan
;IKA2 - ?
IKA2 = FACOS((TOFLOAT((FemurLength*FemurLength) - (TibiaLength*TibiaLength)) + (IKSW*IKSW)) / (TOFLOAT(2*Femurlength) * IKSW))
;IKFemurAngle
IKFemurAngle = (TOINT(((IKA1 + IKA2) * 180.0) / 3.141592)*-1)+90
;IKTibiaAngle
IKTibiaAngle = (90-TOINT(((FACOS((TOFLOAT((FemurLength*FemurLength) + (TibiaLength*TibiaLength)) - (IKSW*IKSW)) / TOFLOAT(2*Femurlength*TibiaLength)))*180.0) / 3.141592)) * -1
;IKCoxaAngle
GOSUB GetBoogTan [IKFeetPosZ, IKFeetPosX]
IKCoxaAngle = TOINT((BoogTan*180.0) / 3.141592)
;Set the Solution quality
IF(IKSW < TOFLOAT(FemurLength+TibiaLength-30)) THEN
IKSolution = TRUE
ELSE
IF(IKSW < TOFLOAT(FemurLength+TibiaLength)) THEN
IKSolutionWarning = TRUE
ELSE
IKSolutionError = TRUE
ENDIF
ENDIF
return
;--------------------------------------------------------------------
;[CHECK ANGLES] Checks the mechanical limits of the servos
CheckAngles:
RFCoxaAngle = (RFCoxaAngle min RFCoxa_MIN) max RFCoxa_MAX
RFFemurAngle = (RFFemurAngle min RFFemur_MIN) max RFFemur_MAX
RFTibiaAngle = (RFTibiaAngle min RFTibia_MIN) max RFTibia_MAX
RMCoxaAngle = (RMCoxaAngle min RMCoxa_MIN) max RMCoxa_MAX
RMFemurAngle = (RMFemurAngle min RMFemur_MIN) max RMFemur_MAX
RMTibiaAngle = (RMTibiaAngle min RMTibia_MIN) max RMTibia_MAX
RRCoxaAngle = (RRCoxaAngle min RRCoxa_MIN) max RRCoxa_MAX
RRFemurAngle = (RRFemurAngle min RRFemur_MIN) max RRFemur_MAX
RRTibiaAngle = (RRTibiaAngle min RRTibia_MIN) max RRTibia_MAX
LFCoxaAngle = (LFCoxaAngle min LFCoxa_MIN) max LFCoxa_MAX
LFFemurAngle = (LFFemurAngle min LFFemur_MIN) max LFFemur_MAX
LFTibiaAngle = (LFTibiaAngle min LFTibia_MIN) max LFTibia_MAX
LMCoxaAngle = (LMCoxaAngle min LMCoxa_MIN) max LMCoxa_MAX
LMFemurAngle = (LMFemurAngle min LMFemur_MIN) max LMFemur_MAX
LMTibiaAngle = (LMTibiaAngle min LMTibia_MIN) max LMTibia_MAX
LRCoxaAngle = (LRCoxaAngle min LRCoxa_MIN) max LRCoxa_MAX
LRFemurAngle = (LRFemurAngle min LRFemur_MIN) max LRFemur_MAX
LRTibiaAngle = (LRTibiaAngle min LRTibia_MIN) max LRTibia_MAX
return
;--------------------------------------------------------------------
;[SERVO DRIVER] Updates the positions of the servos
ServoDriver:
;Front Right leg
serout SSC_OUT,SSC_BAUTE,"#",dec RFCoxaPin,"P",dec TOINT(TOFLOAT(-RFCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RFFemurPin,"P",dec TOINT(TOFLOAT(-RFFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RFTibiaPin,"P",dec TOINT(TOFLOAT(-RFTibiaAngle+90)/0.10588238)+650]
;Middle Right leg
serout SSC_OUT,SSC_BAUTE,"#",dec RMCoxaPin,"P",dec TOINT(TOFLOAT(-RMCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RMFemurPin,"P",dec TOINT(TOFLOAT(-RMFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RMTibiaPin,"P",dec TOINT(TOFLOAT(-RMTibiaAngle+90)/0.10588238)+650]
;Rear Right leg
serout SSC_OUT,SSC_BAUTE,"#",dec RRCoxaPin,"P",dec TOINT(TOFLOAT(-RRCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RRFemurPin,"P",dec TOINT(TOFLOAT(-RRFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec RRTibiaPin,"P",dec TOINT(TOFLOAT(-RRTibiaAngle+90)/0.10588238)+650]
;Front Left leg
serout SSC_OUT,SSC_BAUTE,"#",dec LFCoxaPin,"P",dec TOINT(TOFLOAT(LFCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LFFemurPin,"P",dec TOINT(TOFLOAT(LFFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LFTibiaPin ,"P",dec TOINT(TOFLOAT(LFTibiaAngle+90)/0.10588238)+650]
;Middle Left leg
serout SSC_OUT,SSC_BAUTE,"#",dec LMCoxaPin,"P",dec TOINT(TOFLOAT(LMCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LMFemurPin,"P",dec TOINT(TOFLOAT(LMFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LMTibiaPin,"P",dec TOINT(TOFLOAT(LMTibiaAngle+90)/0.10588238)+650]
;Rear Left leg
serout SSC_OUT,SSC_BAUTE,"#",dec LRCoxaPin,"P",dec TOINT(TOFLOAT(LRCoxaAngle +90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LRFemurPin,"P",dec TOINT(TOFLOAT(LRFemurAngle+90)/0.10588238)+650]
serout SSC_OUT,SSC_BAUTE,"#",dec LRTibiaPin,"P",dec TOINT(TOFLOAT(LRTibiaAngle+90)/0.10588238)+650]
;Send <CR>
serout SSC_OUT,SSC_BAUTE,"T",dec SSCTime,13]
PrevSSCTime = SSCTime
return
;--------------------------------------------------------------------
;[FREE SERVOS] Frees all the servos
FreeServos
for Index = 0 to 31
serout SSC_OUT,SSC_BAUTE,"#",DEC Index,"P0"]
next
serout SSC_OUT,SSC_BAUTE,"T200",13]
return
;-----------------------------------------------------------------------------------
;[Handle TimerW interrupt]
BEGINASMSUB
HANDLE_TIMERW
push.w r1 ; save away register we will use
bclr #7,@TSRW:8 ; clear the overflow bit in the Timer status word
mov.w @LTIMERWOVERFLOWCNT+1:16,r1 ; We will increment the word that is the highword for a clock timer
inc.w #1,r1
mov.w r1, @LTIMERWOVERFLOWCNT+1:16
pop.w r1 ; restore our registers
rte ; and return
return
;-------------------------------------------------------------------------------------
;[Simple function to get the current time and verify that no overflow happened]
GetCurrentTime
lCurrentTime = lTimerWoverflowCnt + TCNT ; calculate the timer
IF lCurrentTime.highword <> lTimerWOverflowcnt.highword THEN
lCurrentTime = lTimerWoverflowCnt + TCNT ; calculate the timer
ENDIF
return lCurrentTIme
;--------------------------------------------------------------------
;GP player
GPPlayer
if (GPIsPlaying = FALSE) & (GPoccupied = FALSE) then
serout SSC_OUT,SSC_BAUTE,"PL0 SQ", dec GPSeqToBePlayed, " SM" , dec GPSpeed, " IX0 PA0 ONCE",13]
GPIsPlaying = TRUE
GPoccupied = TRUE 'This inhibit the player to play the same sequence several times
else
serout SSC_OUT,SSC_BAUTE,"QPL0",13]
serin SSC_IN, SSC_BAUTE,[GPByte0,GPByte1,GPByte2,GPByte3]
;debug:
'serout S_OUT, i9600, "SQPlayed: ",dec GPByte0," IX: ", dec GPByte2," -> ",dec GPByte1," Remaining time: ",dec GPByte3, 13]
IF GPByte0 = 255 THEN
GPIsPlaying = FALSE
endif
endif
return
;-----------------------------------------------------------------------------------
This is the part I am concerned with and would like to replace GP player with my own code
;*************************************************************************************
;*** GP sequencer player mode choose between two different seq with 2-state button ***
;*************************************************************************************
elseif GPModeON
'GPoccupied = TRUE
if TwoStateSW then 'Use 2-state switch to toogle between every sequence
if GPIsPlaying = FALSE then
if GPSeqToBePlayed < 2 then
GPSeqToBePlayed = GPSeqToBePlayed +1
else
GPSeqToBePlayed = 0 'Selected GP sequence
endif
for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
pause 150
sound P9,[70\1200]
next
endif
endif
if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
GPoccupied = FALSE
sound P9,[30\800,30\1000,30\1200,30\1400]
endif
GPSpeed = 100
endif
BodyPosY = (RCInput(2)-1000)/8 'adjust body height
;Calculate walking time delay
InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-1010)/8)
'ENDIF
And then this is what I did to it, notice I have commented things out with double ;; zenta’s work is only commented out with 1 ;
;*************************************************************************************
;*** GP sequencer player mode choose between two different seq with 2-state button ***
;*************************************************************************************
elseif GPModeON
'GPoccupied = TRUE
;if TwoStateSW then 'Use 2-state switch to toogle between every sequence
;;if GPIsPlaying = FALSE then
;;if GPSeqToBePlayed < 2 then
;;GPSeqToBePlayed = GPSeqToBePlayed +1
;;else
;;GPSeqToBePlayed = 0 'Selected GP sequence
;;endif
;;for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
;;pause 150
sound P9,[70\1200]
;;next
;;endif
;;endif
;;if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
;;GPoccupied = FALSE
;;sound P9,[30\800,30\1000,30\1200,30\1400]
;;endif
;;GPSpeed = 100
;;endif
;;BodyPosY = (RCInput(2)-1000)/8 'adjust body height
;Calculate walking time delay
;;InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-910)/8)
ENDIF
return
so Zenta had sent me a PM to assist me in trying to figure out why this doesn’t work and told me that in the main loop of the code comment out these two pieces of code
'Check if we are in GPMode
if (GPModeON OR GPIsPlaying) = FALSE then
and
'We are in GPMode:
else
gosub GPPlayer
pause 60
endif
Ok so Ive done this and Still I can’t raise and lower my phoenix
How’s that for the longest post in thread history!
anyway let me know what you guys think.
–Aaron