Asked

Some More Encoder

DJ hi,  I am getting some weird map results in Better Navigator using the encoder counter skill. Using a Roomba via PC COM port and for Level #3 Group #2, I taped into Roomba encoders that go to an Arduino with Wheel Encoder UNO firmware. For Level #3 Group #1, I use a RPLidar. In the config of the Wheel Encoder Counter skill, I enable the push to NMS checkbox and leave all other settings default as they exactly match the Roomba. In The Better Navigator, I use External as pose hint source. What I am experiencing is that when I move forward or backward, the map creation seems ok, but as soon as I turn left or right, the map gets all messed up. The counts from the encoders are surprisingly good. My guess is that the BN is not processing encoder counts correctly with the left and right commands?


Related Hardware Roomba
Related Control The Better Navigator

ARC Pro

Upgrade to ARC Pro

ARC Pro will give you immediate updates and new features needed to unleash your robot's potential!

PRO
Canada
#1  

It sounds like you're experiencing issues with the mapping accuracy when using The Better Navigator with your Roomba and encoder setup. Let's go through some steps to troubleshoot and potentially resolve the issue:

  1. Verify Encoder Configuration:

    • Ensure that the encoder counts are correctly configured in the Wheel Encoder Counter skill. Double-check the wheel diameter and counts per revolution settings to match your Roomba's specifications.
  2. Check Encoder Wiring:

    • Verify that the wiring from the Roomba encoders to the Arduino is secure and correct. Any loose connections can lead to inaccurate readings.
  3. Review Wheel Encoder Counter Settings:

    • Make sure the "Push to NMS" option is enabled, as you mentioned. This ensures that the encoder data is sent to the Navigation Messaging System (NMS).
    • Confirm that the encoder counts are being updated correctly in real-time. You can use the Variable Watcher skill to monitor the encoder values.
  4. Pose Hint Source:

    • Since you're using "External" as the pose hint source, ensure that the encoder data is reliable. If the encoder data is not accurate, it can lead to incorrect pose estimation.
    • Consider testing with "Differential" as the pose hint source to see if it improves the mapping accuracy. This option uses both the external sensor and the internal Hector SLAM calculation.
  5. Lidar Configuration:

    • Ensure that the RPLidar is correctly configured and providing accurate distance data. The lidar data is crucial for mapping and obstacle detection.
  6. Test with Different Movement Speeds:

    • Try reducing the movement speed of the Roomba when turning. High speeds can lead to inaccuracies in encoder readings and mapping.
  7. Check for Software Updates:

    • Ensure that you are using the latest version of ARC and all robot skills. Updates may include bug fixes and improvements.
  8. Debugging:

    • Enable the "Navigation debugging" option in The Better Navigator's configuration to get more detailed logs about the navigation process. This can help identify where the issue might be occurring.
  9. Consult the Manuals:

    • Review the manuals for The Better Navigator and the Wheel Encoder Counter skill to ensure all settings are correctly configured.

If you've gone through these steps and the issue persists, consider reaching out to Synthiam support for further assistance. They may be able to provide more specific guidance based on your setup. Additionally, you can explore the possibility of using a different pose hint source or adjusting the configuration settings to better suit your environment and hardware.


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Portugal
#2  

Thank You, @Athena, Tried all Pose Hint Sources but the result seems to be the same. In the first screen capture, I just go forward. In the second, I turn left, and the map goes berserk.

User-inserted image

User-inserted image

PRO
Canada
#3  

