The number of reachable snake orientations This challenge is not about the game Snake.

Imagine a 2d snake formed by drawing a horizontal line of length n.  At integer points along its body, this snake can rotate its body by 90 degree. If we define the front of the snake to be on the far left to start with, the rotation will move the back part of the snake and the front part will stay put. By doing repeated rotations it can make a lot of different snake body shapes.  

Rules


One part of the snake's body can't overlap another.  
It has to be possible to reach the final orientation without any parts of the snake's body overlapping in between. Two points that touch are counted as overlapping in this problem.
I regard a snake and its reverse as being the same shape.


Task


  Up to rotation, translation and mirror symmetry, what is the total
  number of different snake body shapes that can be made?


Example of a rotation of part of the snakes body. Imagine n=10 and the snake is in its start orientation of a straight line. Now rotate at point 4 90 degrees counter-clockwise. We get the snake from  4 to 10 (the tail of the snake) lying vertically and the snake from 0 to 4 lying horizontally. The snake now has one right angle in its body. 

Here are some examples thanks to Martin Büttner.

We start with the horizontal snake.



Now we rotate from position 4.



We end up after the rotation in this orientation.



Now let us consider this orientation of a different snake.



We can now see an illegal move where there would be an overlap caused during the rotation. 



Score

Your score is the largest n for which your code can solve the problem in less than one minute on my computer.

When a rotation happens it will move one half of the snake with it. We do have to worry about whether any of this part which is rotated might overlap a part of the snake during the rotation.  For simplicity we can assume the snake has width zero.  You can only rotate at a particular point in snake up to 90 degrees clockwise of counter clockwise. For, you can never full fold the snake in two as that would have involved two rotations at the same point in the same direction.

Shapes that can't be made

A simple example of a shape that can't be made is a capital T.   A more sophisticated version is



(Thank you to Harald Hanche-Olsen for this example)

In this example all the adjacent horizontal lines are 1 apart as are the vertical ones. There is therefore no legal move from this position and as the problem is reversible there is therefore no way to get there from the starting position.

Languages and libraries

You can use any language which has a freely available compiler/interpreter/etc. for Linux and any libraries which are also freely available for Linux.

My machine
The timings will be run on my machine. This is a standard ubuntu install on an AMD FX-8350 Eight-Core Processor. This also means I need to be able to run your code. As a consequence, only use easily available free software and please include full instructions how to compile and run your code.
Python 3 - provisional score: n=11 (n=13 with PyPy*)
Since there have been no answers in the first week, here is an example in Python to encourage competition. I've tried to make it reasonably readable so that inefficiencies can be identified easily to give ideas for other answers.
Approach

Start with the straight snake and find all the positions that can be legally reached in one move.
Find all the positions that can be legally reached from those positions, that haven't already been identified.
Repeat until no more can be found, and return the number of positions found altogether.

Code
(now with some doctests and asserts after my incorrect first attempt)
'''
Snake combinations

A snake is represented by a tuple giving the relative orientation at each joint.
A length n snake has n-1 joints.
Each relative orientation is one of the following:

0: Clockwise 90 degrees
1: Straight
2: Anticlockwise 90 degrees

So a straight snake of length 4 has 3 joints all set to 1:

(1, 1, 1)

x increases to the right
y increases upwards

'''


import turtle


def all_coords(state):
    '''Return list of coords starting from (0,0) heading right.'''
    current = (1, 0)
    heading = 0
    coords = [(0,0), (1,0)]
    for item in state:
        heading += item + 3
        heading %= 4
        offset = ((1,0), (0,1), (-1,0), (0,-1))[heading]
        current = tuple(current[i]+offset[i] for i in (0,1))
        coords.append(current)
    return coords
        

def line_segments(coords, pivot):
    '''Return list of line segments joining consecutive coords up to pivot-1.'''
    return [(coords[i], coords[i+1]) for i in range(pivot+1)]

    
def rotation_direction(coords, pivot, coords_in_final_after_pivot):
    '''Return -1 if turning clockwise, 1 if turning anticlockwise.'''
    pivot_coord = coords[pivot + 1]
    initial_coord = coords[pivot + 2]
    final_coord = coords_in_final_after_pivot[0]
    initial_direction = tuple(initial_coord[i] - pivot_coord[i] for i in (0,1))
    final_direction = tuple(final_coord[i] - pivot_coord[i] for i in (0,1))
    return (initial_direction[0] * final_direction[1] -
            initial_direction[1] * final_direction[0]
            )


def intersects(arc, line):
    '''Return True if the arc intersects the line segment.'''
    if line_segment_cuts_circle(arc, line):
        cut_points = points_cutting_circle(arc, line)
        if cut_points and cut_point_is_on_arc(arc, cut_points):
            return True


def line_segment_cuts_circle(arc, line):
    '''Return True if the line endpoints are not both inside or outside.'''
    centre, point, direction = arc
    start, finish = line
    point_distance_squared = distance_squared(centre, point)
    start_distance_squared = distance_squared(centre, start)
    finish_distance_squared = distance_squared(centre, finish)
    start_sign = start_distance_squared - point_distance_squared
    finish_sign = finish_distance_squared - point_distance_squared
    if start_sign * finish_sign &lt;= 0:
        return True


