Categories
Climbing

Climbing in an ocean of darkness

My climbing partner and I wanted to get a few hours of practice in, so we headed out to exit 38 Thursday night. We knew we would be coming off the climb in the dark, but I don’t think either of us expected it to be so fun. Once the sun went down it was like climbing in an ocean of dark.

Night Climbing at Substation

The bright spot in the picture is Clay’s headlamp. He’s building an anchor and about to bring me up. The climb is only a 5.6, but we just wanted to practice a new anchor setup – so it was perfect. I climbed it once in the light, then brought up Clay and hiked off while he built his anchor. So I got to climb it both in the dark and in the light. It was a totally weird and different experience.

Categories
Robits!

Shark Hull Water Testing

The shark hull just passed a 48 hours float test. There was no change in weight or other signs it absorbed water. Using the bathtub enabled float testing in clean water – and this hull is huge so the bathtub was the only volume in which it would fit. That said – it turns out explaining why there is a robot floating in the bathtub can lead to unexpectedly awkward conversation.

Water Testing the Shark Hull

The new hull uses a blown polyurethane hull filler, which cast under pressure. That creates a closed cell foam but one dense enough for the hulls littoral pressure ratings. Tests show clear for moving on the rest of the design. 

Categories
Math

Never argue with a Mathematician…

The reason you never want to argue with a mathematician is simple – the homework. I awoke to find this waiting for me on the couch where I do my morning reading.

konrad_argument_May14th2019

Talking about metrics with my roommate quickly revealed a hole in how I thought about metrics, which was simply put wrong. I hadn’t realized that I tend to project higher dimensional problems into Euclidian spaces – and that included metrics. Still homework waiting for me in the morning was cold, funny, but ice cold.

Categories
Knifemaking Martial Arts Photos and Events Projects Uncategorized

A knife for father’s day

My nephew loves his dad.

I said I would help my nephew to make a training blade as a father’s day gift. I’d planned on a simple wooden trainer – but he had other ideas. After saying that “his dad deserved the best” – he talked over his options with me then spent the day in the shop making a rather awesome knife.

I was impressed, as it was a lot of time-consuming work. We started with an old piece of scrap, a half finished milling prototype for a knife I made a while back. He used files to finish shaping the blade. The blade was made out of aluminum, and he insisted on 5 sanding passes to get the blade face to look just right.

blade_for_dad_p1_July_8th_2018

Once he was happy with what the blade looked like – we stamped in his dad’s name on one side, and “I love you dad on the other”. He even made sure we checked that “I love you dad” would be right way up, and readable, when his dad was using the knife.

blade_for_dad_p2_July_8th_2018

We watched a bunch of YouTube videos on para-cord wrapping knife handles. Once we found a pattern he liked, we drilled the handle and he wrapped it up.

blade_for_dad_p3_July_8th_2018

It was a tricky process, as he had to hold tension on the cord, while setting the pattern on the top and bottom of the blade. I offered to do the wrapping, but he wanted to do it.

blade_for_dad_p4_July_8th_2018

In the end I was really impressed with what he made. It is a sweet training blade in itself, but my nephew was right – you can read “I love you dad” when you are using it, and thats just awesome.

blade_for_dad_p5_July_8th_2018

Categories
Toolboxes Tools

My Wednesday hammer….

This morning I was asking my nephew if he wanted to help me finish the hammer rack I was building. The conversation went something like this:

Nephew: “Do you really need that many hammers?”
Me: “Yes, yes I do!”
Nephew: “This is my Wednesday hammer, this is my….”

He is a funny kid. Might have a point though.

Categories
TensorFlow

TensorFlow – What not to do

This blog post was awesome. I am working through a lot of TensorFlow material lately and it was refreshing and atypical to find someone telling you what not to do.

I am capturing it here so I can find it again in the future. If you are interested in TensorFlow, or technical writing, this is worth a read: How Not To Program the TensorFlow Graph

Categories
Climbing

Climbing gear failure modes

This is why I love trad climbing; it really is the sport for engineers. Every single piece of gear and how it is used gets meticulously engineered and tested. I especially love black diamonds gear as Black Diamond’s testing lab posts a lot about their testing results.

Categories
Machine Learning Programming

Structuring TensorFlow Models

Danijar Hafner has an excellent tutorial on Structuring Your TensorFlow Models. I really liked it so I am posting it here so its always easy to find. He is using Python’s decorators to provide a lazy initialization for the graph components. Its a neat trick. Totally separate from TensorFlow, I am actively working on improving my Python programming and will definitely be using this approach in the future.

Categories
Climbing

Climbing at Index (April 26th)

Leaving Seattle at 7:30, I got to Index and met up with Cameron a little after 9. Then we headed over to our first climb of the day. It was the “ss-ultrabrutal”. I am glad I found about the name after we climbed it – that name is just awesomely intimidating.

