-
Notifications
You must be signed in to change notification settings - Fork 16
/
Makefile
198 lines (157 loc) · 6.19 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
.DEFAULT: default
### CUSTOMISABLE VARIABLES
#
# These variables have default values which may be overridden on the command line.
# Username used to prefix Docker images with.
WHOAMI ?= ${USER}
# Docker binary
DOCKER ?= docker
# Addition arguments to docker build. (E.g. set --no-cache to invalidate the
# current Docker cache if APT package information becomes outdated.)
DOCKER_BUILD_OPTS ?=
# What is a suitable name for the current git branch? Use it as the Docker tag.
# If this is not a git repo, or there is no HEAD ref, use "latest" as a
# fallback.
TAG ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "latest")
# The name of this project
PROJECT ?= robotic_surgery
# The size of the GUI screen
GUI_SCREEN ?= 1440x900
VNC_VIEWER ?= vncviewer
# Any other options to pass to vncviewer
VNC_VIEWER_OPTS ?=
# Override to run a specific command in the container via make shell
CMD ?=
# Override to run a specific command in the container via make gui
GUI_CMD ?= bash
# Override to pass additional arguments to catkin_make via make build
CM_ARGS ?=
# ROS package and launch file and additional parameters to use with roslaunch (make launch)
PKG ?= surgery_launch
LAUNCH ?= surgery.launch
PARAMS ?=
### DERIVED VARIABLES
#
# Variables which are not intended to be overridden on the command line.
# Name of image to build.
PROJECT_IMAGE := $(WHOAMI)/$(PROJECT):$(TAG)
# Docker run options:
# -it allocate a pseudo TTY and keep stdin open on interactive
# sessions (mosly useful for debugging)
# --privileged allow container to access hardware
# -P open all network ports on the container
DOCKER_RUN_COMMON := $(DOCKER) run -it --privileged -P
# If /dev/ttyUSB0 exists on the host, expose it to the container. This is the
# USB serial interface used to talk to the dynamixel bus.
USB_DEVICE:=/dev/ttyUSB0
ifneq (,$(wildcard $(USB_DEVICE)))
DOCKER_RUN_COMMON += -v /dev/ttyUSB0:/dev/ttyUSB0
endif
# If /dev/video0 exists on the host, expose it to the container. This is the
# USB interface used to talk to a USB webcam
VIDEO_DEVICE:=/dev/video0
ifneq (,$(wildcard $(VIDEO_DEVICE)))
DOCKER_RUN_COMMON += -v /dev/video0:/dev/video0
endif
# If /dev/video1 exists on the host, expose it to the container. This is the
# USB interface used to talk to a USB webcam
VIDEO_DEVICE:=/dev/video1
ifneq (,$(wildcard $(VIDEO_DEVICE)))
DOCKER_RUN_COMMON += -v /dev/video1:/dev/video1
endif
# Run a command in the image as ros or root.
DOCKER_RUN_ROS := -u ros -w /home/ros/workspace -e HOME=/home/ros "$(PROJECT_IMAGE)"
DOCKER_RUN_ROOT := -u root "$(PROJECT_IMAGE)"
# Name of the SSH container and its associated container id, start image and IP address
SSH_NAME := $(WHOAMI)_$(PROJECT)_ssh
SSH_CID_CMD := $(DOCKER) inspect -f '{{ .Id }}' $(SSH_NAME) 2>/dev/null
SSH_IMAGE_ID_CMD := $(DOCKER) inspect -f '{{ .Image }}' $(SSH_NAME) 2>/dev/null
SSH_IP_CMD := $(DOCKER) inspect -f '{{ .NetworkSettings.IPAddress }}' $(SSH_NAME) 2>/dev/null
SSH_CID := $(shell $(SSH_CID_CMD))
SSH_IP := $(shell $(SSH_IP_CMD))
SSH_IMAGE_ID := $(shell $(SSH_IMAGE_ID_CMD))
# The id for the image we have built.
IMAGE_ID_CMD := $(DOCKER) inspect -f '{{ .Id }}' $(PROJECT_IMAGE) 2>/dev/null
# Launch a SSH session into the container
SSH_OPTS := -o StrictHostKeyChecking=no -i config/ros_user_ssh_key
SSH := ssh $(SSH_OPTS) -l ros
SCP := scp $(SSH_OPTS)
SFTP := sftp $(SSH_OPTS)
# Name of the "delete my work" target
REMOVE_SSH_TARGET := delete_all_my_work
.PHONY: default
default: build
.PHONY: image
image:
$(DOCKER) build -t $(PROJECT_IMAGE) $(DOCKER_BUILD_OPTS) src
# We have to do this curious "double rule" here because the $(shell ...)
# functions are evaluated at the *start* of the rule no matter where within the
# rule they occur.
.PHONY: ssh $(REMOVE_SSH_TARGET)
.PHONY: _existing_ssh_container _launch_ssh_container_if_necessary _ssh_container_valid
# If a ssh container is not running, launch one. We give it the fixed name
# $(SSH_NAME) and run it in detached mode.
_launch_ssh_container_if_necessary: image
@if [ -z "$(SSH_CID)" ] ; then \
$(DOCKER_RUN_COMMON) --name=$(SSH_NAME) -d $(DOCKER_RUN_ROOT) \
/usr/sbin/sshd -D ; \
fi
_existing_ssh_container: _launch_ssh_container_if_necessary
$(eval SSH_CID := $(shell $(SSH_CID_CMD)))
$(eval SSH_IP := $(shell $(SSH_IP_CMD)))
$(eval SSH_IMAGE_ID := $(shell $(SSH_IMAGE_ID_CMD)))
_ssh_container_valid: image _existing_ssh_container
$(eval IMAGE_ID := $(shell $(IMAGE_ID_CMD)))
@if [ "$(SSH_IMAGE_ID)" != "$(IMAGE_ID)" ] ; then \
echo "The current SSH container is for an old version of the build image." ; \
echo "Remove it with\n" ; \
echo " $(MAKE) $(REMOVE_SSH_TARGET)\n" ; \
echo "and try again." ; \
echo "**IMPORTANT** THIS WILL DELETE ANY LOCAL CHANGES IN THE CONTAINER!" ; \
false ; \
fi
ssh: _ssh_container_valid
scripts/wait_port.sh $(SSH_IP) 22
@echo "SSH started. Log in with\n"
@echo " $(SSH) $(SSH_IP)"
$(REMOVE_SSH_TARGET):
if [ -n "$(SSH_CID)" ]; then \
$(DOCKER) stop $(SSH_NAME) ; \
$(DOCKER) rm $(SSH_NAME) ; \
fi
# Launch a login shell in the image.
.PHONY: shell
shell: ssh
$(SSH) -X $(SSH_IP) "$(CMD)"
# Launch an SFTP client in the image.
sftp: ssh
$(SFTP) ros@$(SSH_IP)
# Launch a GUI session. This does some horrible magic in order to launch a SSH
# session into the container, send it to the background, launch vncviewer and
# then, after vncviewer exits, kill the original SSH session.
.PHONY: gui
gui: GUI_CMD_TMP := $(shell mktemp -t gui-cmd-robotic-surgery.XXXXXX)
gui: ssh
echo "$(GUI_CMD)" > "$(GUI_CMD_TMP)"
$(SCP) $(GUI_CMD_TMP) ros@$(SSH_IP):/home/ros/gui-command.sh
rm -f $(GUI_CMD_TMP)
$(SSH) $(SSH_IP) x11vnc -forever -xdummy \
-env FD_PROG=\"/usr/bin/lxsession -e LXDE -s Lubuntu\" \
-env FD_GEOM=\"${GUI_SCREEN}\" & \
scripts/wait_port.sh $(SSH_IP) 5900 && \
$(VNC_VIEWER) $(VNC_VIEWER_OPTS) $(SSH_IP) ; \
$(SSH) $(SSH_IP) killall lxsession
# Run a roslaunch file
.PHONY: launch gui_launch
launch: ssh
$(SSH) -X $(SSH_IP) 'roslaunch $(PKG) $(LAUNCH) $(PARAMS)'
gui_launch: GUI_CMD := roslaunch $(PKG) $(LAUNCH) $(PARAMS)
gui_launch: gui
# Build the actual software
.PHONY: build
build: ssh
$(SSH) $(SSH_IP) 'cd ~/workspace && catkin_make $(CM_ARGS)'
# Run the tests
.PHONY: test
test: ssh
$(SSH) $(SSH_IP) 'cd ~/workspace && catkin_make run_tests'