Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bash script to use Anaconda with ROS
### This script wraps all executables in the anaconda bin folder so that they can be used without adding Anaconda
### to the path which would break some functionality of ROS (Robot Operating System)
###
### The commands e.g. jupyter notebook will cause the script to add anaconda to the path, start jupyter notebook
### and after jupyter notebook terminated remove anaconda from the path again
###
### Notable commands:
### * release-the-snake Adds conda to the path and removes all aliases defined by this script
### Conda will stay in the PATH until the end of the session (terminal is closed) or
### until "cage-the-snake" is called
### * cage-the-snake Removes conda from the path and redefines all aliases for anaconda executables
### * source activate [env] Works just like with anaconda in the PATH, will activate the environment or (root) and
### Anaconda will stay in the PATH for the remaining session or until "source deactivate" is run
### * source deactivate Deactivates the environment and if Anaconda wasn't released manually using release-the-snake
### Anaconda will be removed from the PATH again.
if [ -z ${_ROS_CONDA_ADDED+x} ]
then
_ROS_CONDA_PATH=~/anaconda3/bin
_ROS_CONDA_ADDED=0
_ROS_CONDA_ALIASES=''
_ROS_CONDA_RELEASED_MANUALLY=0
_ROS_CONDA_PYTHONPATH_WITHOUT_ROS=$PYTHONPATH
fi
function _ROS_CONDA_addAliases {
if [[ $_ROS_CONDA_ALIASES != '' ]]
then
echo "ROS Conda Wrapper: Error! Aliases already defined!"
_ROS_CONDA_removeAliases
fi
for file in $_ROS_CONDA_PATH/*
do
local name
name=${file##*/}
if ! [ -x "$(command -v $name)" ]
then
alias $name='_ROS_CONDA_runWithConda '$name' $@'
_ROS_CONDA_ALIASES=$_ROS_CONDA_ALIASES" "$name
fi
done
}
function _ROS_CONDA_removeAliases {
for cmd in $_ROS_CONDA_ALIASES
do
unalias $cmd
done
_ROS_CONDA_ALIASES=''
}
function _ROS_CONDA_runWithConda {
_ROS_CONDA_ensureCondaInPath
command $@
_ROS_CONDA_removeCondaFromPath
}
function _ROS_CONDA_ensureCondaInPath {
if [ $_ROS_CONDA_ADDED -eq 1 ]
then
return 1 # false
fi
_ROS_CONDA_ADDED=1
# Check that the path doesn't start, end or contain the ros conda path
if [[ $PATH != $_ROS_CONDA_PATH":"* && $PATH != *":"$_ROS_CONDA_PATH && $PATH != *":"$_ROS_CONDA_PATH":"* ]]
then
export PATH=$_ROS_CONDA_PATH:$PATH
# Backup and clear python path to keep ros from checking ros directories for python modules
_ROS_CONDA_PYTHONPATH_BACKUP=$PYTHONPATH
export PYTHONPATH=$_ROS_CONDA_PYTHONPATH_WITHOUT_ROS
# Unalias the stuff
_ROS_CONDA_removeAliases
return 0 # true
fi
return 1
}
function _ROS_CONDA_removeCondaFromPath {
if [[ $PATH = $_ROS_CONDA_PATH":"* ]]
then
export PATH=${PATH#$_ROS_CONDA_PATH:}
elif [[ $PATH = *":"$_ROS_CONDA_PATH ]]
then
export PATH=${PATH%:$_ROS_CONDA_PATH}
elif [[ $PATH = *":"$_ROS_CONDA_PATH":"* ]]
then
export PATH=${PATH//:$_ROS_CONDA_PATH:/:}
fi
if [ $_ROS_CONDA_ADDED -eq 1 ]
then
# Restore ROS PYTHONPATH
export PYTHONPATH=$_ROS_CONDA_PYTHONPATH_BACKUP
_ROS_CONDA_addAliases
fi
_ROS_CONDA_ADDED=0
}
function _ROS_CONDA_sourceWrapper {
if [ $1 == "activate" ]
then
_ROS_CONDA_ensureCondaInPath
if [ $# == 1 ]
then
# If only source activate call source activate root.
# Otherwise it will fail. Don't know why though
command source activate
else
command source $@
fi
elif [ $1 == "deactivate" ]
then
command source deactivate
if [ $_ROS_CONDA_RELEASED_MANUALLY -eq 0 ]
then
_ROS_CONDA_removeCondaFromPath
fi
else
command source $@
fi
}
if [ $_ROS_CONDA_ADDED -eq 0 ]
then
if [[ $_ROS_CONDA_ALIASES != '' ]]
then
_ROS_CONDA_removeAliases
fi
_ROS_CONDA_addAliases
fi
alias source='_ROS_CONDA_sourceWrapper'
alias release-the-snake='_ROS_CONDA_RELEASED_MANUALLY=1; if _ROS_CONDA_ensureCondaInPath; then echo "All hail the snake!"; else echo "The snake is in another castle!
Jk, you released it already."; fi'
alias cage-the-snake='_ROS_CONDA_RELEASED_MANUALLY=0; _ROS_CONDA_removeCondaFromPath; echo "The snake has been caged if it wasn'"'"'t already."'
@StefanFabian

This comment has been minimized.

Copy link
Owner Author

commented Jan 8, 2018

To make Anaconda work with ROS:

  1. Remove the line that adds the anaconda bin folder to your PATH in the ~/.bashrc file (if you've let anaconda add itself to the PATH during installation)
  2. Download this file and move it to your home folder
  3. Change _ROS_CONDA_PATH in line 19 to the path of your Anaconda bin folder (if you didn't install it to ~/anaconda3)
  4. Add the following line to your ~/.bashrc file before any ros setup bash files are sourced
    source ~/.anaconda_with_ros_wrapper.bash

This script creates aliases for all executables in the anaconda binary folder that are not already present on the system.
So, basically, it checks for each executable in the binary folder if the system already has an executable with that name in the PATH and only if not it creates an alias that adds Anaconda to the PATH, executes the command and removes Anaconda from the PATH again.
For more info, read the information at the top of the script.

@StefanFabian

This comment has been minimized.

Copy link
Owner Author

commented May 2, 2018

Update 1:

Added functionality to remove ROS from the python path. The issue here being that python looks for packages in the ros paths which may not be compatible with the python version used in the anaconda environment.

IMPORTANT:

To make this functionality as universal as possible, I chose to backup the PYTHONPATH when the script is first sourced. This means it is now necessary to source the .anaconda_with_ros_wrapper.bash before you source any ros setup bash files. The script will backup the PYTHONPATH environment variable when it is loaded and restore the backup when you use any command that activates anaconda. Once you're done with anaconda and deactivate it, the PYTHONPATH is set to whatever it was before the backup was restored.

@thejeshk

This comment has been minimized.

Copy link

commented Mar 14, 2019

Hello Stefan,

I appreciate your work here. But I want to use two user accounts for ROS in one account and for Anaconda (Jupyter notebook) for other projects

My question as most of the root installations are global for all users will there be still conflict??

Thanks in advace

Regards
TK

@StefanFabian

This comment has been minimized.

Copy link
Owner Author

commented Mar 21, 2019

Hey @thejeshk,
thank you! Sorry for the late reply, I only noticed your comment by accident. Unfortunately, GitHub doesn't notify me about new comments here. If anyone reading this has any questions, please don't hesitate to contact me directly.

No, if you use separate accounts for ROS and Anaconda, it shouldn't clash. The installation is global but the conflicts only happen when you source the ros setup.bash and add Anaconda to the PATH environment variable. As long as you don't source ROS on your Anaconda account and don't have Anaconda in your PATH on your ROS account, you shouldn't run into any issues.
I've used that setup for some time but ultimately it was too much of a hassle and a waste of disk space to switch users all the time.

Best,
Stefan

@rojas70

This comment has been minimized.

Copy link

commented Apr 5, 2019

So could we place this bash file in our .bashrc file immediately before sourcing /opt/ros/.../setup.bash and the workspace setup.bash files?

I realize there will be times in which we will use anaconda that we are not using ros. At these times, we could comment out the line in the .bashrc file.

@StefanFabian

This comment has been minimized.

Copy link
Owner Author

commented Apr 9, 2019

Hey @rojas70,
sorry for the late reply, as already mentioned I don't get notified about comments and again saw it by accident because I'm upgrading to 18.04 today and had to redownload the script.

Regarding your question, I'm not sure what you mean?
As instructed in the first comment, you have to place it before sourcing the ros setup.bash and your workspace setup.bash.
You should also remove whatever anaconda added to the .bashrc.
You could, of course, comment out any ros related setup.bash files at any time but the intention of this script is making this unnecessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.