It is a trad climb, Cameron led and I cleaned. At the time I thought it was just a 5.6 (it’s a 5.7) but it was an easy climb, and I had hard time on it, so while I enjoyed myself I came off it just feeling a little depressed about how out of climbing shape I was. Definitely time to hit the gym more. In the picture you can just make out Cameron at the bolts at the top of the climb. The climb traverses left to right on about a forty five degree angle – following the large crack above the old tunnel.

IMG_0023b

Next we moved over to do the GM route on The Country. Cameron had climbed it before and wanted to lead all three pitches in a single push. So I belayed him from the ground, then he rappelled back down to the first pitch belay ledge cleaning as he went. I’d thought I’d be doing the second two pitches, but I just made such a mess of cleaning the first pitch Cameron just pulled the rope and I cleaned the first pitch. You can see the rope line in the picture. Cameron had already been doing some rope soloing that morning – and I was having an off day – so we called it and went and put our heads in the river.

IMG_0025

Think I am kidding? Nope. Cameron put his head in the river and it looked so refreshing I followed suit.

IMG_0039

All in all a lovely day – but I confess after seeing the camping spot he snagged by showing up on a Wednesday, I was kicking myself for not joining the night before. I skipped the over night so I could attend a practice session on glacier travel. Lesson learned.

IMG_0035

The view from the river was even better.

IMG_0037

Categories
Programming

NetworkX Graph library for Python

I’ll admit – I still try and write Python like it was C or C++. To fix that for a while I am going to switch to writing things in Python for a while, while working on actually writing good Python.

Graph algorithms are the kidneys of computer science – there in the background filtering out all the bad things for us. In my switch over to writing in Python I needed to find a solid python graph library, and decided to try NetworkX. Here is a simple example program using it. These are mostly just notes for myself – but I am posting it here in case it is useful to anyone else.

This code is basically the NetworkX weighted graph example, with some annotations. Here is some code to create and plot a weighted graph.


import matplotlib.pyplot as plt
import networkx as nx

# Populate the graph...
map_graph = nx.Graph()

map_graph.add_edge('Issaquah','Bellevue', weight=0.11 )
map_graph.add_edge('Bellevue','Kirkland', weight=0.05 )
map_graph.add_edge('Bellevue','Redmond', weight=0.06 )
map_graph.add_edge('Kirkland','Redmond', weight=0.24 )
map_graph.add_edge('Bellevue','Seattle', weight=0.01 )
map_graph.add_edge('Renton','Seattle', weight=0.03 )
map_graph.add_edge('Renton','Bellevue', weight=0.48 )

# Determine the layout of points in the graph. Some other layouts that 
# would work here are spring_layout, shell_layout, and random_layout                                                                                                 
pos = nx.circular_layout( map_graph ) # Sets positions for nodes

# Put "dots" down for each node                                                     
nx.draw_networkx_nodes( map_graph, pos, node_size=700)

# Attaches Labesl to each node                                                               
nx.draw_networkx_labels( map_graph, pos, font_size=14, font_family='sans-serif')

map_edges = [(u,v) for (u, v, d) in map_graph.edges(data=True) ]

nx.draw_networkx_edges( map_graph,
                        pos,             # Spring
                        map_edges,       # List of edges                                     
                        width=5, alpha=0.5, edge_color='b', style='dashed' )

plt.axis('off')
plt.show()

The plotted graph looks something like this.

Screen Shot 2018-04-29 at 5.01.30 PM

One of the things I want from a graph library is the standard graph algorithms – like finding me the shortest path between nodes, or testing for the presence of a path at all. So for example to find the shortest path from Issaquah to Renton we could add the following code to the example above?:


# Generates the shortest path - but since there could be more than                                                   
# one of them what you get back is a "generator" from which you                                                      
# need to pluck the shortest path.                                                                                   
a_shortest_path = nx.all_shortest_paths(map_graph, source='Issaquah', target='Renton')                              

print( [p for p in a_shortest_path] )    

The added code will give the path [[‘Issaquah’, ‘Bellevue’, ‘Renton’]], which is the shortest path by number of edges traversed. To obtain the shortest path by edge weight we can use dijkstras like so:


a_shortest_path = nx.dijkstra_path(map_graph, ‘Issaquah’, ‘Renton’)
print( a_shortest_path )

Which gives the path: [‘Issaquah’, ‘Bellevue’, ‘Seattle’, ‘Renton’]

The problem is that this implementation of dijkstra’s fails when a path is not present between the origin and destination nodes. So for example if we add a disconnected vertex with no edges like below, searches on a path to that vertex will cause the call to fail.


map_graph.add_node(‘Mercer Island’)

Screen Shot 2018-04-29 at 8.15.15 PM

