> For the complete documentation index, see [llms.txt](https://docs.hello-robot.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hello-robot.com/stretch4-ros2-repo/hello_helpers.md).

# hello\_helpers

### Overview

*hello\_helpers* mostly consists of the hello\_helpers Python module. This module provides various Python files used across stretch\_ros2 that have not attained sufficient status to stand on their own.

### Capabilities

*fit\_plane.py* : Fits planes to 3D data.

*hello\_misc.py* : Various functions, including a helpful Python object with which to create ROS nodes.

*hello\_ros\_viz.py* : Various helper functions for vizualizations using RViz.

### Typical Usage

```python
import hello_helpers.fit_plane as fp
```

```python
import hello_helpers.hello_misc as hm
```

```python
import hello_helpers.hello_ros_viz as hr
```

## API

### Classes

#### [HelloNode](https://github.com/hello-robot/stretch4_ros2/blob/jazzy/hello_helpers/src/hello_helpers/hello_misc.py)

This class is a convenience class for creating a ROS 2 node for Stretch. The most common way to use this class is to extend it. In your extending class, the main function would call `HelloNode`'s main function. This would look like:

```python
import hello_helpers.hello_misc as hm

class MyNode(hm.HelloNode):
    def __init__(self):
        hm.HelloNode.__init__(self)

    def main(self):
        hm.HelloNode.main(self, 'my_node', 'my_node', wait_for_first_pointcloud=False)
        # my_node's main logic goes here

node = MyNode()
node.main()
```

There is also a one-liner class method for instantiating a `HelloNode` for easy prototyping. One example where this is handy in sending pose commands from iPython:

```python
# roslaunch the stretch launch file beforehand

import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.move_to_pose({'lift_joint': 0.4})
```

**Attributes**

**`dryrun`**

This attribute allows you to control whether the robot actually moves when calling `move_to_pose()`, `home_the_robot()`, `stow_the_robot()`, or other motion methods in this class. When `dryrun` is set to True, these motion methods return immediately. This attribute is helpful when you want to run just the perception/planning part of your node without actually moving the robot. For example, you could replace the following verbose snippet:

```python
# launch the stretch driver launch file beforehand
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
actually_move = False
[...]
if actually_move:
    temp.move_to_pose({'translate_mobile_base': 1.0})
```

to be more consise:

```python
# launch the stretch driver launch file beforehand
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
[...]
temp.dryrun = True
temp.move_to_pose({'translate_mobile_base': 1.0})
```

**Methods**

**`move_to_pose(pose, blocking=False, custom_contact_thresholds=False, duration=2.0)`**

This method takes in a dictionary that describes a desired pose for the robot and communicates with [stretch\_driver](/stretch4-ros2-repo/stretch_core.md#stretchdrivernodesstretchdriver) to execute it. The basic format of this dictionary is string/number key/value pairs, where the keys are joint names and the values are desired position goals. For example, `{'lift_joint': 0.5}` would put the lift at 0.5m in its joint range. A full list of command-able joints is published to the `/stretch/joint_states` topic. Used within a node extending `HelloNode`, calling this method would look like:

```python
self.move_to_pose({'lift_joint': 0.5})
```

Internally, this dictionary is converted into a [JointTrajectory](https://docs.ros2.org/latest/api/trajectory_msgs/msg/JointTrajectory.html) message that is sent to a [FollowJointTrajectory action](http://docs.ros.org/en/noetic/api/control_msgs/html/action/FollowJointTrajectory.html) server in stretch\_driver. This method waits by default for the server to report that the goal has completed executing. However, you can return before the goal has completed by setting the `blocking` argument to False. This can be useful for preempting goals.

When the robot is in `position` mode, if you set `custom_contact_thresholds` to True, this method expects a different format dictionary: string/tuple key/value pairs, where the keys are still joint names, but the values are `(position_goal, effort_threshold)`. The addition of a effort threshold enables you to detect when a joint has made contact with something in the environment, which is useful for manipulation or safe movements. For example, `{'arm_joint': (0.5, 20)}` commands the telescoping arm fully out (the arm is nearly fully extended at 0.5 meters) but with a low enough effort threshold (20% of the arm motor's max effort) that the motor will stop when the end of arm has made contact with something. Again, in a node, this would look like:

```python
self.move_to_pose({'arm_joint': (0.5, 40)}, custom_contact_thresholds=True)
```

When the robot is in `trajectory` mode, if you set argument `duration` as `ts`, this method will ensure that the target joint positions are achieved over `ts` seconds. For example, the below would put the lift at 0.5m from its current position in `5.0` seconds:

```python
self.move_to_pose({'lift_joint': 0.5}, duration=5.0)
```

**`home_the_robot()`**

This is a convenience method to interact with the driver's [`/home_the_robot` service](/stretch4-ros2-repo/stretch_core.md#home_the_robot-std_srvstrigger).

**`stow_the_robot()`**

This is a convenience method to interact with the driver's [`/stow_the_robot` service](/stretch4-ros2-repo/stretch_core.md#stow_the_robot-std_srvstrigger).

**`stop_the_robot()`**

This is a convenience method to interact with the driver's [`/stop_the_robot` service](/stretch4-ros2-repo/stretch_core.md#stop_the_robot-std_srvstrigger).

**`get_tf(from_frame, to_frame)`**

Use this method to get the transform ([geometry\_msgs/TransformStamped](https://docs.ros2.org/latest/api/geometry_msgs/msg/TransformStamped.html)) between two frames. This method is blocking. For example, this method can do forward kinematics from the base\_link to the link between the gripper fingers, grasp\_center\_link, using:

```python
# launch the stretch driver launch file beforehand

import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
t = temp.get_tf('base_link', 'grasp_center_link')
print(t.transform.translation)
```

**`get_robot_floor_pose_xya(floor_frame='odom')`**

Returns the current estimated x, y position and angle of the robot on the floor. This is typically called with respect to the odom frame or the map frame. x and y are in meters and the angle is in radians.

```python
# launch the stretch driver launch file beforehand

import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
t = temp.get_robot_floor_pose_xya(floor_frame='odom')
print(t)
```

**`main(node_name, node_topic_namespace, wait_for_first_pointcloud=True)`**

When extending the `HelloNode` class, call this method at the very beginning of your `main()` method. This method handles setting up a few ROS components, including registering the node with the ROS server, creating a TF listener, creating a [FollowJointTrajectory](http://docs.ros.org/en/noetic/api/control_msgs/html/action/FollowJointTrajectory.html) client for the [`move_to_pose()`](#movetoposepose-returnbeforedonefalse-customcontactthresholdsfalse-customfullgoalfalse) method, subscribing to depth camera point cloud topic, and connecting to the quick-stop service.

Since it takes up to 30 seconds for the head camera to start streaming data, the `wait_for_first_pointcloud` argument will get the node to wait until it has seen camera data, which is helpful if your node is processing camera data.

**`quick_create(name, wait_for_first_pointcloud=False)`**

A class level method for quick testing. This allows you to avoid having to extend `HelloNode` to use it.

```python
# launch the stretch driver launch file beforehand

import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.move_to_pose({'lift_joint': 0.4})
```

**Subscribed Topics**

**/camera/depth/color/points (**[**sensor\_msgs/PointCloud2**](https://docs.ros2.org/latest/api/sensor_msgs/msg/PointCloud2.html)**)**

Provides a point cloud as currently seen by the Realsense depth camera in Stretch's head. Accessible from the `self.point_cloud` attribute.

```python
# launch the stretch driver launch file beforehand

import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp', wait_for_first_pointcloud=True)
print(temp.point_cloud)
```

**/stretch/joint\_states (**[**sensor\_msgs/JointState**](https://docs.ros2.org/latest/api/sensor_msgs/msg/JointState.html)**)**

Provides the current state of robot joints that includes joint names, positions, velocities, efforts. Accessible from the `self.joint_state` attribute.

```python
print(temp.joint_state)
```

**/mode (**[**std\_msgs/String**](https://docs.ros2.org/latest/api/std_msgs/msg/String.html)**)**

Provides the mode the stretch driver is currently in. Possible values include `position`, `trajectory`, `navigation`, `homing`, `stowing`.

```python
print(temp.mode)
```

**/tool (**[**std\_msgs/String**](https://docs.ros2.org/latest/api/std_msgs/msg/String.html)**)**

Provides the end of arm tool attached to the robot.

```python
print(temp.tool)
```

**Subscribed Services**

**/stop\_the\_robot (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to quickly stop any motion currently executing on the robot.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.stop_the_robot_service(TriggerRequest())
```

**/stow\_the\_robot (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to stow the robot arm.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.stow_the_robot_service(TriggerRequest())
```

**/home\_the\_robot (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to home the robot joints.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.home_the_robot_service(TriggerRequest())
```

**/switch\_to\_trajectory\_mode (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to quickly stop any motion currently executing on the robot.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.switch_to_trajectory_mode_service(TriggerRequest())
```

**/switch\_to\_position\_mode (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to quickly stop any motion currently executing on the robot.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.switch_to_position_mode_service(TriggerRequest())
```

**/switch\_to\_navigation\_mode (**[**std\_srvs/Trigger**](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html)**)**

Provides a service to quickly stop any motion currently executing on the robot.

```python
# launch the stretch driver launch file beforehand

from std_srvs.srv import TriggerRequest
import hello_helpers.hello_misc as hm
temp = hm.HelloNode.quick_create('temp')
temp.switch_to_navigation_mode_service(TriggerRequest())
```

### License

For license information, please see the LICENSE files.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hello-robot.com/stretch4-ros2-repo/hello_helpers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