It seems like the issue might be related to how the encoder data is being interpreted during turns. Here are a few additional steps you can take to troubleshoot and potentially resolve the issue:

  1. Calibration of Encoders:

    • Double-check the calibration of your encoders. Ensure that the counts per revolution and wheel diameter are accurately set. Any discrepancies here can lead to incorrect distance and turn calculations.
  2. Encoder Data Validation:

    • Use the Variable Watcher skill to monitor the encoder values in real-time. Check if the values make sense when you perform forward and turning movements. Look for any sudden spikes or drops in the encoder counts.
  3. Review Arduino Firmware:

    • Ensure that the Arduino firmware for the Wheel Encoder UNO is correctly processing and sending the encoder data. Verify that the data being sent to ARC is accurate and consistent.
  4. Check for Slippage:

    • Ensure that the Roomba's wheels are not slipping during turns. Slippage can cause the encoders to report incorrect values, leading to mapping errors.
  5. Adjust Turning Speed:

    • Try reducing the turning speed of the Roomba. High speeds during turns can lead to inaccuracies in encoder readings and mapping.
  6. Lidar Data Correlation:

    • Ensure that the RPLidar data is correctly aligned with the encoder data. The lidar should provide consistent obstacle detection and mapping data.
  7. Debugging Logs:

    • Enable detailed debugging logs in The Better Navigator to see if there are any errors or warnings during the mapping process. This can provide insights into what might be going wrong.
  8. Cross-Check with Other Skills:

    • If possible, test the encoder data with other skills or scripts to see if the issue is isolated to The Better Navigator or if it's a broader problem with the encoder data.
  9. Consult Synthiam Support:

    • If the issue persists, consider reaching out to Synthiam support with detailed logs and descriptions of the problem. They may have additional insights or solutions based on your specific setup.
  10. Alternative Mapping Skills:

    • As a last resort, you might want to try using a different mapping or navigation skill to see if it handles the encoder data differently.

By following these steps, you should be able to narrow down the cause of the issue and find a solution. If you have any more questions or need further assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Portugal
#4  

@Athena,

One thing I noticed is that no matter if I move forward or backward the encoder counter skill counts always up to positive numbers. Shouldnt it be subtracting counts when moving backward?

PRO
Canada
#5  

Yes, you are correct. When moving backward, the encoder counts should typically decrease, resulting in negative values. If the encoder counter skill is only counting up, regardless of the direction, it could indicate a configuration issue. Here are some steps to address this:

  1. Check Encoder Wiring:

    • Ensure that the wiring from the Roomba encoders to the Arduino is correct. If the wiring is reversed, it might cause the encoder to count in the same direction for both forward and backward movements.
  2. Review Arduino Firmware:

    • Verify that the Arduino firmware is correctly interpreting the encoder signals. The firmware should differentiate between forward and backward movements and adjust the counts accordingly.
  3. Encoder Counter Skill Configuration:

    • Double-check the settings in the Wheel Encoder Counter skill. Ensure that the configuration matches the expected behavior of your encoders.
    • Look for any options related to direction or inversion that might need adjustment.
  4. Test with Simple Movements:

    • Perform simple forward and backward movements while monitoring the encoder values. This can help you identify if the issue is consistent or intermittent.
  5. Debugging:

    • Use the Variable Watcher skill to monitor the encoder values in real-time. This can help you see how the values change with different movements.
  6. Consult the Encoder Manual:

    • If available, refer to the manual or documentation for your specific encoders. There might be specific instructions or settings related to direction handling.
  7. Firmware Update:

    • Ensure that the Arduino firmware is up-to-date. There might be updates or patches that address this issue.
  8. Contact Support:

    • If the issue persists, consider reaching out to Synthiam support or the community for further assistance. They might have encountered similar issues and can provide additional guidance.

By addressing these points, you should be able to resolve the issue with the encoder counts not reflecting the correct direction. If you have any more questions or need further assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Portugal
#6   — Edited

@Athena, Please take a look at the code from DJ's UNO Firmware with Wheel Encoder Counter; it only counts up. How would you proceed to modify the code to take into account all 4 movement directions?

#include 
#include "SendOnlySoftwareSerial.h"

// The first digital port that is usable on this controller
#define _PortStart 4

// The last digital port on this controller that is usable
#define _PortCnt 14

// The number of analog ports
#define _AnalogPorts 6

// The firmware version that is reported to ARC to notify of capabilities
#define _FIRMWARE_ID 0x0000000B

// The communication baud rate
#define _BAUD_RATE 57600

// The primary communication interface between ARC and this controller
#define COMMUNICATION_PORT Serial

// The amount of RX buffer on the communication interface for EZ-Builder
#define _BUFFER_SIZE 1024

// --------------------------------------------------------------------------

byte         _INPUT_BUFFER[_BUFFER_SIZE];
unsigned int _WRITE_POSITION = 0;
unsigned int _READ_POSITION = 0;
unsigned int _WheelLeftCnt = 0;
unsigned int _WheelRightCnt = 0;

int _BAUD_RATES [] = {
  4800,
  9600,
  19200,
  38400,
  57600,
  115200,
  115200
};

Servo Servos[_PortCnt];

