Skip to content

Instantly share code, notes, and snippets.

@PeterMitrano
Last active November 29, 2020 19:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PeterMitrano/f2c8eea79661feef1d32c6914ae2c578 to your computer and use it in GitHub Desktop.
Save PeterMitrano/f2c8eea79661feef1d32c6914ae2c578 to your computer and use it in GitHub Desktop.
ROS Noetic via conda workspace setup
#!/bin/env python
import argparse
from multiprocessing import Process
import contextlib
import os
import pathlib
from subprocess import run
import requests
import yaml
@contextlib.contextmanager
def working_directory(path):
"""Changes working directory and returns to previous on exit."""
prev_cwd = pathlib.Path.cwd()
os.chdir(path)
try:
yield
finally:
os.chdir(prev_cwd)
class CondaRunner:
def __init__(self, conda_env_name):
""" Just calling conda activate will not work inside the python script"""
self.conda_env_name = conda_env_name
init_commands = [
'eval "$(conda shell.bash hook)"',
'conda activate ' + self.conda_env_name,
]
self.init_command = ';'.join(init_commands)
def run(self, command):
combined_command = self.init_command + '; ' + command
print(combined_command)
run(combined_command, shell=True)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("ws_dir", type=pathlib.Path)
parser.add_argument("conda_env_name")
parser.add_argument("--no-create-conda-env", action='store_true')
args = parser.parse_args()
args.ws_dir.mkdir(exist_ok=True)
with working_directory(args.ws_dir):
src_dir = pathlib.Path('src')
src_dir.mkdir(exist_ok=True)
from time import perf_counter
t0 = perf_counter()
setup_conda_proc = Process(target=setup_conda, args=(args.no_create_conda_env, args.conda_env_name))
setup_conda_proc.start()
setup_workspace_proc = Process(target=setup_workspace, args=(src_dir,))
setup_workspace_proc.start()
setup_conda_proc.join()
setup_workspace_proc.join()
print('Setup Time:', perf_counter() - t0)
# we need the conda environment to exist before we do this, so join here
cr = CondaRunner(args.conda_env_name)
with working_directory(src_dir):
cr.run('catkin_init_workspace')
cr.run('touch catkin_tools/CATKIN_IGNORE')
build_catkin_tools(cr)
build_non_catkin_deps(cr, args.conda_env_name)
print('Total Time:', perf_counter() - t0)
print("")
print("Done!")
print("You may now activate the conda environment and run catkin build")
def setup_conda(no_create_conda_env, conda_env_name):
if not no_create_conda_env:
create_conda_env(conda_env_name)
def setup_workspace(src_dir):
with working_directory(src_dir):
rosinstall_url = 'https://raw.githubusercontent.com/UM-ARM-Lab/documentation/master/rosinstalls/' \
'conda-ros-noetic/.rosinstall?token=AA6TGERCVJ6IDFZXZ3OQIY27ZPJGS'
run(['wget', rosinstall_url, '-O', '.rosinstall'])
run(['vcs', 'import', '--input', '.rosinstall'])
def build_catkin_tools(cr):
with working_directory('catkin_tools'):
cr.run('python setup.py install')
def build_non_catkin_deps(cr, conda_env_name):
with working_directory('ignition-common3'):
pathlib.Path("build").mkdir(exist_ok=True)
with working_directory('build'):
cr.run('cmake .. -DCMAKE_INSTALL_PREFIX=' + '~/miniconda3/envs/' + conda_env_name)
cr.run('make -j8')
cr.run('make install')
def create_conda_env(conda_env_name):
# Load conda env yaml file
env_yml_url = 'https://gist.githubusercontent.com/PeterMitrano/' \
'ac204903ebb6e22e190bf1088fb40e31/raw/conda-ros-noetic-env.yml'
r = requests.get(env_yml_url, stream=True)
env = yaml.load(r.raw, Loader=yaml.SafeLoader)
# Change the name
env['name'] = conda_env_name
with open('env.yml', 'w') as env_file:
yaml.dump(env, env_file)
run(['conda', 'env', 'create', '-f', 'env.yml'])
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment