### 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."' |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
Hey @thejeshk, 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 Best, |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
Hey @rojas70, Regarding your question, I'm not sure what you mean? |
This comment has been minimized.
This comment has been minimized.
Hi, I'm a user of your ros with anaconda script, it used to work but I have found that with more recent versions of anaconda it has stopped. Anaconda now informs me when I try to activate an env that the shell has not been initialised and I must run conda init bash. Running conda init bash adds this to .bashrc
and now when I open a shell I get:
If you have a fix, it would be very much appreciated :) (I tried sending this on your website but it didn't work) |
This comment has been minimized.
This comment has been minimized.
What version are you using? PS: Thanks for the heads up regarding the contact form on my website. I've fixed it. But the good news is that github finally seems to send me email notifications for new comments. :) |
This comment has been minimized.
This comment has been minimized.
I'm on conda 4.6.14 - ok cool - I'll try source activate [env] |
This comment has been minimized.
This comment has been minimized.
@StefanFabian I wrote a small installable bash wrapper based on your code. It can be found here. |
This comment has been minimized.
To make Anaconda work with ROS:
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.