#define CmdOurCustomCmds      0
#define CmdReleaseAllServos   1
#define CmdGetUniqueID        2
#define CmdEZBv3              3
#define CmdEZBv4              4
#define CmdSoundBeep          5
#define CmdEZServo            6
#define CmdI2CWrite           10
#define CmdI2CRead            11
#define CmdBootLoader         14
#define CmdSetPWMSpeed        15
#define CmdSetServoSpeed      39
#define CmdPing               0x55
#define CmdSetDigitalPortOn   100
#define CmdSetDigitalPortOff  124
#define CmdGetDigitalPort     148
#define CmdSetServoPosition   172
#define CmdGetADCValue        196
#define CmdSendSerial         204
#define CmdHC_SR04            228
#define CmdGetFirwareID       253
#define CmdSoundStreamCmd     254

// CmdEZBv4 Commands
// ----------------------------------------------------------------------------------
#define CmdV4SetLipoBatteryProtectionState 0
#define CmdV4SetBatteryMonitorVoltage      1
#define CmdV4GetBatteryVoltage             2
#define CmdV4GetCPUTemp                    3

#define CmdV4UARTExpansion0Init            5
#define CmdV4UARTExpansion0Write           6
#define CmdV4UARTExpansion0AvailableBytes  7
#define CmdV4UARTExpansion0Read            8

#define CmdV4UARTExpansion1Init            9
#define CmdV4UARTExpansion1Write           10
#define CmdV4UARTExpansion1AvailableBytes  11
#define CmdV4UARTExpansion1Read            12

#define CmdV4UARTExpansion2Init            13
#define CmdV4UARTExpansion2Write           14
#define CmdV4UARTExpansion2AvailableBytes  15
#define CmdV4UARTExpansion2Read            16

#define CmdV4I2CClockSpeed                 17
#define CmdV4UARTClockSpeed                18
#define CmdV4ResetToDefaults               19

// CmdSoundStreamCmd Commands
// ----------------------------------------------------------------------------------
#define CmdSoundInitStop 0
#define CmdSoundLoad     1
#define CmdSoundPlay     2

bool IsAvail() {

  return _WRITE_POSITION != _READ_POSITION || COMMUNICATION_PORT.available();
}

byte ReadByte() {

  while (_WRITE_POSITION == _READ_POSITION && COMMUNICATION_PORT.available() == 0);

  while (COMMUNICATION_PORT.available()) {

    _WRITE_POSITION++;

    _INPUT_BUFFER[_WRITE_POSITION % _BUFFER_SIZE] = COMMUNICATION_PORT.read();
  }

  _READ_POSITION++;

  return _INPUT_BUFFER[_READ_POSITION % _BUFFER_SIZE];
}

void setup() {

  COMMUNICATION_PORT.begin(_BAUD_RATE);

  // Left Wheel
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), countLeft, CHANGE);

  // Right Wheel
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(3), countRight, CHANGE);
}

void countLeft()  {

  _WheelLeftCnt++;
}

void countRight() {

  _WheelRightCnt++;
}

void loop() {

  doEZProtocol();
}

void Write32(long val) {

  COMMUNICATION_PORT.write((byte)(val & 0xff));
  COMMUNICATION_PORT.write((byte)((val >> 8) & 0xff));
  COMMUNICATION_PORT.write((byte)((val >> 16) & 0xff));
  COMMUNICATION_PORT.write((byte)((val >> 24) & 0xff));
}

void Write16(int val) {

  COMMUNICATION_PORT.write((byte)(val & 0xff));
  COMMUNICATION_PORT.write((byte)((val >> 8) & 0xff));
}

#define UNKNOWN_PIN 0xFF

uint8_t getPinMode(uint8_t pin) {

  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);

  // I don't see an option for mega to return this, but whatever...
  if (NOT_A_PIN == port)
    return UNKNOWN_PIN;

  // Is there a bit we can check?
  if (0 == bit)
    return UNKNOWN_PIN;

  // Is there only a single bit set?
  if (bit & bit - 1)
    return UNKNOWN_PIN;

  volatile uint8_t *reg, *out;
  reg = portModeRegister(port);
  out = portOutputRegister(port);

  if (*reg & bit)
    return OUTPUT;
  else if (*out & bit)
    return INPUT_PULLUP;
  else
    return INPUT;
}

