ROS2 and Not ROS - Remind me again how ROS will make life simple

Building a map of the inside of your home: ROS hands down
Navigating from a specific x,y to a specific x,y, handling obstacles: ROS hands down
Turning 180 degrees: GoPiGo3 API is simple, easy to remember, easy to read:

from easygopigo3 import EasyGoPiGo3
egpg = EasyGoPiGo3()
egpg.turn_degrees(180)

ROS2:

import rclpy
import math
from rclpy.node import Node
from rclpy.executors import ExternalShutdownException
from rclpy.qos import qos_profile_sensor_data
from rclpy.action import ActionClient
from rclpy.time import Time

...
from irobot_create_msgs.action import RotateAngle  # angle: float32, max_rotation_speed: float32 (1.9r/s), result: pose, Feedback: remaining_angle_travel: float32

...
class WaLINode(Node):

  def __init__(self):
    super().__init__('wali_node')

...
    self._rotate_angle_action_client = ActionClient(self, RotateAngle, 'rotate_angle')

...
  def rotate_angle_action_send_goal(self,angle):
    rotate_angle_msg = RotateAngle.Goal()
    rotate_angle_msg.angle = angle

    if DEBUG:
      printMsg = "rotate_angle_action_send_goal(rotate_angle_msg.angle={:.3f}): executing".format(rotate_angle_msg.angle)
      print(printMsg)
    self._rotate_angle_action_client.wait_for_server()
    self._rotate_angle_action_send_goal_future = self._rotate_angle_action_client.send_goal_async(rotate_angle_msg)
    self._rotate_angle_action_send_goal_future.add_done_callback(self.rotate_angle_goal_response_callback)

  def rotate_angle_goal_response_callback(self, future):
    goal_handle = future.result()
    if DEBUG:
      printMsg = "rotate_angle_goal_response_callback(): Goal Accepted: {}".format(goal_handle.accepted)
      print(printMsg)

    if not goal_handle.accepted:
      self.get_logger().info('rotate Goal Rejected :(')
      return

    self.get_logger().info('rotate Goal Accepted :)')

    self._get_rotate_angle_result_future = goal_handle.get_result_async()
    self._get_rotate_angle_result_future.add_done_callback(self.get_rotate_angle_result_callback)

  def get_rotate_angle_result_callback(self, future):
    result = future.result().result
    if DEBUG:
      printMsg = "get_rotate_angle_result_callback(): rotate Result {} %".format(result)
      print(printMsg)
  ...



  def wali_main_cb(self):
    try:
...
        self.rotate_angle_action_send_goal(angle=math.pi)    # pi=180 deg
...
def main():
  rclpy.init(args=None)
  wali_node = WaLINode()
  try:
    rclpy.spin(wali_node)
  except KeyboardInterrupt:
    pass
  except ExternalShutdownException:
    sys.exit(0)
  finally:
    wali_node.destroy_node()
    try:
      rclpy.try_shutdown()
    except:
      pass


if __name__ == '__main__':
    main()

ROS can really make the easy stuff complicated

2 Likes

Simple?

You are kidding, right?

I have never noticed that it was simple based on the comments both you and Keith have been making.  In fact it has always struck me as being overly complex - it seems that you have to perform the Labors of Hercules to make the robot do even the simplest things.

Maybe I’m wrong?  I don’t know.

:man_shrugging:
:man_facepalming:

Exactly, but the hard stuff? ROS has you covered in 1/50th the time and code. There is something I’m missing, like a made for my robot python interface that would allow:

import ros2myrobotinterface


def main():
    myROSrobot = ros2myrobotinterfce.BestROS2RobotInTheWorld()
    myROSrobot.turn_degrees(180)
    while myROSrobot.battery_state.percent > 25:
        myROSrobot.map_my_house("async")
    myROSrobot.return_to_dock()
    myROSrobot.chill()
1 Like

Ok, I am confused.

On the one hand I here Keith and yourself talking about how much of a pain in the tush ROS is, then you turn around and in the same breath make it sound trivially easy.

So, which is it?

2 Likes

If you think small detail, ROS is HUGE. If you think big picture, ROS is small detail.

The architecture and the mechanisms of ROS are simple principles that can be understood completely in a few hours reading.

Discovering and learning to use one of the released packages ad-hoc teams of smart people have dedicated years to designing, coding, testing, modularizing, parameterizing, maintaining, re-designing, re-packaging, can take a few minutes if you find a good Internet article or follow a book.

Understanding how to synthesize with the plethora of packages and create something new of your own takes a lot of sleepless nights and a lot of dreaming.

I used to tell new software engineers that they will know how to do things after a year on the job, and will also know how much they do not understand.

ROS is small. The quality free open source software available for a ROS developer is HUGE.

So ROS is easy in some sense, and unknowably hard in reality.

1 Like

Well to be fair, ROS(2) is not robot specific. So someone has to write the robot specific functionality. I bet if you looked at the egpg class you’d see similar complexity for the turn_degrees() method.

/K

procedural.

I started programming before there were threads or multi-processing. The introduction of operating system time-slicing multiple programs continued to allow each single program to operate as the only game in town, and does not force multi-thread/process thinking.

I struggle to imagine true multi-process solutions, and ROS taking multi-process to distributed computing enables amazing benefits but adds opaque layers into my designs.

Like Python WaLi running in a terminal shell on my ROS2 desktop over Ubuntu desktop over VMware Fusion over macOS stops noticing /battery_state topics, (after 12 or so hours), that continue to be published by the robot sitting in the next room.

But then for over a year that same Apple desktop has been periodically stopping processing the key presses it receives from my bluetooth keyboard. That is also opaque.

1 Like