Mecanum Wheeled Robot with Machine Vision

12346

Comments

  • amano001amano001 Posts: 47
    edited 2013-03-15 - 23:52:01
    Hey Duane, I seem to be having an issue with the robot autodriving sometimes. I tried to comment out some things that I thought might be causing it to start on its own and also I changed the couple things you had mentioned that might cause the autodriving from earlier posts but it still seems to start up sometimes by itself.

    Here are some things I commented out to try and make it stop:

    This whole function I commented out basically

    PRI AutoDrive(localCommand, localIndex)

    InputNoticed
    'previousThrottle := channel[Control#THROTTLE_CHANNEL]
    { if keyboardFlag
    'InputNoticed
    'Bot.RefreshSpeeds
    elseif inputFlag }
    ' if keyboardFlag == 0 and inputFlag == 0 ' auto mode //might need this

    ' globalIndex := localIndex
    ' repeat
    ' if InputNoticed
    ' quit
    ' if localCommand == TURN_COMMAND
    ' Bot.Turn(speed, turnRate)
    ' elseif localCommand == STRAIGHT_COMMAND
    ' Bot.Straight(speed)
    ' result := ||(previousThrottle - channel[Control#THROTTLE_CHANNEL])
    ' while globalIndex > 0 and throttleChangeFlag == 0

    ' previousThrottle := channel[Control#THROTTLE_CHANNEL]
    'if throttleChangeFlag and cnt - throttleTimer > ignoreThrottleInterval
    ' throttleChangeFlag := 0 //till here might need this
    {PUB OmniLoop | localIndex, localRotation, previousGIndex

    pDebubFlag := debugFlag
    debugFlag := 1
    localIndex := Header#STEPS_PER_FIGURE_8 / 2
    localRotation := 0 '600
    pseudoIncrement := PSEUDO_CIRCLE / localIndex '112

    repeat
    InputNoticed
    if keyboardFlag == 0 and inputFlag == 0
    'result := Bot.Straight(0)
    psuedoMagnitude := 0
    Control.ComputeTargetSpeeds(psuedoMagnitude, psuedoAngle)
    'previousThrottle := channel[Control#THROTTLE_CHANNEL]
    globalIndex := localIndex
    previousGIndex := localIndex
    repeat
    if InputNoticed
    quit

    repeat while globalIndex == previousGIndex
    previousGIndex-- ' ** not sure about this
    psuedoAngle := Control.IncrementAngle(psuedoAngle, pseudoIncrement)
    Control.ComputeTargetSpeeds(psuedoMagnitude, psuedoAngle)
    while previousGIndex > 0
    if keyboardFlag == 0 and inputFlag == 0
    globalIndex := localIndex
    previousGIndex := localIndex

    repeat
    if InputNoticed
    quit

    repeat while globalIndex == previousGIndex
    previousGIndex--
    psuedoAngle := Control.IncrementAngle(psuedoAngle, pseudoIncrement)
    Control.Refresh
    while previousGIndex > 0

    globalIndex := 800
    previousGIndex := 800
    psuedoMagnitude := 0
    psuedoAngle := Header#DEFAULT_COURSE * Header#PSEUDOREAL_MULTIPLIER

    Control.ComputeTargetSpeeds(psuedoMagnitude, psuedoAngle)
    'localRotation := 0
    if keyboardFlag == 0 and inputFlag == 0
    repeat
    if InputNoticed
    quit

    repeat while globalIndex == previousGIndex
    previousGIndex--
    while previousGIndex > 0
    repeat while keyboardFlag == 0 and inputFlag == 0 ' just do loop once
    InputNoticed
    'else
    if inputFlag
    ''**Control.Refresh'(Input#ZERO_CENTER_RANGE)
    '**Control.SpeedFromXY'(channel[Input#X_CHANNEL],
    ' channel[Input#Y_CHANNEL], Motion#RC_INPUT)
    'pDebubFlag := debugFlag
    'debugFlag := 2
    Bot.RefreshSpeeds
    }

    also this stuff in main loop

    ' repeat
    ' speed := Header#DEFAULT_SPEED
    ' turnRate := Header#DEFAULT_TURN_RATE
    ' AutoDrive(TURN_COMMAND, localIndex)
    'speed := Header#DEFAULT_SPEED
    ' turnRate := -Header#DEFAULT_TURN_RATE
    ' AutoDrive(TURN_COMMAND, localIndex)
    'speed := 200
    ' turnRate := Header#DEFAULT_TURN_RATE

    ' AutoDrive(STRAIGHT_COMMAND, 200)
    ' speed := 0
    'turnRate := Header#DEFAULT_TURN_RATE

    ' AutoDrive(STRAIGHT_COMMAND, 200)


    ' repeat while keyboardFlag == 0 and inputFlag == 0 ' just do loop once
    ' AutoDrive(STRAIGHT_COMMAND, Header#REFRESH_RATE / 2) '** don't really like this

    I had changed the keyboard flag to 1 like you had said in a previous post. Not sure what else it could be.
  • amano001amano001 Posts: 47
    edited 2013-03-15 - 23:58:09
    Now on to the fun stuff. Here is the code I have added to accept my serial stuff from Arduino

    Parallax Code:

    repeat
    if Pst.CharIn == "!" 'Starting Char
    case Pst.CharIn '-1000 to 1000 Speeds
    "W":
    Bot.Straight(300) 'Positive Straight
    "D":
    Bot.SideWays(500) ' Positive Right
    "X":
    Bot.Straight(0) ' Stop
    "S":
    Bot.Straight(-500) 'Negative Backwards
    "A":
    Bot.SideWays(-500) ' Negative Left
    "Q":
    Bot.StrBreakLeft(300)'StrBrake Left
    "E": 'StrBrake Right
    Bot.StrBreakRight(300)
    "Z": 'SideBrake Left
    Bot.SideBreakForward(300)
    "C": 'SideBreak Right
    Bot.SideBreakRear(300)
    "F": 'Turn Left
    Bot.TurnLeft(300)
    "G": 'Turn Right
    Bot.TurnRight(300)

    Here is stuff from the fourmotor encoder file

    PRI StraightPrivate

    repeat result from 0 to HIGHEST_MOTOR_ID
    long[targetPtr][result] := globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD ' since target speeds have now been set

    PRI SideWaysPrivate


    long[targetPtr][0] := -globalSpeed
    long[targetPtr][1] := globalSpeed
    long[targetPtr][2] := -globalSpeed
    long[targetPtr][3] := globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD

    PRI TurnRightPrivate
    long[targetPtr][0] := globalSpeed
    long[targetPtr][1] := globalSpeed
    long[targetPtr][2] := -globalSpeed
    long[targetPtr][3] := -globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD
    PRI TurnLeftPrivate
    long[targetPtr][0] := -globalSpeed
    long[targetPtr][1] := -globalSpeed
    long[targetPtr][2] := globalSpeed
    long[targetPtr][3] := globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD

    //all of these are for error correction if using a compass or in our case we are using two ultrasonics to stay parallel to a wall. We decided that we would need to break certain sets of wheels to correct if it was veering off //course. There might be a better way to do this not sure yet.
    PRI StrBreakLeftPrivate
    long[targetPtr][0] := globalSpeed * 0.9
    long[targetPtr][1] := globalSpeed * 0.9
    long[targetPtr][2] := globalSpeed
    long[targetPtr][3] := globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD
    PRI StrBreakRightPrivate
    long[targetPtr][0] := globalSpeed
    long[targetPtr][1] := globalSpeed
    long[targetPtr][2] := globalSpeed * 0.9
    long[targetPtr][3] := globalSpeed * 0.9
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD
    PRI SideBreakForwardPrivate
    long[targetPtr][0] := -globalSpeed
    long[targetPtr][1] := globalSpeed * 0.9
    long[targetPtr][2] := -globalSpeed * 0.9
    long[targetPtr][3] := globalSpeed
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD
    PRI SideBreakRearPrivate
    long[targetPtr][0] := -globalSpeed * 0.9
    long[targetPtr][1] := globalSpeed
    long[targetPtr][2] := -globalSpeed
    long[targetPtr][3] := globalSpeed * 0.9
    SetSpeedsPrivate
    command := INDIVIDUAL_CMD


    PRI MainLoop
    '' This loop runs in its own cog. Control of object is done
    '' by setting the variable "command" through public methods.
    repeat
    case command
    SIDEWAYS_CMD:
    SideWaysPrivate
    STRAIGHT_CMD:
    StraightPrivate
    TURN_CMD:
    TurnPrivate
    TURNRIGHT_CMD:
    TurnRightPrivate
    TURNLEFT_CMD:
    TurnLeftPrivate
    STRBREAKLEFT_CMD:
    StrBreakLeftPrivate
    STRBREAKRIGHT_CMD:
    StrBreakRightPrivate
    SIDEBREAKFORWARD_CMD:
    SideBreakForwardPrivate
    SIDEBREAKREAR_CMD:
    SideBreakRearPrivate
    INDIVIDUAL_CMD:
    SetSpeedsPrivate
    'other: 'NO_NEW_CMD



    'result := @targetSpeed
    PUB SideWays(localspeed)
    globalSpeed := localSpeed
    command := STRAIGHT_CMD




    PUB TurnRight(localspeed)
    globalSpeed := localSpeed
    command := TURNRIGHT_CMD
    PUB TurnLeft(localspeed)
    globalSpeed := localSpeed
    command := TURNLEFT_CMD
    PUB StrBreakLeft(localspeed)
    globalSpeed := localSpeed
    command := STRBREAKLEFT_CMD
    PUB StrBreakRight(localspeed)
    globalSpeed := localSpeed
    command := STRBREAKRIGHT_CMD
    PUB SideBreakForward(localspeed)
    globalSpeed := localSpeed
    command := SIDEBREAKFORWARD_CMD
    PUB SideBreakRear(localspeed)
    globalSpeed := localSpeed
    command := SIDEBREAKREAR_CMD

    Now my arduino code is just serial commands that I send:

    Serial.print('!'); //this is to make sure parallax knows its an actual movement command
    Serial.print('W'); //this would just cause it to go forward at a certain speed.

    at the moment I dont have it taking speed and direction commands I just hardcoded those because the serial seemed to be to slow to turn on all four wheels at once, I could have probably created a buffer to store each command that came in and then pass it to the functions above.

    Thanks Duane!
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-03-17 - 10:55:02
    It's great you're modifying the code to suit your needs.

    As you may know, Spin uses indentation as part of its syntax. The forum software removes the indentation unless you use code tags. They're easy to use, but I'll let Phil explain how to use them in the following link.

    attachment.php?attachmentid=78421&d=1297987572

    As I mentioned before, there are still lots of bugs in the code. I didn't really feel like it was ready to be released but I thought having something was better than nothing.

    I'm still working on improving the encoder code to measure the time between encoder pulses instead of just counting encoder pulses within a set time period. Counting pulses works fine when the robot is moving fast, but at slow speed, there aren't enough encoder ticks per 1/50 second refresh period to accurately gauge speed. The guy who designed the Rover 5 suggested I measure the time between pulses to increase the low speed accuracy. I think this should work well but it takes some time to get the kinks worked out.

    Once I have the encoder stuff worked out, I'm going to try to make the code work better when used as a slave.

    You mentioned using a compass. What kind of compass are you using?

    What kind of ultrasound sensor(s) are you using?

    Even though I intend to use a compass and ultrasound with my robot, I'm not sure if it would be helpful to include these devices as part of the slave code. It might be better to have the master board monitor sensors directly but I'm not sure.

    You may find, once you learn enough Spin, that you can do everything you need done with just the Propeller and not need the Arduino at all. IMO, the Propeller is a great microcontroller to know how to use if one is interested in robotics.
  • amano001amano001 Posts: 47
    edited 2013-03-17 - 13:30:11
    How is it going Duane,

    Here is the reposted code in a nicer format thanks for the tip!

    Here is the stuff I have added so far
    repeat
        if Pst.CharIn == "!"           'Starting Char
          case Pst.CharIn              '-1000 to 1000 Speeds
            "W":
              Bot.Straight(300)  'Positive Straight
            "D":                       
              Bot.SideWays(500)  ' Positive Right
            "X":
              Bot.Straight(0)     ' Stop
            "S":
              Bot.Straight(-500)  'Negative Backwards
            "A":
              Bot.SideWays(-500)   ' Negative Left
            "Q":
              Bot.StrBreakLeft(300)'StrBrake Left
            "E":  'StrBrake Right
              Bot.StrBreakRight(300)
            "Z":   'SideBrake Left
              Bot.SideBreakForward(300)
            "C":    'SideBreak Right
              Bot.SideBreakRear(300)
            "F":   'Turn Left
              Bot.TurnLeft(300)
            "G":    'Turn Right
              Bot.TurnRight(300)
    
    and from the fourmotors file
    
    PRI MainLoop
    '' This loop runs in its own cog. Control of object is done
    '' by setting the variable "command" through public methods.
      repeat
        case command
          SIDEWAYS_CMD:
            SideWaysPrivate
          STRAIGHT_CMD:
            StraightPrivate
          TURN_CMD:
            TurnPrivate
          TURNRIGHT_CMD:
            TurnRightPrivate
          TURNLEFT_CMD:
            TurnLeftPrivate
          STRBREAKLEFT_CMD:
            StrBreakLeftPrivate
          STRBREAKRIGHT_CMD:
            StrBreakRightPrivate
          SIDEBREAKFORWARD_CMD:
            SideBreakForwardPrivate
          SIDEBREAKREAR_CMD:
            SideBreakRearPrivate
          INDIVIDUAL_CMD:
            SetSpeedsPrivate
          'other: 'NO_NEW_CMD
    
    PUB TurnRight(localspeed)
    globalSpeed := localSpeed
      command := TURNRIGHT_CMD
    PUB TurnLeft(localspeed)
    globalSpeed := localSpeed
      command := TURNLEFT_CMD
    PUB StrBreakLeft(localspeed)
    globalSpeed := localSpeed
      command := STRBREAKLEFT_CMD
    PUB StrBreakRight(localspeed)
    globalSpeed := localSpeed
      command := STRBREAKRIGHT_CMD
    PUB SideBreakForward(localspeed)
    globalSpeed := localSpeed
      command := SIDEBREAKFORWARD_CMD
    PUB SideBreakRear(localspeed)
    globalSpeed := localSpeed
      command := SIDEBREAKREAR_CMD
    
    PRI SideWaysPrivate
    
     
      long[targetPtr][0] := -globalSpeed
      long[targetPtr][1] := globalSpeed
      long[targetPtr][2] := -globalSpeed
      long[targetPtr][3] := globalSpeed 
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    
    PRI TurnRightPrivate
     long[targetPtr][0] := globalSpeed
      long[targetPtr][1] := globalSpeed
      long[targetPtr][2] := -globalSpeed
      long[targetPtr][3] := -globalSpeed 
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    PRI TurnLeftPrivate
     long[targetPtr][0] := -globalSpeed
      long[targetPtr][1] := -globalSpeed
      long[targetPtr][2] := globalSpeed
      long[targetPtr][3] := globalSpeed 
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    PRI StrBreakLeftPrivate
     long[targetPtr][0] := globalSpeed * 0.9
      long[targetPtr][1] := globalSpeed * 0.9
      long[targetPtr][2] := globalSpeed
      long[targetPtr][3] := globalSpeed 
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    PRI StrBreakRightPrivate
     long[targetPtr][0] := globalSpeed
      long[targetPtr][1] := globalSpeed
      long[targetPtr][2] := globalSpeed * 0.9
      long[targetPtr][3] := globalSpeed  * 0.9
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    PRI SideBreakForwardPrivate
     long[targetPtr][0] := -globalSpeed
      long[targetPtr][1] := globalSpeed * 0.9
      long[targetPtr][2] := -globalSpeed  * 0.9
      long[targetPtr][3] := globalSpeed 
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    PRI SideBreakRearPrivate
     long[targetPtr][0] := -globalSpeed  * 0.9
      long[targetPtr][1] := globalSpeed
      long[targetPtr][2] := -globalSpeed
      long[targetPtr][3] := globalSpeed  * 0.9
      SetSpeedsPrivate
      command := INDIVIDUAL_CMD
    
    
    
    
    

    Yes I definitely agree that the parallax is probably going to become one of my goto boards now that I am starting to get familiar with it. At the moment I just dont know enough about the syntax
    to code with the parallax unfortunately to add all of the things I want to add. I am using ping parallax ultrasonics to measure my distance and also using two one one side to stay parallel with a wall.
    Also when we were trying to write our first PID we would use the time in between pulses of the encoder to compare to a master wheel. Therefore if one wheel was going faster then another
    we were able to tell because the pulses on the master wheel would be much higher etc. We decided to just use the ultrasonics to keep parallel due to compass restrictions of EMF.
    We have a lot of electronics and we have a height restriction on how big the robot can be, so the pole idea that I saw in your video might not work as good.

    Also if you plan to add sensors and what nots it might be better to use it on whatever your master board will be. Serial seems to be a huge pain when trying to send and receive information.

    Do you have any ideas what code might be causing the robot to spaz out sometimes on its own?
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-03-17 - 14:47:34
    amano001 wrote: »
    Yes I definitely agree that the parallax is probably going to become one of my goto boards

    "Parallax" or "Parallax Inc." is the company that sells several different microcontrollers. The Propeller is one of these microcontrollers. Calling the chip or board "Parallax" sounds funny IMO. Not a big deal, but I thought I'd mention it.
    amano001 wrote: »
    At the moment I just dont know enough about the syntax
    to code with the parallax unfortunately to add all of the things I want to add.

    I used C a lot on a PC before I started using Spin on the Propeller. Initially I was disappointed the Propeller didn't use C. It didn't take long for me to prefer Spin over C. There are several versions of C for the Prop but I much prefer Spin now so I haven't switched over to using C.
    amano001 wrote: »
    I am using ping parallax ultrasonics to measure my distance and also using two one one side to stay parallel with a wall.

    Pings are nice since they only need one I/O line. The downside to Pings is their price. There are lots of inexpensive ultrasound sensors that work great but use separate echo and trigger pins. The echo lines of multiple sensors can be combined so it's possible to use four sensors with five I/O pins.
    amano001 wrote: »
    Also when we were trying to write our first PID we would use the time in between pulses of the encoder to compare to a master wheel. Therefore if one wheel was going faster then another
    we were able to tell because the pulses on the master wheel would be much higher etc.

    The object "FourMotorsAndEncoders" does this for you. You just set the target speed and the program increases the PWM or decreases the PWM to bring the wheels to the desired speed. Try setting the speed of one of the wheels and then try to slow the wheel with your hand. The motor will fight your attempt to slow the wheel.

    The control algorithm only uses proportional control. My attempts to add integral or differential didn't improve the motors' behavior. The proportional algorithm is in the "ComputeP" method of the "FourMotorsAndEncoders" object. If you wanted to try to added I. and D. to the P. that's the method to do it. Keep in mind the program uses a timed loop of 20ms so your PID algorithm can assume a constant time period between each update. This is assuming you attempt your PID in the Propeller. Trying to run your PID algoritm from the Arduino will be problematic because of the increased latency from serial signals.
    amano001 wrote: »
    We decided to just use the ultrasonics to keep parallel due to compass restrictions of EMF.
    We have a lot of electronics and we have a height restriction on how big the robot can be, so the pole idea that I saw in your video might not work as good.

    The pole I used was much taller than needed. It was just used the first, relatively short, piece of carbon fiber rod I found. I'll probably use a shorter rod in the future.
    amano001 wrote: »
    Also if you plan to add sensors and what nots it might be better to use it on whatever your master board will be.

    In my case the QuickStart is the master board. I was wondering if it would be beneficial to include sensor information as part of the slave component of the program. I'll probably make sensor information an option if it's not hard for me to include it as part of the slave code.

    I didn't write the program with the intention of having it be used on a slave board. It was just after the fact that I realized there were already aspects of the code that would allowed another uC to control it.
    amano001 wrote: »
    Serial seems to be a huge pain when trying to send and receive information.

    Actually, it's very, very common to have robot components controlled with a serial connection. The Dynamixel robot servos all use a serial interface. I don't think the serial connection itself is the problem here, I think it's one of both of our codes causing the problem.
    amano001 wrote: »
    Do you have any ideas what code might be causing the robot to spaz out sometimes on its own?

    No, it's very possible there's something in the code I posted causing the problem but I'm not completely convinced the problem is on the Propeller side of the setup.

    As I've said, I'm still working on the code and there's lots of things about it that will be changing.
  • amano001amano001 Posts: 47
    edited 2013-03-17 - 15:14:06
    Thanks for the info duane, I will keep looking into whats causing the robot to auto move. Maybe its picking up junk in the serial? But it woud be odd to pick up a '!' and then character right after that would cause it to move from my functions. I know you had some code that would cause it to automove when it had not received any input after a set amount of time. But I thought I commented most of that out from mainloop in demo4wd. Im sure the serial issues I am having is due to the way I am handling the commands being received since I can't at the moment code in my own buffers to store and parse the info coming in I am just relying on the propeller buffer.

    Also yes I know the propeller board not parallax SEMANTICS I SAY!!!!!

    Yes I enjoy C, I eally would like to learn python one day. Spin seems interesting OOP and will most likely start using it more. Arduino has huge limitations when it comes to speed.
  • amano001amano001 Posts: 47
    edited 2013-03-26 - 14:00:59
    So I got the ghost to stop finally lol. We are now having it follow walls very good with some new code we wrote. The serial seems to be responding great to just single or double character inputs. like 'W' or "!W". Our computer vision is working but very slow at the moment only 2fps so we are trying to figure out how to get it to work faster. I will post some videos soon as we get more testing in.
  • CliffoCliffo Posts: 12
    edited 2013-03-28 - 00:46:51
    Hi Duane,

    I finally made some progress with the next phase of the Rover 5-controlling Java program that runs in my laptop.

    I wanted to create a mapping between a given PWM value sent to the motors, and the resulting EncoderCounts/sec. that they output. To have a better chance of ending up with an observable, repeatable curve, I did 11 test runs, running through PWM values of 30-255 each time.

    As you can see below, each run has various odd gaps and shifts, which I'm imagining are due to my evolving data collection methodology (I had 50-100 hours of opportunities to evolve it, ugh), and perhaps related to the battery voltage differing for each test run, and decreasing during each one as well:

    NavScreen-Data Graph-130327-full+255.jpg
    NavScreen-Data Graph-130327-full.jpg
    NavScreen-Data Graph-130327-zoomed.jpg


    Right now I'm thinking that these plots are such a mess, that they are mostly just a strong endorsement for using PID to monitor/vary the PWM value to achieve a desired the EncoderCounts/sec. value, rather than trying to set any particular PWM value and praying that that will ever result in any reproducible EncoderCounts/sec. result.

    My initial thought for a next step to implement is to fit a curve through the above data, and use the resulting (PWM,EncoderCounts/sec.) pairs as a starting point upon which to base a PID implementation.

    How does this sound to you?

    =Cliff
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-03-28 - 10:18:27
    I think the main problem I see to your approach is the PWM required to move at any particular speed will vary widely based on the load on the motors. Different surfaces will cause different amounts of resistance to movement. I think forward movement will produce a different load than sideways movement.

    I think you're better off with some sort of proportional feedback loop. I doubt you'll need full PID.

    How many volts where you using with your tests? How long was the sample time when measuring the speed?

    The third graph looks like you were missing encoder pulses. Where you monitoring both encoder lines or did you monitor one pin of the encoders "or"ed together?

    The first two graphs looks like you had a sampling time issue where your sampling time wasn't long enough to come up with a good average.

    I suppose someone well versed in control theory could use your data to partially tune a PID algorithm but the graphs don't give information about change over time. I think you're making this harder than it needs to be. I think a good control algorithm would take care of adjusting the PWM for you. While I think it's interesting to see your PWM vs speed graph I don't think it's needed to come up with a control algorithm.

    Have you figured out a way of monitoring the encoders with your control board? I think I remember you were having trouble with the number of interrupts you were receiving?
  • night_walkernight_walker Posts: 3
    edited 2013-04-09 - 23:41:53
    I am new to mecanum and struggling with the following problem?


    As there is lot of slipping in mecanum wheels due to one point contact how you were getting correct encoder values using internal encoders?

    There will be a lot of error in the encoder values due to slipping.
    Is there any way to reduce this error?

    Currently i am working on a precise path tracing mecanum wheel bot but i am not able to solve the above problem.
    I will appreciate your little help.
  • amano001amano001 Posts: 47
    edited 2013-04-10 - 08:41:40
    I don't think there is an accurate way to measure distance by the encoder values due to slippage. The way we moved around precisely was with ultrasonic sensors using surrounding walls. The meccanum wheels are great for traction but there is always going to be error in the encoder readings due to when the motors are changing directions etc.
  • amano001amano001 Posts: 47
    edited 2013-04-10 - 08:45:35
    Here is what our final robot looked like, Thanks again duane for all your help with the PID. The beagle board XM was used for computer vision, the arduino for serial control of the motors, communication with beagle and other sensors(ultrasonics, IRs, arm Servos) and the propeller for motor control PID.
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-04-10 - 10:07:29
    As there is lot of slipping in mecanum wheels due to one point contact how you were getting correct encoder values using internal encoders?

    There will be a lot of error in the encoder values due to slipping.
    Is there any way to reduce this error?

    I know you're not the first one to worry about this. Post #44 of this thread has a link to an article about using an optical mouse type sensor to compute position. Parallax sells a sensor that should work well in the application.

    I haven't used the encoders for anything other than speed control with this robot so far. I haven't tested how accurate the odometry using the encoders is yet. I'd imagine the odometry would be more accurate when the robot is travelling more like a conventional robot straight forward or straight back. I'd think the sideways motion would produce the most error. Again, these are just guesses since I haven't measured these values myself.
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-04-10 - 10:10:31
    amano001 wrote: »
    Here is what our final robot looked like,

    Very cool robot. Thanks for posting the photo but we really need to see a video of your robot in action, preferably in the competition.
  • amano001amano001 Posts: 47
    edited 2013-04-10 - 10:46:03
    Will be posting a video of it, I will try to find one from the competition. Although the computer vision failed horribly at the competition lol. The lighting was just not on our side.

    Thanks Duane.
  • night_walkernight_walker Posts: 3
    edited 2013-04-12 - 06:50:09
    @amano001 and @duane
    about getting distance using encoders.

    1.What if we use external encoders instead of internal motor encoders? will it help?

    2. @amano001 we made a simple bot with maxons having internal encoders and tried to move it in straight line. But it always use to deviate by some 5-10 cms. we were not particulary concerned with the distance but we wanted it to move in straight line, but we couldn't achieve it perfectly.

    Can slow pwm and large wheel radius help?
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-04-12 - 07:40:39
    What do you mean by "external" encoders? If you mean encoders on the wheels themselves then no, it wouldn't help.

    When you say it would deviate by 5-10 cm, what distance did you travel? What kind of surface? What kind of wheels(Mecanum?, size, material)? What kind of encoders (how many ticks per rev)? What was the surface like? What did you use as a control algorithm?

    I believe in general large thin wheels that don't slip work well for odometry. Slower speeds are also better since you're less likely to have the wheels slip.
  • night_walkernight_walker Posts: 3
    edited 2013-04-12 - 16:13:24
    1. external encoders in the sense encoders on free wheels, not on the powered wheels.
    2.Straight line distance was some 3metres on wooden surface painted with some two layers of paint. we used simple aluminium wheels with grips.(.i am posting the picture)
    20121222_153741.jpg


    3.Our Control algorithm was pid with error based on difference between encoder values.
    1024 x 768 - 91K
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-04-13 - 16:29:49
    I haven't used encoders to measure distance traveled myself. So far I've just used the encoders to monitor motor speed.

    There are lots of threads about using encoders in both the Parallax forums and at LetsMakeRobots.com.
  • Duane DegnDuane Degn Posts: 10,119
    edited 2013-11-15 - 16:08:50
    Well this project thread has kind of gone feral. The stop over in Cuba was a bit distracting but
    I realized the best video of the robot driving under remote control was of the robot with a bug which limited the movements to 45 degree increments.

    Someone over on Let's Make Robots was asking about a Mecanum wheeled robot so I thought I'd update the video.

    Edit: Ugh! I just started watching this. Sorry it's so boring. The robot doesn't start driving until 2:00. I was trying to explain about the technical details. I think I need to try this again with less talking.

    I plan to add a CMUcam4 to this robot (the hardware is installed I still need to incorporate it into the software.

    I've been working on the software on this robot. The current program is a mess. I'm trying to clean it up and I also want to change the control interface to use Nordic nRF24L01+ transceivers instead of the RC system it's currently using. The robot remote I'm working on uses a Nordic device for communication so I'd like to get all my robots able to interface with the remote.

    I've been working on a bunch of stuff lately I just don't have much for to show for it. I sure have a lot of yak hair though.
  • Mark_TMark_T Posts: 1,981
    edited 2013-11-16 - 06:24:35
    Wonder if anyone's thought of an ice-skating robot - those slides are very reminiscent of ice-skating to me!
  • ercoerco Posts: 19,720
    edited 2013-11-16 - 21:06:20
    Sweet video, Pal. Stop apologizing already!
  • whiteoxewhiteoxe Posts: 794
    edited 2014-08-03 - 18:04:05
    I never get tired of watching the vision of this rover. Its just a shame those wheels are not cheap. I purchased a 4ch R/C system for use one day in the future. I would be fun to watch two of these rovers race on a track where the sideways movement was an advantage. And some super fast motors =D
  • Duane DegnDuane Degn Posts: 10,119
    edited 2014-08-03 - 19:55:22
    whiteoxe wrote: »
    Its just a shame those wheels are not cheap.

    I started out with Fingertech Mecanum wheels.

    attachment.php?attachmentid=81068&d=1305066014


    The Fingertech wheels don't come close to working as well as the Vex wheels and the Vex wheels cost less than the Fingertech wheels.

    At $60 (US) the Vex wheels are a great deal. Of course even if they're a great deal, $60 is still a lot to spend on wheels.
    whiteoxe wrote: »
    I would be fun to watch two of these rovers race on a track where the sideways movement was an advantage.

    Racing a Mecanum wheeled robots sounds like it would be fun to watch. The controls (at least on my remote) for the Mecanum wheeled robot are pretty much the same controls used for controlling a quadcopter or a helicopter. The main control difference is the Mecanum wheeled robot doesn't require throttle input. Not needing to keep the Mecanum wheeled robot level is also a big difference. The forward and side motion use the same controls as pitch and roll on a 'copter. Yaw (rotation) is also the same control stick (rudder). It's kind of nice the two types of vehicles use the same controls so my helicopter practice also improve my Mecanum wheeled robot driving skills (and vice versa).

    The Mecanum wheels are really a lot of fun. The robot is always a hit when I bring it out for visitors.

    attachment.php?attachmentid=110076&d=1407120835
    whiteoxe wrote: »
    And some super fast motors =D

    The Rover 5 motors work fine with the Mecanum wheels but I hope to build an upgraded version using some motors like these. I have a set of four similar motors from Pololu, I may use with the Mecanum wheels.

    Whichever motors are used used with the Mecanum wheels, it's a very good idea to have encoders on the motors. There was a huge improvement in performance when I added encoder feedback to my control algorithm. IMO, just about every ground robot should have encoders but they're even more important than usual when using Mecanum wheels.

    One of my future plans is to add a gyro/accelerometer combo to aid the Mecanum wheeled robot with autonomous navigation. I still haven't done much to make this robot drive autonomously other than some experiments with a digital compass. IMO, if a robot is only remote controlled then it's not really a robot. It's just a RC toy. I still have some work to do to change this toy into a real robot.
    540 x 376 - 456K
  • W9GFOW9GFO Posts: 3,953
    edited 2014-08-03 - 19:59:25
    whiteoxe wrote: »
    I never get tired of watching the vision of this rover.

    Here's a video you can tire of watching, it's the only video I have of my Mecanum robot;
  • Duane DegnDuane Degn Posts: 10,119
    edited 2014-08-03 - 20:12:11
    W9GFO wrote: »
    it's the only video I have of my Mecanum robot;

    I know I've seen another video of your robot. I think it was made during a Propeller Expo.

    Your robot is one of the reasons I want to upgrade the motors on mine. Your robot definitely had much more power than mine.

    I often think of what your robot's name (Kepler) implies. I keep hoping to get a pair of omni directional robots to kind of dance around each other.

    I got my omni wheeled robot robot to "spin straight".

    But I'd really like to get the robots to be able to do more complex motions preferably as they move around one another.

    I found the other Kepler video.

    It was on erco's YouTube channel.
  • W9GFOW9GFO Posts: 3,953
    edited 2014-08-03 - 20:41:16
    Thanks Duane, forgot about that one. Yes, the intent of Kepler was to have it be able to "orbit" an arbitrary point whilst changing it's own orientation. I'll probably need a couple more years before that gets done.
  • whiteoxewhiteoxe Posts: 794
    edited 2014-08-03 - 21:40:38
    W9GFO wrote: »
    Here's a video you can tire of watching, it's the only video I have of my Mecanum robot;
    That was hilarious... the little robot was going to hide under those drawers no matter what :confused:
  • whiteoxewhiteoxe Posts: 794
    edited 2014-08-03 - 22:00:03
    I got my omni wheeled robot to "spin straight".
    I have to wonder at some vehicle designs ?.... the one good thing about this 3 wheeled transporter is it would probably be great for those that can't manage a normal reverse park, we all know someone like that .... but the difficulty of going from A to B over more than a few yards just wouldn't be worth the tradeoff :swear:
  • davidgitzdavidgitz Posts: 7
    edited 2014-08-13 - 19:52:05
    Looks like a great robot! At FAST Robotics we are offering a nice solution for using your Quickstart on a Robotics project, the Robot Shield.
    810001A_Robot Shield ISO.jpg

    Some basic info:
    -4 Servo Outputs externally powered
    -9 GPIO Pins
    -8 Analog Inputs
    -SD Card
    -Serial Port

    We are currently working on the new version of this board to make minor improvements and move the headers to the exterior of the board for connecting shields together. Here is our github page for the Robot Shield https://github.com/fastrobotics/810001_robot-shield
    and a link to a demo video on a robot: https://www.youtube.com/watch?v=DXkjqCKs9c8
    We have a lot of other things we're working on too. Check out our facebook for more info: https://www.facebook.com/fastrobotics
    1024 x 683 - 72K
Sign In or Register to comment.