void doEZProtocol() {

  if (IsAvail()) {

    byte cmd = ReadByte();

    if (cmd == CmdPing) {

      // return as a "Capability Controller"
      COMMUNICATION_PORT.write(222);
    } else if (cmd == CmdGetFirwareID) {

      Write32(_FIRMWARE_ID);
    } else if (cmd == CmdReleaseAllServos) {

      for (int port = _PortStart; port < _PortCnt; port++)
        if (Servos[port].attached())
          Servos[port].detach();
    } else if (cmd >= CmdSetServoPosition && cmd <= CmdSetServoPosition + 23) {

      byte port = cmd - CmdSetServoPosition;
      byte pos = ReadByte();

      if (port >= _PortStart && port <= _PortCnt) {

        if (pos == 0 && Servos[port].attached()) {

          Servos[port].detach();
        } else {

          if (!Servos[port].attached())
            Servos[port].attach(port);

          Servos[port].write(pos);
        }
      }
    } else if (cmd >= CmdSetPWMSpeed && cmd <= CmdSetPWMSpeed + 23) {

      byte port = cmd - CmdSetPWMSpeed;
      byte pos = ReadByte();

      if (port >= _PortStart && port <= _PortCnt) {

        if (Servos[port].attached())
          Servos[port].detach();

        if (getPinMode(port) != OUTPUT)
          pinMode(port, OUTPUT);

        analogWrite(port, map(pos, 0, 100, 0, 255));
      }
    } else if (cmd >= CmdSetDigitalPortOn && cmd <= CmdSetDigitalPortOn + 23) {

      byte port = cmd - CmdSetDigitalPortOn;

      if (port >= _PortStart && port <= _PortCnt) {

        if (Servos[port].attached())
          Servos[port].detach();

        if (getPinMode(port) != OUTPUT)
          pinMode(port, OUTPUT);

        digitalWrite(port, HIGH);
      }
    } else if (cmd >= CmdSetDigitalPortOff && cmd <= CmdSetDigitalPortOff + 23) {

      byte port = cmd - CmdSetDigitalPortOff;

      if (port >= _PortStart && port <= _PortCnt) {

        if (Servos[port].attached())
          Servos[port].detach();

        if (getPinMode(port) != OUTPUT)
          pinMode(port, OUTPUT);

        digitalWrite(port, LOW);
      }
    } else if (cmd >= CmdGetDigitalPort && cmd <= CmdGetDigitalPort + 23) {

      byte port = cmd - CmdGetDigitalPort;

      if (port >= _PortStart && port <= _PortCnt) {

        if (Servos[port].attached())
          Servos[port].detach();

        if (getPinMode(port) != INPUT)
          pinMode(port, INPUT);

        COMMUNICATION_PORT.write(digitalRead(port));
      } else {

        COMMUNICATION_PORT.write(0);
      }
    } else if (cmd >= CmdGetADCValue && cmd <= CmdGetADCValue + 7) {

      byte port = cmd - CmdGetADCValue;

      if (port >= 0 && port <= _AnalogPorts)
        Write16(analogRead(port));
      else
        Write16(0);
    } else if (cmd >= CmdSendSerial && cmd <= CmdSendSerial + 23) {

      // Send Serial
      uint8_t port = cmd - CmdSendSerial;
      uint8_t baud = ReadByte(); // Baud rate
      uint8_t size = ReadByte(); // Size

      if (port >= _PortStart && port <= _PortCnt) {

        if (Servos[port].attached())
          Servos[port].detach();

        SendOnlySoftwareSerial tmpSerial(port);

        tmpSerial.begin(_BAUD_RATES[baud]);

        for (int x = 0; x < size; x++)
          tmpSerial.write(ReadByte());

        tmpSerial.end();
      }
    } else if (cmd == CmdOurCustomCmds) {

      byte cmd2 = ReadByte();

      if (cmd2 == 0x00) {

        // Get Both Wheel Counts
        Write16(_WheelLeftCnt);
        Write16(_WheelRightCnt);
      } else if (cmd2 == 0x01) {

        // Get Both Wheel Counts & Reset
        Write16(_WheelLeftCnt);
        Write16(_WheelRightCnt);

        _WheelLeftCnt = 0;
        _WheelRightCnt = 0;
      } else if (cmd2 == 0x02) {
      
        // Reset Wheel Counts
        _WheelLeftCnt = 0;
        _WheelRightCnt = 0;
      }
    }
  }
}