def distance_squared(centre, point):
    '''Return the square of the distance between centre and point.'''
    return sum((point[i] - centre[i]) ** 2 for i in (0,1))
                                
                                
def cut_point_is_on_arc(arc, cut_points):
    '''Return True if any intersection point with circle is on arc.'''
    centre, arc_start, direction = arc
    relative_start = tuple(arc_start[i] - centre[i] for i in (0,1))
    relative_midpoint = ((relative_start[0] - direction*relative_start[1])/2,
                         (relative_start[1] + direction*relative_start[0])/2
                         )
    span_squared = distance_squared(relative_start, relative_midpoint)
    for cut_point in cut_points:
        relative_cut_point = tuple(cut_point[i] - centre[i] for i in (0,1))
        spacing_squared = distance_squared(relative_cut_point,
                                           relative_midpoint
                                           )
        if spacing_squared &lt;= span_squared:
            return True
    

def points_cutting_circle(arc, line):
    '''Return list of points where line segment cuts circle.'''
    points = []
    start, finish = line
    centre, arc_start, direction = arc
    radius_squared = distance_squared(centre, arc_start)
    length_squared = distance_squared(start, finish)
    relative_start = tuple(start[i] - centre[i] for i in (0,1))
    relative_finish = tuple(finish[i] - centre[i] for i in (0,1))
    relative_midpoint = tuple((relative_start[i] +
                               relative_finish[i]
                               )*0.5 for i in (0,1))
    determinant = (relative_start[0]*relative_finish[1] -
                   relative_finish[0]*relative_start[1]
                   )
    determinant_squared = determinant ** 2
    discriminant = radius_squared * length_squared - determinant_squared
    offset = tuple(finish[i] - start[i] for i in (0,1))
    sgn = (1, -1)[offset[1] &lt; 0]
    root_discriminant = discriminant ** 0.5
    one_over_length_squared = 1 / length_squared
    for sign in (-1, 1):
        x = (determinant * offset[1] +
             sign * sgn * offset[0] * root_discriminant
             ) * one_over_length_squared
        y = (-determinant * offset[0] +
             sign * abs(offset[1]) * root_discriminant
             ) * one_over_length_squared
        check = distance_squared(relative_midpoint, (x,y))
        if check &lt;= length_squared * 0.25:
            points.append((centre[0] + x, centre[1] + y))
    return points

    
def potential_neighbours(candidate):
    '''Return list of states one turn away from candidate.'''
    states = []
    for i in range(len(candidate)):
        for orientation in range(3):
            if abs(candidate[i] - orientation) == 1:
                state = list(candidate)
                state[i] = orientation
                states.append(tuple(state))
    return states


def reachable(initial, final):
    '''
    Return True if final state can be reached in one legal move.

    &gt;&gt;&gt; reachable((1,0,0), (0,0,0))
    False

    &gt;&gt;&gt; reachable((0,1,0), (0,0,0))
    False

    &gt;&gt;&gt; reachable((0,0,1), (0,0,0))
    False

    &gt;&gt;&gt; reachable((1,2,2), (2,2,2))
    False

    &gt;&gt;&gt; reachable((2,1,2), (2,2,2))
    False

    &gt;&gt;&gt; reachable((2,2,1), (2,2,2))
    False
    
    &gt;&gt;&gt; reachable((1,2,1,2,1,1,2,2,1), (1,2,1,2,1,1,2,1,1))
    False
    
    '''
    pivot = -1
    for i in range(len(initial)):
        if initial[i] != final[i]:
            pivot = i
            break

    assert pivot &gt; -1, '''
        No pivot between {} and {}'''.format(initial, final)
    assert initial[pivot + 1:] == final[pivot + 1:], '''
        More than one pivot between {} and {}'''.format(initial, final)

    coords_in_initial = all_coords(initial)
    coords_in_final_after_pivot = all_coords(final)[pivot+2:]
    coords_in_initial_after_pivot = coords_in_initial[pivot+2:]
    line_segments_up_to_pivot = line_segments(coords_in_initial, pivot)

    direction = rotation_direction(coords_in_initial,
                                   pivot,
                                   coords_in_final_after_pivot
                                   )
    
    pivot_point = coords_in_initial[pivot + 1]

    for point in coords_in_initial_after_pivot:
        arc = (pivot_point, point, direction)
        if any(intersects(arc, line) for line in line_segments_up_to_pivot):
            return False
    return True
    
    
