Snippets

Furhat Robotics WIP: Example flow for a passive state with wake-up words and an active state with dialog

Created by Ludvig Linse last modified
<!-- idle state, waiting for wake-up words -->
<state id="Idle" extends="PassiveDialog">
	<onentry>
		<agent:listen />
		<reentry />
	</onentry>

	<onevent name="sense.user.speak**" cond="event?:sem:wakeup">
		<goto state="VerifyWakeup" p:wakeupEvent="event"/>
	</onevent>
</state>

<!-- state to verify wakeup, if "furhat" is said it directly goes to Attending state -->
<state id="VerifyWakeup" extends="Dialog">
	<param name="wakeupEvent" type="iristk.system.Event"/>

	<onentry>
		<agent:attend target="wakeupEvent:user"/>
		<if cond="asString(wakeupEvent:text).contains('furhat')">
			<exec>
				wakeupEvent.getRecord("sem").remove("wakeup")
			</exec>
			<if cond="asRecord(wakeupEvent:sem).empty()">
				<exec>wakeupEvent = null</exec>
				<agent:say>Hey</agent:say>
			</if>
			<goto state="Attending" p:wakeupEvent="wakeupEvent"/>
		<else/>
			<agent:say>Are you talking to me?</agent:say>
			<agent:listen/>
		</if>
	</onentry>

	<onevent name="sense.user.speak**" cond="event?:sem:yes">
		<agent:say>Cool</agent:say>
		<goto state="Attending" />
	</onevent>

	<onevent name="sense.user.speak**" cond="event?:sem:no or event?:sem:exit">
		<agent:say>Okay, sorry</agent:say>
		<goto state="Idle" />
	</onevent>
</state>

<!-- State when Furhat is actively listening without wake-up word -->
<state id="Attending" extends="PassiveDialog">
	<param name="wakeupEvent" type="iristk.system.Event"/>

	<onentry>
		<if cond="wakeupEvent != null and wakeupEvent?:sem">
			<raise event="sense.user.speak" copy="wakeupEvent"/>
		<else/>
			<agent:listen/>
		</if>
	</onentry>

	<!-- answering hard-coded questions -->
	<onevent name="sense.user.speak" cond="event?:sem:question">

		<var name="question" type="String" value="asString(event:sem:question)"/>

		<!-- Question and answer pairs, in this example hard-coded. The semantics for the questions needs to be added in grammar file -->
		<if cond="question.equals('whatsYourName')">
			<agent:say>My name is Fur hat</agent:say>
			<!-- We should never end up here. If we do, we have added a semantic tag in grammar that we haven't caught -->
			<agent:say>Sorry, I can't answer that.</agent:say>
		</if>
		<agent:listen />
	</onevent>
</state>

<!-- master state used when in a "passive" dialog, i.e waiting for commands -->
<state id="PassiveDialog" extends="Master">
	<onevent name="sense.user.speak**">
		<agent:listen />
	</onevent>

	<onevent name="sense.user.silence">
		<agent:listen />
	</onevent>

	<onevent name="sense.user.leave" cond="system.isAttending(event)">
		<if cond="system.hasUsers()">
			<agent:attendRandom />
		</if>
	</onevent>
</state>

<!-- master state used when in an "active" dialog, i.e expecting answers from users -->
<state id="Dialog" extends="Master">

	<!-- Start smiling when someone starts speaking -->
	<onevent name="sense.user.speech.start" cond="system.isAttending(event) and eq(event:speakers, 1)">
		<agent:gesture name="'smile'" />
	</onevent>

	<!-- Catch speak events that we our grammar can't handle -->
	<onevent name="sense.user.speak" cond="!eq(event:text, 'NO_MATCH')">
		<agent:say>Sorry, I don't understand that</agent:say>
		<agent:listen />
	</onevent>

	<onevent name="sense.user.speak">
		<agent:say>Sorry, what was that?</agent:say>
		<agent:listen />
	</onevent>

	<onevent name="sense.user.silence">
		<agent:say>Sorry, I didn't hear anything</agent:say>
		<agent:listen />
	</onevent>

	<onevent name="sense.user.speak.multi">
		<send event="sense.user.speak" copy="event"/>
	</onevent>

	<onevent name="sense.user.speak.side">
		<send event="sense.user.speak" copy="event"/>
	</onevent>
</state>

<!-- master state used by both passive and active dialog master states -->
<state id="Master">
	<onevent name="sense.user.enter">
		<agent:attend target="event:user" />
	</onevent>

	<onevent name="sense.user.leave" cond="system.isAttending(event)">
		<if cond="system.hasUsers()">
			<agent:attendRandom />
		</if>
	</onevent>
</state>

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.