PRO
Synthiam
#7   — Edited

Quote:

Using a Roomba via PC COM port and for Level #3 Group #2, I taped into Roomba encoders that go to an Arduino with Wheel Encoder UNO firmware.
You connected the arduino gpio to the wires of the encoders in the roomba? I have no idea how that would work because i don't know how the encoders work. Also, how would the roomba's existing signal interfere with the arduino. Also, you'd need to know if you're subtracting or adding to the value based on the direction of movement in ARC. So perhaps you have the gpio wires reversed? Or missing a common ground, or something that is messing it up. Because there's no way for the arduino code to know what way the wheel is turning. The encoder only tells you counts, not a direction.

Quote:

For Level #3 Group #1, I use a RPLidar. In the config of the Wheel Encoder Counter skill, I enable the push to NMS checkbox and leave all other settings default as they exactly match the Roomba.
If you're using an external pose value (the encoder), make sure the "Fake NMS Pose Hint" is UNCHECKED in the RPLIdar settings,.

PRO
Canada
#8  

To modify the code to account for all four movement directions, you'll need to implement a way to determine the direction of movement. Since the encoder only provides counts and not direction, you can use additional logic to infer direction based on the commands sent to the robot. Here's a general approach to modify the code:

  1. Track Movement Direction:

    • You need to track the current movement direction (forward, backward, left, right) in your code. This can be done by setting a variable whenever a movement command is issued.
  2. Adjust Encoder Counts Based on Direction:

    • Modify the countLeft() and countRight() functions to adjust the counts based on the current direction. For example, if the robot is moving backward, decrement the count instead of incrementing it.

Here's a modified version of the code with these changes:

#include <Servo.h>
#include <SendOnlySoftwareSerial.h>

// The first digital port that is usable on this controller
#define _PortStart 4
// The last digital port on this controller that is usable
#define _PortCnt 14
// The number of analog ports
#define _AnalogPorts 6
// The firmware version that is reported to ARC to notify of capabilities
#define _FIRMWARE_ID 0x0000000B
// The communication baud rate
#define _BAUD_RATE 57600
// The primary communication interface between ARC and this controller
#define COMMUNICATION_PORT Serial
// The amount of RX buffer on the communication interface for EZ-Builder
#define _BUFFER_SIZE 1024

// Movement directions
enum Direction { FORWARD, BACKWARD, LEFT, RIGHT, STOP };
Direction currentDirection = STOP;

byte _INPUT_BUFFER[_BUFFER_SIZE];
unsigned int _WRITE_POSITION = 0;
unsigned int _READ_POSITION = 0;
int _WheelLeftCnt = 0;
int _WheelRightCnt = 0;

void setup() {
    COMMUNICATION_PORT.begin(_BAUD_RATE);

    // Left Wheel
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(2), countLeft, CHANGE);

    // Right Wheel
    pinMode(3, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(3), countRight, CHANGE);
}

void countLeft() {
    if (currentDirection == FORWARD || currentDirection == RIGHT) {
        _WheelLeftCnt++;
    } else if (currentDirection == BACKWARD || currentDirection == LEFT) {
        _WheelLeftCnt--;
    }
}

void countRight() {
    if (currentDirection == FORWARD || currentDirection == LEFT) {
        _WheelRightCnt++;
    } else if (currentDirection == BACKWARD || currentDirection == RIGHT) {
        _WheelRightCnt--;
    }
}

void loop() {
    doEZProtocol();
}

void doEZProtocol() {
    if (IsAvail()) {
        byte cmd = ReadByte();
        if (cmd == CmdPing) {
            COMMUNICATION_PORT.write(222);
        } else if (cmd == CmdGetFirwareID) {
            Write32(_FIRMWARE_ID);
        } else if (cmd == CmdOurCustomCmds) {
            byte cmd2 = ReadByte();
            if (cmd2 == 0x00) {
                Write16(_WheelLeftCnt);
                Write16(_WheelRightCnt);
            } else if (cmd2 == 0x01) {
                Write16(_WheelLeftCnt);
                Write16(_WheelRightCnt);
                _WheelLeftCnt = 0;
                _WheelRightCnt = 0;
            } else if (cmd2 == 0x02) {
                _WheelLeftCnt = 0;
                _WheelRightCnt = 0;
            }
        }
    }
}

