Skip to content

Commit

Permalink
Merge pull request #213 from hello-robot/feature/check_updates
Browse files Browse the repository at this point in the history
Add automatic update checking to command line tools
  • Loading branch information
hello-binit authored Dec 7, 2023
2 parents af2fb95 + bbb5b3e commit 0b4faa2
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 80 deletions.
6 changes: 5 additions & 1 deletion body/stretch_body/robot_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@
"datefmt": "%m/%d/%Y %H:%M:%S"
}
}
}}
},
"system_check": {
"show_sw_exc": False
},
}

class RobotParams:
"""Build the parameter dictionary that is available as stretch_body.Device().robot_params.
Expand Down
22 changes: 16 additions & 6 deletions docs/robot_parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ Additional sources of parameters for Stretch Body to import in when organizing t
The most common reason to set an additional parameter source is to supply parameters relating to a new [tool](#tool).

| Parameter | Default Value |
| --------- | ------------- |
| params | `[]` |
|-----------|---------------|
| params | `[]` |

### tool

You can swap the tool (or "end-effector") on Stretch. There's a [repository of 3D printable tools](https://github.com/hello-robot/stretch_tool_share/blob/master/README.md) that includes a USB camera tool, a phone holder tool, a dry erase marker tool, and many more. Many of these tools come with a Python class that extends Stretch Body's `EndOfArm` class to implement functionality specific to the tool. For example, the USB camera tool comes with a [`ToolUSBCamWrist`](https://github.com/hello-robot/stretch_tool_share/blob/master/python/stretch_tool_share/usbcam_wrist_v1/tool.py) class, named `tool_usbcam_wrist`, to take pictures or return a video stream directly from Stretch Body. You can also create your own custom tools and extend `EndOfArm` to expose functionality custom to your tool. More information on swapping/creating tools is available in the [Tool Change Tutorial](../../stretch_tutorials/stretch_body/tutorial_tool_change.md).

After attaching the hardware to Stretch's wrist, set this parameter to your tool class's name to change which tool class is imported into Stretch Body. See also [params](#params) for supplying parameters needed by your tool class.

| Parameter | Default Value |
| ------------ | ------------------------ |
| Parameter | Default Value |
|------------|--------------------------|
| robot.tool | `'tool_stretch_gripper'` |

### use_multiturn

The Dynamixel joints on the robot have a "multiturn" or "Extended Position Control" mode, which allows the Dynamixel servo to rotate many revolutions. This is in contrast to regular "Position Control" mode, where the servo is limited to 360° rotation. The joints where the servos have gear reductions operate in multiturn mode to achieve the desired range. In the other joints, the servo directly controls the position of the joint, so multiple revolutions are not required. More details on the Dynamixel's control modes are [available here](https://emanual.robotis.com/docs/en/dxl/x/xl430-w250/#operating-mode11).

| Parameter | Default Value |
| ------------------------------- | ------------- |
| Parameter | Default Value |
|-------------------------------|---------------|
| head_pan.use_multiturn | `0` * |
| head_tilt.use_multiturn | `0` |
| stretch_gripper.use_multiturn | `1` |
Expand All @@ -36,3 +36,13 @@ The Dynamixel joints on the robot have a "multiturn" or "Extended Position Contr
| wrist_roll.use_multiturn | `0` |

\* `head_pan.use_multiturn` is `0` for most Stretch robots, except for some early RE1s. For those robots, the parameter is set to `1` in "stretch_configuration_params.yaml".

## Parameters for Command Line Tools

### show_sw_exc

In the `stretch_robot_system_check.py` tool, the "Checking Software" section is wrapped in a try/except because of the experimental nature of the code. The tool is introspecting the system and relying on resources/files to be available in specific places with specific formats. Since the tool's output needs to be easily understood, the error or exception cannot be shown (hence the try/except block). This parameter allows the tool to raise the exception and display it in the terminal. This is useful for debugging purposes.

| Parameter | Default Value |
|--------------------------|---------------|
| system_check.show_sw_exc | False |
106 changes: 106 additions & 0 deletions tools/bin/stretch_robot_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,122 @@
from __future__ import print_function
import stretch_body.robot as robot
import argparse
import sys
import time
import json
import yaml
import pathlib
import requests
import xmltodict
import multiprocessing
import http.client as httplib
try:
import stretch_factory.firmware_available
factory_installed = True
except:
factory_installed = False
import stretch_body.hello_utils as hu
hu.print_stretch_re_use()

parser=argparse.ArgumentParser(description='Find zeros for all robot joints')
args=parser.parse_args()

def fetch_updates_in_background():
def have_internet():
conn = httplib.HTTPSConnection("8.8.8.8", timeout=5)
try:
conn.request("HEAD", "/")
return True
except Exception:
return False
finally:
conn.close()
def get_latest_pypi_version(url):
resp = requests.get(url)
if resp.status_code == 200:
releases = xmltodict.parse(resp.text)['rss']['channel']['item']
for i in range(len(releases)):
if 'dev' not in releases[i]['title']:
return releases[i]['title']
return None
def get_latest_github_commit(url):
resp = requests.get(url)
if resp.status_code == 200:
return json.loads(resp.text)[0]['sha']
return None

try:
start = time.time()
scans_dir = pathlib.Path('~/stretch_user/log/updates_logger').expanduser()
if not scans_dir.is_dir():
scans_dir.mkdir(parents=True, exist_ok=True)
datetime_str = hu.create_time_string()
scan_file = scans_dir / f'updates_scan.{datetime_str}.yaml'
scan_log = scans_dir / f'log_updates_scan.{datetime_str}.log'

# override stdout/stderr
sys.stdout = open(str(scan_log), "a")
sys.stderr = open(str(scan_log), "a")

# check for Stretch Factory installed
if not factory_installed:
return
print('background: got factory installed!', time.time() - start, flush=True)

# check for internet connection
if not have_internet():
return
print('background: got internet!', time.time() - start, flush=True)

# check for firmware updates
use_device = {'hello-motor-arm': True, 'hello-motor-right-wheel': True, 'hello-motor-left-wheel': True, 'hello-pimu': True, 'hello-wacc': True,'hello-motor-lift': True}
fa = stretch_factory.firmware_available.FirmwareAvailable(use_device)
scan_dict = {
'firmware': {
'hello-pimu': str(fa.get_most_recent_version('hello-pimu', None)),
'hello-wacc': str(fa.get_most_recent_version('hello-wacc', None)),
'hello-motor-arm': str(fa.get_most_recent_version('hello-motor-arm', None)),
'hello-motor-lift': str(fa.get_most_recent_version('hello-motor-lift', None)),
'hello-motor-left-wheel': str(fa.get_most_recent_version('hello-motor-left-wheel', None)),
'hello-motor-right-wheel': str(fa.get_most_recent_version('hello-motor-right-wheel', None)),
},
'version': '0.0',
}
print('background: got latest firmware!', time.time() - start, flush=True)

# check for pip updates
scan_dict['pip'] = {
'hello-robot-stretch-body': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-body/releases.xml"),
'hello-robot-stretch-body-tools': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-body-tools/releases.xml"),
'hello-robot-stretch-tool-share': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-tool-share/releases.xml"),
'hello-robot-stretch-factory': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-factory/releases.xml"),
'hello-robot-stretch-diagnostics': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-diagnostics/releases.xml"),
'hello-robot-stretch-urdf': get_latest_pypi_version("https://pypi.org/rss/project/hello-robot-stretch-urdf/releases.xml"),
}
print('background: got latest pip!', time.time() - start, flush=True)

# check latest pushed github commits
scan_dict['ros'] = {
'stretch_ros': get_latest_github_commit("https://api.github.com/repos/hello-robot/stretch_ros/commits"),
'stretch_ros2': get_latest_github_commit("https://api.github.com/repos/hello-robot/stretch_ros2/commits"),
}
print('background: got latest github!', time.time() - start, flush=True)

# save to updates_scan directory
with open(str(scan_file), 'w') as outfile:
yaml.dump(scan_dict, outfile)
print('background: saved to scan logger dir', time.time() - start, flush=True)
except:
pass
background_process = multiprocessing.Process(target=fetch_updates_in_background)

r=robot.Robot()
r.startup()
if not r.pimu.status['runstop_event']:
background_process.start()
r.home()
background_process.terminate()
background_process.join()
else:
r.logger.warning('Cannot home while run-stopped')
r.stop()
Loading

0 comments on commit 0b4faa2

Please sign in to comment.