I think you need to use the has_path method to test for the existence of any path first, then if there is a path use dijkstras to find the minimum cost path. Something like this:


# Create a helper function for testing for a path
def shortest_weighted(from_node, to_node):
    if nx.has_path( map_graph, from_node, to_node ) == True :
	a_shortest_path = nx.dijkstra_path(map_graph, from_node, to_node)
        return( a_shortest_path )
    else:
        print("No path from",from_node,"to", to_node, "\r\n")
        return( False )

Then checking for the minimum path can look something like this:


# Test where path does not exist
shortest_weighted_path = shortest_weighted( 'Issaquah', 'Mercer Island' )
if shortest_weighted_path != False:
    print( shortest_weighted_path )

# Test where path does exist
shortest_weighted_path = shortest_weighted( 'Issaquah', 'Renton' )
if shortest_weighted_path != False:
    print( shortest_weighted_path )

Neither call will fail and checking for the existing path from Issaquah to Renton will return: [‘Issaquah’, ‘Bellevue’, ‘Seattle’, ‘Renton’]

Since the graphs are weighted – list comprehensions can be used to conditionally act based on edge weights. For example:


# Segment the nodes by weight                                                                                                  
map_red_edges  = [(u,v) for (u, v, d) in map_graph.edges(data=True) if d['weight'] >  0.1  ]
map_blue_edges = [(u,v) for (u, v, d) in map_graph.edges(data=True) if d['weight'] <= 0.1  ]

Then use the segmentation to perform multiple colorings.


nx.draw_networkx_edges( map_graph,
                        pos,             # Spring                                                                    
                        map_red_edges,   # List of edges                                                             
                        width=5,
                        alpha=0.5,
                        edge_color='r',
                        style='dashed' )

nx.draw_networkx_edges( map_graph,
                        pos,             # Spring                                                                    
                        map_blue_edges,  # List of edges                                                             
                        width=5,
                        alpha=0.5,
                        edge_color='b',
                        style='solid' )

Which will produce the following graph:

Screen Shot 2018-04-29 at 9.49.43 PM

Also useful is shortest_path, which returns all the paths between all nodes, but sorted by vertex traversal path length. So the following code:


paths = nx.shortest_path(map_graph)
print( paths )

Generates the following paths.


{'Issaquah': {'Issaquah': ['Issaquah'], 'Bellevue': ['Issaquah', 'Bellevue'], 'Kirkland': ['Issaquah', 'Bellevue', 'Kirkland'], 'Redmond': ['Issaquah', 'Bellevue', 'Redmond'], 'Seattle': ['Issaquah', 'Bellevue', 'Seattle'], 'Renton': ['Issaquah', 'Bellevue', 'Renton']}, 'Bellevue': {'Bellevue': ['Bellevue'], 'Issaquah': ['Bellevue', 'Issaquah'], 'Kirkland': ['Bellevue', 'Kirkland'], 'Redmond': ['Bellevue', 'Redmond'], 'Seattle': ['Bellevue', 'Seattle'], 'Renton': ['Bellevue', 'Renton']}, 'Kirkland': {'Kirkland': ['Kirkland'], 'Bellevue': ['Kirkland', 'Bellevue'], 'Redmond': ['Kirkland', 'Redmond'], 'Issaquah': ['Kirkland', 'Bellevue', 'Issaquah'], 'Seattle': ['Kirkland', 'Bellevue', 'Seattle'], 'Renton': ['Kirkland', 'Bellevue', 'Renton']}, 'Redmond': {'Redmond': ['Redmond'], 'Bellevue': ['Redmond', 'Bellevue'], 'Kirkland': ['Redmond', 'Kirkland'], 'Issaquah': ['Redmond', 'Bellevue', 'Issaquah'], 'Seattle': ['Redmond', 'Bellevue', 'Seattle'], 'Renton': ['Redmond', 'Bellevue', 'Renton']}, 'Seattle': {'Seattle': ['Seattle'], 'Bellevue': ['Seattle', 'Bellevue'], 'Renton': ['Seattle', 'Renton'], 'Issaquah': ['Seattle', 'Bellevue', 'Issaquah'], 'Kirkland': ['Seattle', 'Bellevue', 'Kirkland'], 'Redmond': ['Seattle', 'Bellevue', 'Redmond']}, 'Renton': {'Renton': ['Renton'], 'Seattle': ['Renton', 'Seattle'], 'Bellevue': ['Renton', 'Bellevue'], 'Issaquah': ['Renton', 'Bellevue', 'Issaquah'], 'Kirkland': ['Renton', 'Bellevue', 'Kirkland'], 'Redmond': ['Renton', 'Bellevue', 'Redmond']}, 'Mercer Island': {'Mercer Island': ['Mercer Island']}}