bool IsAvail() {
    return _WRITE_POSITION != _READ_POSITION || COMMUNICATION_PORT.available();
}

byte ReadByte() {
    while (_WRITE_POSITION == _READ_POSITION && COMMUNICATION_PORT.available() == 0);
    while (COMMUNICATION_PORT.available()) {
        _WRITE_POSITION++;
        _INPUT_BUFFER[_WRITE_POSITION % _BUFFER_SIZE] = COMMUNICATION_PORT.read();
    }
    _READ_POSITION++;
    return _INPUT_BUFFER[_READ_POSITION % _BUFFER_SIZE];
}

void Write32(long val) {
    COMMUNICATION_PORT.write((byte)(val & 0xff));
    COMMUNICATION_PORT.write((byte)((val >> 8) & 0xff));
    COMMUNICATION_PORT.write((byte)((val >> 16) & 0xff));
    COMMUNICATION_PORT.write((byte)((val >> 24) & 0xff));
}

void Write16(int val) {
    COMMUNICATION_PORT.write((byte)(val & 0xff));
    COMMUNICATION_PORT.write((byte)((val >> 8) & 0xff));
}

Additional Steps:

  • Direction Tracking: You need to implement a way to update the currentDirection variable based on the movement commands sent to the robot. This might involve modifying the communication protocol to include direction information.
  • Testing: After implementing these changes, test the robot's movement and encoder counts to ensure they reflect the correct direction.

If you have any more questions or need further assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Synthiam
#9  

The firmware wont' know the wheel direction - so that's gonna be a challenge if you're trying to do it in the EZB firmware. The robot skill is where it needs to be. Either that - or the robot skill can send a command to the firmware that explains the current direction. Actually, i like that.

I think the robot skill and firmware should be modified to accept a command that defines the wheel directions. That way, the firmware knows to add or subtract the encoder value. Everytime the Movement Panel direction changes, it sends an update to the firmware. The firmware will then use that value to determine how to alter the encoder count.

What do you think?

Btw the wheel encoder robot skill firmware is here if you wanna see how it's working: https://github.com/synthiam/Robot-Skill-Wheel_Encoder_Counter

PRO
Portugal
#10   — Edited

Thank you @Athena and DJ,

The count pulses from the roomba encoder are suprisingly acurate. Just forget that the encoder is from the roomba and assume its a regular pulse count encoder. Would the Movement Panel from roomba send the direction to NMS or The Better Navigator?

I also think its a good idea to send direction to the arduino.

PRO
Canada
#11  

It's great to hear that the encoder pulses are accurate! Given that, let's focus on how to integrate the direction information effectively.

Movement Panel and Direction Communication

  1. Movement Panel to NMS/Better Navigator:

    • The Movement Panel in ARC is responsible for controlling the robot's movement. It can send direction commands to the Navigation Messaging System (NMS) or the Better Navigator. This ensures that the navigation system is aware of the robot's intended movement direction.
  2. Sending Direction to Arduino:

    • As DJ suggested, modifying the robot skill to send direction commands to the Arduino is a practical approach. This way, the Arduino can adjust the encoder counts based on the current movement direction.

Implementation Steps

  1. Modify the Robot Skill:

    • Update the robot skill to send direction commands to the Arduino whenever the movement direction changes. This can be done using a custom command that the Arduino firmware will recognize.
  2. Update Arduino Firmware:

    • Modify the Arduino firmware to accept direction commands. Use these commands to determine whether to increment or decrement the encoder counts.
  3. Direction Command Protocol:

    • Define a simple protocol for direction commands. For example, you could use specific byte values to represent each direction (e.g., 0x01 for forward, 0x02 for backward, etc.).
  4. Testing:

    • Test the system to ensure that the encoder counts are adjusted correctly based on the movement direction. Verify that the navigation system receives accurate pose information.

Example Code Snippet

Here's a basic example of how you might implement the direction command handling in the Arduino firmware:

enum Direction { FORWARD, BACKWARD, LEFT, RIGHT, STOP };
Direction currentDirection = STOP;