def display(snake):
    '''Display a line diagram of the snake.

    Accepts a snake as either a tuple:

    (1, 1, 2, 0)

    or a string:

    &quot;1120&quot;

    '''
    snake = tuple(int(s) for s in snake)
    coords = all_coords(snake)

    turtle.clearscreen()
    t = turtle.Turtle()
    t.hideturtle()
    s = t.screen
    s.tracer(0)

    width, height = s.window_width(), s.window_height()
    
    x_min = min(coord[0] for coord in coords)
    x_max = max(coord[0] for coord in coords)
    y_min = min(coord[1] for coord in coords)
    y_max = max(coord[1] for coord in coords)
    unit_length = min(width // (x_max - x_min + 1),
                      height // (y_max - y_min + 1)
                      )

    origin_x = -(x_min + x_max) * unit_length // 2
    origin_y = -(y_min + y_max) * unit_length // 2

    pen_width = max(1, unit_length // 20)
    t.pensize(pen_width)
    dot_size = max(4, pen_width * 3)
    
    t.penup()
    t.setpos(origin_x, origin_y)
    t.pendown()
    
    t.forward(unit_length)
    for joint in snake:
        t.dot(dot_size)
        t.left((joint - 1) * 90)
        t.forward(unit_length)
    s.update()
    

def neighbours(origin, excluded=()):
    '''Return list of states reachable in one step.'''
    states = []
    for candidate in potential_neighbours(origin):
        if candidate not in excluded and reachable(origin, candidate):
            states.append(candidate)
    return states


def mirrored_or_backwards(candidates):
    '''Return set of states that are equivalent to a state in candidates.'''
    states = set()
    for candidate in candidates:
        mirrored = tuple(2 - joint for joint in candidate)
        backwards = candidate[::-1]
        mirrored_backwards = mirrored[::-1]
        states |= set((mirrored, backwards, mirrored_backwards))
    return states

        
def possible_snakes(snake):
    '''
    Return the set of possible arrangements of the given snake.

    &gt;&gt;&gt; possible_snakes((1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1))
    {(1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1)}

    '''
    reached = set()
    candidates = set((snake,))
    
    while candidates:
        candidate = candidates.pop()
        reached.add(candidate)
        new_candidates = neighbours(candidate, reached)
        reached |= mirrored_or_backwards(new_candidates)
        set_of_new_candidates = set(new_candidates)
        reached |= set_of_new_candidates
        candidates |= set_of_new_candidates
        
    excluded = set()
    final_answers = set()
    while reached:
        candidate = reached.pop()
        if candidate not in excluded:
            final_answers.add(candidate)
            excluded |= mirrored_or_backwards([candidate])

    return final_answers


def straight_derived_snakes(length):
    '''Return the set of possible arrangements of a snake of this length.'''
    straight_line = (1,) * max(length-1, 0)
    return possible_snakes(straight_line)

    
if __name__ == '__main__':
    import doctest
    doctest.testmod()
    import sys
    arguments = sys.argv[1:]
    if arguments:
        length = int(arguments[0])
    else:
        length = int(input('Enter the length of the snake:'))
    print(len(straight_derived_snakes(length)))

Results
On my machine the longest snake that can be calculated in under 1 minute is length 11 (or length 13 with PyPy*). This is obviously just a provisional score until we find out what the official score is from Lembik's machine.
For comparison, here are the results for the first few values of n:
 n | reachable orientations
-----------------------------
 0 | 1
 1 | 1
 2 | 2
 3 | 4
 4 | 9
 5 | 22
 6 | 56
 7 | 147
 8 | 388
 9 | 1047
10 | 2806
11 | 7600
12 | 20437
13 | 55313
14 | 148752
15 | 401629
16 | 1078746
17 | MemoryError (on my machine)

Please let me know if any of these turn out to be incorrect.
If you have an example of an arrangement that should not be able to be unfolded, you can use the function neighbours(snake) to find any arrangements reachable in one step, as a test of the code. snake is a tuple of joint directions (0 for clockwise, 1 for straight, 2 for anticlockwise). For example (1,1,1) is a straight snake of length 4 (with 3 joints).
Visualisation
To visualise a snake you have in mind, or any of the snakes returned by neighbours, you can use the function display(snake). This accepts a tuple like the other functions, but since it is not used by the main program and therefore does not need to be fast, it will also accept a string, for your convenience.
display((1,1,2,0)) is equivalent to display(&quot;1120&quot;)
As Lembik mentions in the comments, my results are identical to OEIS A037245 which does not take into account intersections during rotation. This is because for the first few values of n there is no difference - all shapes that do not self-intersect can be reached by folding a straight snake. The correctness of the code can be tested by calling neighbours() with a snake that cannot be unfolded without intersection. Since it has no neighbours it will contribute only to the OEIS sequence, and not to this one. The smallest example I am aware of is this length 31 snake that Lembik mentioned, thanks to David K:
(1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,2,1,1,2,2,1,0,1,0,1,1,1,1)
display('111121211111121112112210101111') gives the following output:


Tip: If you resize the display window and then call display again, the snake will be fitted to the new window size.

I'd love to hear from anyone who has a shorter example with no neighbours. I suspect that the shortest such example will mark the smallest n for which the two sequences differ.

*Note that each increment of n takes very roughly 3 times as long, so increasing from n=11 to n=13 requires almost 10 times the time. This is why PyPy only allows increasing n by 2, even though it runs considerably faster than the standard Python interpreter.