diff --git a/src/orca/Makefile.am b/src/orca/Makefile.am
index 7041dc3b2a67f5ee96bba824f0e45012378fecdb..89d79b896c98b95e3aca53e3db17b8453346c94a 100644
--- a/src/orca/Makefile.am
+++ b/src/orca/Makefile.am
@@ -40,6 +40,7 @@ orca_python_PYTHON = \
 	messages.py \
 	mouse_review.py \
 	notification_messages.py \
+	object_navigator.py	 \
 	object_properties.py \
 	orca.py \
 	orca_gtkbuilder.py \
diff --git a/src/orca/cmdnames.py b/src/orca/cmdnames.py
index 445015800b62ab71c0f40c5d368a3ba3c4099474..d052fe49e608180766765ca8812993a12b10b42f 100644
--- a/src/orca/cmdnames.py
+++ b/src/orca/cmdnames.py
@@ -1079,3 +1079,23 @@ VISITED_LINK_NEXT = _("Go to next visited link")
 
 # Translators: this is for navigating among visited links in a document.
 VISITED_LINK_LIST = _("Display a list of visited links")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+NAVIGATOR_UP = _("Moves the object navigator to the parent of the object with navigator focus.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+NAVIGATOR_DOWN = _("Moves the object navigator to the first child of the object with navigator focus.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+NAVIGATOR_NEXT = _("Moves the object navigator to the next sibling of the object with navigator focus.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+NAVIGATOR_PREVIOUS = _("Moves the object navigator to the previous sibling of the object with navigator focus.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# Users are also able to perform the usual action on an object encountered during navigation, which is usually a click, press, or causing it to grab keyboard focus.
+NAVIGATOR_PERFORM_ACTION = _("Performs the usual action on the object with navigator focus.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This hierarchy can be simplified, and the simplification can be toggled on and off.
+NAVIGATOR_TOGGLE_SIMPLIFIED = _("Toggles whether object navigation should be simplified.")
diff --git a/src/orca/common_keyboardmap.py b/src/orca/common_keyboardmap.py
index 246af2e18c939876f5f46eaf9ad7314660bec431..05ee37206e9a2f17ba5e8f6abcd2c3e82a971827 100644
--- a/src/orca/common_keyboardmap.py
+++ b/src/orca/common_keyboardmap.py
@@ -71,6 +71,18 @@ keymap = (
 
     ("Up", defaultModifierMask, ORCA_SHIFT_MODIFIER_MASK,
     "whereAmISelectionHandler"),
+    ("Up", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorUpHandler"),
+    ("Down", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorDownHandler"),
+    ("Right", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorNextHandler"),
+    ("Left", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorPreviousHandler"),
+    ("Return", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorActionHandler"),
+    ("S", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
+    "navigatorToggleSimplifyHandler"),
 
     #####################################################################
     #                                                                   #
diff --git a/src/orca/messages.py b/src/orca/messages.py
index 5186e76f51d700708e8cb9e70929b934001330f3..c0b191e2d679e394808505abb10cfe7d81c61999 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -1751,6 +1751,32 @@ MOUSE_REVIEW_ENABLED = _("Mouse review enabled.")
 # from getting these objects.
 NAVIGATION_DIALOG_ERROR = _("Error: Could not create list of objects.")
 
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This message is spoken when the current node in the hierarchy has no children.
+NAVIGATOR_NO_CHILDREN = _("No children.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This message is spoken when the current node in the hierarchy has no next sibling.
+NAVIGATOR_NO_NEXT = _("No next.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This message is spoken when the current node in the hierarchy has no parent.
+NAVIGATOR_NO_PARENT = _("No parent.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This message is spoken when the current node in the hierarchy has no previous sibling.
+NAVIGATOR_NO_PREVIOUS = _("No previous.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This hirerarchy can be simplified to aid with navigation.
+# This message is spoken when the simplified view is enabled.
+NAVIGATOR_SIMPLIFIED_ENABLED = _("Simplified navigation enabled.")
+
+# Translators: the object navigator allows users to explore UI objects presented as a hierarchy.
+# This hirerarchy can be simplified to aid with navigation.
+# This message is spoken when the simplified view is disabled.
+NAVIGATOR_SIMPLIFIED_DISABLED = _("Simplified navigation DISABLED.")
+
 # Translators: This message describes a list item in a document. Nesting level
 # is how "deep" the item is (e.g., a level of 2 represents a list item inside a
 # list that's inside another list).
diff --git a/src/orca/object_navigator.py b/src/orca/object_navigator.py
new file mode 100644
index 0000000000000000000000000000000000000000..702cf82aa6b232b0988ce56089e223427ae45471
--- /dev/null
+++ b/src/orca/object_navigator.py
@@ -0,0 +1,149 @@
+# Orca
+#
+# Copyright 2020 The Orca Team
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Object for maintaining the state of the object navigator."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2020 The Orca Team"
+__license__   = "LGPL"
+
+import pyatspi
+
+from . import messages
+from . import orca_state
+
+class ObjectNavigator:
+    def __init__(self):
+        self.navigatorFocus=None
+        self.lastNavigatorFocus=None
+        self.lastLocusOfFocus=None
+        self.simplify=True
+        self.inclusionList = [pyatspi.ROLE_PARAGRAPH]
+        self.exclusionList = [pyatspi.ROLE_SECTION]
+
+    def _isEmpty(self, object):
+        """ Method for determining whether an object should be excluded from simple navigation. """
+        if object.role in self.inclusionList:
+            return False
+        return orca_state.activeScript.utilities.isLayoutOnly(object) or object.getRole() in orca_state.activeScript.utilities.getCellRoles() or object.role in self.exclusionList
+
+    def _children(self, object):
+        """ Returns a list of children for object, taking simple navigation into account if enabled. """
+        if object.childCount==0: # if we have no children, return the empty list
+            return []
+        if not self.simplify: # just return the usual children
+            return list(object)
+        children = list(object) # the normal list of children
+        resultingChildren = [] # the list we're constructing
+        for child in children:
+            if self._isEmpty(child): # add the children of empty objects to our list of children
+                resultingChildren.extend(self._children(child))
+            else:
+                resultingChildren.append(child)
+        return resultingChildren
+
+    def _parent(self, object):
+        """ Returns the parent for object, taking simple navigation into account if enabled. """
+        if not self.simplify: # return the usual parent
+            return object.parent
+        while object.parent is not None and self._isEmpty(object.parent): # move up until we find an object with a suitible parent
+            object = object.parent
+        return object.parent
+
+    def setNavigatorFocus(self, object):
+        """ Method for changing the navigator focus. Placing this in a method allow us to keep track of the previous focus. """
+        self.lastNavigatorFocus=self.navigatorFocus
+        self.navigatorFocus=object
+
+    def update(self):
+        """ Updates the navigator focus to the last keyboard focus, if it is different from before. """
+        if orca_state.locusOfFocus==self.lastLocusOfFocus:
+            return  
+        self.navigatorFocus=orca_state.locusOfFocus
+        self.lastLocusOfFocus=orca_state.locusOfFocus
+
+    def present(self):
+        """ Presents the current navigator focus to the user. """
+        generatorMap={}
+        if self.lastNavigatorFocus:
+            generatorMap['priorObj']=self.lastNavigatorFocus
+        utterances = orca_state.activeScript.speechGenerator.generateSpeech(self.navigatorFocus, **generatorMap)
+        if len(utterances)>0:
+            orca_state.activeScript.presentItemsInSpeech(utterances)
+        else:
+            orca_state.activeScript.speakMessage(self.navigatorFocus.getLocalizedRoleName())
+        orca_state.activeScript.displayBrailleForObject(self.navigatorFocus)
+
+    def up(self):
+        """ Moves the navigator focus to the parent of the current focus. """
+        self.update()   
+        parent = self._parent(self.navigatorFocus)
+        if parent is not None:
+            self.setNavigatorFocus(parent)
+            self.present()
+        else:
+            orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_PARENT)
+
+    def down(self):
+        """ Moves the navigator focus to the first child of the current focus. """
+        self.update()
+        children = self._children(self.navigatorFocus)
+        if len(children)>0:
+            self.setNavigatorFocus(children[0])
+            self.present()
+        else:
+            orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_CHILDREN)
+
+    def next(self):
+        """ Moves the navigator focus to the next sibling of the current focus. """
+        self.update()
+        parent = self._parent(self.navigatorFocus)
+        if parent==None:
+            orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_NEXT)
+            return
+        siblings = self._children(parent)
+        if self.navigatorFocus in siblings:
+            index = siblings.index(self.navigatorFocus)
+            if index<len(siblings)-1:
+                self.setNavigatorFocus(siblings[index+1])
+                self.present()
+            else:
+                orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_NEXT)
+        else:
+            self.setNavigatorFocus(parent)
+
+    def previous(self):
+        """ Moves the navigator focus to the previous sibling of the current focus. """
+        self.update()   
+        parent = self._parent(self.navigatorFocus)
+        if parent==None:
+            orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_PREVIOUS)
+            return
+        siblings = self._children(parent)
+        if self.navigatorFocus in siblings:
+            index = siblings.index(self.navigatorFocus)
+            if index>0:
+                self.setNavigatorFocus(siblings[index-1])
+                self.present()
+            else:
+                orca_state.activeScript.speakMessage(messages.NAVIGATOR_NO_PREVIOUS)
+        else:
+            self.setNavigatorFocus(parent)
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index 4881fa8ef0d250ab7e7716a7fa3e33e83dad264b..d3f45451a90c35c094c82bcd2b57bf02da61285d 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -43,6 +43,7 @@ import orca.guilabels as guilabels
 import orca.input_event as input_event
 import orca.keybindings as keybindings
 import orca.messages as messages
+import orca.object_navigator as object_navigator
 import orca.orca as orca
 import orca.orca_gui_commandlist as commandlist
 import orca.orca_state as orca_state
@@ -91,6 +92,7 @@ class Script(script.Script):
         self.targetCursorCell = None
 
         self.justEnteredFlatReviewMode = False
+        self.navigator = object_navigator.ObjectNavigator()
 
         self.digits = '0123456789'
         self.whitespace = ' \t\n\r\v\f'
@@ -519,6 +521,31 @@ class Script(script.Script):
             input_event.InputEventHandler(
                 Script.presentSizeAndPosition,
                 cmdnames.PRESENT_SIZE_AND_POSITION)
+        self.inputEventHandlers["navigatorUpHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorUp,
+                cmdnames.NAVIGATOR_UP)
+        self.inputEventHandlers["navigatorDownHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorDown,
+                cmdnames.NAVIGATOR_DOWN)
+        self.inputEventHandlers["navigatorNextHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorNext,
+                cmdnames.NAVIGATOR_NEXT)
+        self.inputEventHandlers["navigatorPreviousHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorPrevious,
+                cmdnames.NAVIGATOR_PREVIOUS)
+        self.inputEventHandlers["navigatorActionHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorAction,
+                cmdnames.NAVIGATOR_PERFORM_ACTION)
+        self.inputEventHandlers["navigatorToggleSimplifyHandler"]=\
+            input_event.InputEventHandler(
+                Script.navigatorToggleSimplify,
+                cmdnames.NAVIGATOR_TOGGLE_SIMPLIFIED)
+
 
         self.inputEventHandlers.update(notification_messages.inputEventHandlers)
 
@@ -2616,6 +2643,7 @@ class Script(script.Script):
 
         orca.setLocusOfFocus(event, obj)
 
+
     def onShowingChanged(self, event):
         """Callback for object:state-changed:showing accessibility events."""
 
@@ -4445,3 +4473,47 @@ class Script(script.Script):
         brief = messages.SIZE_AND_POSITION_BRIEF % (width, height, x, y)
         self.presentMessage(full, brief)
         return True
+
+    def navigatorUp(self, inputEvent):
+        """ Moves the object navigator to the parent of the current object. """
+        self.navigator.up()
+        return True 
+
+    def navigatorDown(self, inputEvent):
+        """ Moves the object navigator to the first child of the current object. """
+        self.navigator.down()
+        return True
+
+    def navigatorNext(self, inputEvent):
+        """ Moves the object navigator to the next object. """
+        self.navigator.next()
+        return True
+
+    def navigatorPrevious(self, inputEvent):
+        """ Moves the object navigator to the previous object. """
+        self.navigator.previous()
+        return True
+
+    def navigatorAction(self, inputEvent):
+        """ Performs an action (a click, press or focus) on the object with navigator focus. """
+        obj = self.navigator.navigatorFocus 
+        if not obj:
+            return False
+        if eventsynthesizer.clickActionOn(obj):
+            return True
+        if eventsynthesizer.pressActionOn(obj):
+            return True
+        if eventsynthesizer.grabFocusOn(obj):
+            return True
+        return False
+
+    def navigatorToggleSimplify(self, inputEvent):
+        """ Handles toggling simplified navigation with the object navigator. """
+        self.navigator.simplify = not self.navigator.simplify
+        if self.navigator.simplify:
+            self.speakMessage(messages.NAVIGATOR_SIMPLIFIED_ENABLED)
+            self.displayBrailleMessage(messages.NAVIGATOR_SIMPLIFIED_ENABLED, flashTime=settings.brailleFlashTime)
+        else:
+            self.speakMessage(messages.NAVIGATOR_SIMPLIFIED_DISABLED)
+            self.displayBrailleMessage(messages.NAVIGATOR_SIMPLIFIED_DISABLED, flashTime=settings.brailleFlashTime)
+        return True