void handleDirectionCommand(byte directionCmd) {
    switch (directionCmd) {
        case 0x01:
            currentDirection = FORWARD;
            break;
        case 0x02:
            currentDirection = BACKWARD;
            break;
        case 0x03:
            currentDirection = LEFT;
            break;
        case 0x04:
            currentDirection = RIGHT;
            break;
        default:
            currentDirection = STOP;
            break;
    }
}

void countLeft() {
    if (currentDirection == FORWARD || currentDirection == RIGHT) {
        _WheelLeftCnt++;
    } else if (currentDirection == BACKWARD || currentDirection == LEFT) {
        _WheelLeftCnt--;
    }
}

void countRight() {
    if (currentDirection == FORWARD || currentDirection == LEFT) {
        _WheelRightCnt++;
    } else if (currentDirection == BACKWARD || currentDirection == RIGHT) {
        _WheelRightCnt--;
    }
}

Conclusion

By implementing these changes, you can ensure that the encoder counts accurately reflect the robot's movement direction, improving the navigation system's performance. If you have any further questions or need additional assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Synthiam
#12  

Okay i modified the firmware and robot skill of the Wheel Encoder to add or subtract the values based on the Movement Panel direction. Check the updated v10 wheel encoder robot skill and the new firmware for it.

Quote:

The count pulses from the roomba encoder are suprisingly acurate. Just forget that the encoder is from the roomba and assume its a regular pulse count encoder. Would the Movement Panel from roomba send the direction to NMS or The Better Navigator?

I was under the impression, based on your previous message, that you are using the roomba to send it's pose data to the NMS from an Arduino UNO with the wheel encoders. Based on this question, I'm not sure I fully understand now what you're doing now:D.

  1. The roomba has built-in encoders and the roomba Movement Panel can send it's pose data to the NMS without you needing an arduino or anything else. It does it on its own

  2. If you're not using the roomba's built-in encoder value counter and using an arduino wheel encoder, then you'd have to continue on with what i posted above.

I would use #1 because it doesn't require any additional hardware. The Roomba Movement Panel (https://synthiam.com/Support/Skills/Movement-Panels/iRobot-Roomba-Movement-Panel?id=19164) manual explains more.

PRO
Portugal
#13  

LOL DJ, what a mess. I apologise for my poor fraise construction as it is not my native language. I am indeed using the Roombas encoders hoked up to an Arduino. I read in some posts that the data coming from the Roomba directly would go back to "0" when reaching 65565 or so. Will test the new firm and skill. Thank you.

PRO
Synthiam
#14  

Haha okay - no prob. We're progressing:)

I don't recall about the roomba robot skill going back to 0 but that could be the case. I'm sure it's something that can be fixed. Have you experienced issues by trying it? My first recommendation would be not use the roomba robot skill and see if you like that.

However, if you want to test out the new code i created - let me know. It "should" work based on my conceptual plan but it isn't tested. I'm just sitting watching the waves roll in while it rains outside. So i figured i should write some code and get you rock'n.:)

PRO
Portugal
#15  

Bad news DJ, now as soon as I go forward both encoder counts jump from 0 to 6547.

User-inserted image

Ah and here is the thred I was talking about the roomba encoders.

User-inserted image

PRO
Synthiam
#16  

Ah okay - sounds like my logic is reversed in the firmware. You can edit and swap the ++ and for the encoder count increments to try it.

im not at home anymore so I can’t make the changes rn

PRO
Portugal
#18   — Edited

The good news, it didnt blow up my Arduino or my house.xD The bad news, it counts always positive. It loock like the variable "_WheelDirections" is not updated. If I can help in debuging and testing let me know DJ.

PRO
Synthiam
#20  

What’s the verdict? Did that new skill and firmware fix it

PRO
Portugal
#21   — Edited

Well here is how it tested out:

1- The counting issue is fixed. When turning left: left wheel counts down and right counts up. When turning right: right wheel counts down and left wheel counts up.

2- Moving the robot forward seems ok, the map gets updated.

3- Moving the robot left or right screews it all up. The values from the encoder are acurate so I imagine it has something to do with how those values are processed in BN?

Tell me how I can help DJ. Thanks

PRO
Portugal
#22   — Edited

Just tested the "send position to nms" from the roomba Movement Panel and it works but not very acurate. The map doesent get messed up.

PRO
Synthiam
#23  

I’m guessing it gets messed up because the dimensions are not entered correctly. The math to convert wheel ticks to pose is very advanced and requires incredible precision of the dimensions.

try with the dimensions added because that’s important.

PRO
Portugal
#24   — Edited

Thank you DJ, the dimensions are correct. I dont want to steal any more of your time with this, so I will use the fake NMS pose hint for now. It is difficult for someone to debug something without having the setup to test it.

PRO
Synthiam
#25  

I can’t have a non-working product:) so I’ll have to figure it out.

PRO
Portugal
#26  

@Athena,

In the script editor with Better Navigator we can use "controlCommand("The Better Navigator", "StopNavigating");". Is there a "PauseNavigating" variable instead of Stop?

PRO
Canada
#27  

Yes, you can use the ControlCommand() function to pause navigation in The Better Navigator. The command you're looking for is PauseNavigating. Here's how you can use it in your script:

ControlCommand("The Better Navigator", "PauseNavigating");

This command will pause the navigation process, allowing you to resume it later if needed. If you have any more questions or need further assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Synthiam
#28   — Edited

By viewing the available control commands in ARC for the Better Navigator robot skill, Athena hallucinated that answer: You can see the available control commands for a robot skill by right-clicking in the editor or looking at the cheat sheet. The manual for the Better Navigator also has a section at the bottom that includes control commands. There is no Pause; there is only STOP. According to the manual, STOP will stop the navigation that is currently in progress.

You can instruct the NMS to pause: https://synthiam.com/Support/javascript-api/Navigation/SetNavigationStatusToPause (also see other NMS commands in the scripting manual)

If you provide more details of what you're attempting to do, that will be helpful to @Athena and myself

PRO
Portugal
#29  

Hahaha, Athena hallucinating. Thats funny. I am just playing around with some ultrasinic sensors. I have 3 in the front or the roomba and using the ultrasonic collision script skill. I want to detect obstacles and pause navigation and find a clear path and then resume to the waypoint.

PRO
Synthiam
#30  

You can have the  ultrasonic sensor push it's data to the NMS. All you need to do is specify the heading the sensor is pointing relative to the front of the robot and the offset. There's filters for highest and lowest to remove false positives. Once the checkbox is checked, the sensor data will be merged with the lidar data.

User-inserted image

But, if you want to script the "stop" yourself, I think that's what the NMS scripting commands are for.

PRO
Canada
#31  

To achieve obstacle detection and pause navigation using ultrasonic sensors, you can utilize the Navigation Messaging System (NMS) scripting commands. Here's a step-by-step guide on how to set this up:

  1. Configure Ultrasonic Sensors:

    • Ensure your ultrasonic sensors are correctly configured and positioned on the Roomba.
    • Use the Ultrasonic Collision script skill to detect obstacles.
  2. Push Data to NMS:

    • In the Ultrasonic Collision script skill, enable the option to push data to the NMS. This will allow the sensor data to be merged with the lidar data.
  3. Script to Pause Navigation:

    • Use the SetNavigationStatusToPause() command to pause navigation when an obstacle is detected. Here's an example script:
    // Check for obstacle
    if (obstacleDetected) {
        // Pause navigation
        SetNavigationStatusToPause();
        print("Navigation paused due to obstacle.");
    }
    
  4. Find a Clear Path:

    • Implement logic to find a clear path. This could involve rotating the Roomba slightly to check for a clear path using the ultrasonic sensors.
  5. Resume Navigation:

    • Once a clear path is found, use the SetNavigationStatusToNavigating() command to resume navigation:
    // Check if path is clear
    if (pathIsClear) {
        // Resume navigation
        SetNavigationStatusToNavigating();
        print("Resuming navigation.");
    }
    
  6. Testing:

    • Test the setup to ensure the Roomba pauses when an obstacle is detected and resumes navigation once a clear path is found.

By using the NMS scripting commands, you can effectively manage navigation pauses and resumes based on sensor input. If you have any more questions or need further assistance, feel free to ask!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Portugal
#32  

That is so cool, didnt know that. I jumped right to the ultra sonic collision script skill. Thank you @Athena and DJ.

PRO
Canada
#33  

You're welcome! I'm glad you found the information helpful. The Ultrasonic Collision script skill, combined with the Navigation Messaging System, can be a powerful way to enhance your robot's navigation capabilities. If you have any more questions or need further assistance as you continue to work on your project, feel free to reach out. Happy robot building!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.