├── .github
└── workflows
│ └── luacheck.yml
├── .gitignore
├── .imgs
└── modROS.png
├── .luacheckrc
├── LICENSE
├── README.md
├── modDesc.xml
├── src
├── loader.lua
├── modROS.lua
├── mod_config.lua
├── msgs
│ ├── geometry_msgs_transform_stamped.lua
│ ├── nav_msgs_odometry.lua
│ ├── rosgraph_msgs_clock.lua
│ ├── sensor_msgs_imu.lua
│ ├── sensor_msgs_laser_scan.lua
│ └── tf2_msgs_tf_message.lua
├── ros
│ ├── Publisher.lua
│ └── WriteOnlyFileConnection.lua
├── utils
│ ├── LaserScanner.lua
│ ├── frames.lua
│ ├── json.lua
│ ├── ros.lua
│ ├── shared_memory_segment.lua
│ └── vehicle_util.lua
└── vehicles
│ └── RosVehicle.lua
└── store.dds
/.github/workflows/luacheck.yml:
--------------------------------------------------------------------------------
1 | name: luacheck
2 |
3 | on:
4 | push:
5 | pull_request:
6 | # allow manually starting this workflow
7 | workflow_dispatch:
8 |
9 | jobs:
10 | luacheck:
11 | name: Luacheck
12 | runs-on: ubuntu-20.04
13 |
14 | steps:
15 | - name: Fetch repository
16 | uses: actions/checkout@v2
17 | - name: Run luacheck
18 | uses: nebularg/actions-luacheck@v1
19 | with:
20 | files: src/
21 | annotate: warning
22 | # ignore vehicle_utils.lua only in the CI config (not our main
23 | # luacheckrc). We ignore it until we fix it (bad), but get reminded
24 | # about it needing fixes on every local luacheck run.
25 | args: --exclude-files src/utils//vehicle_util.lua
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore symbolic link to named pipe ROS_messages
2 | ROS_messages
3 |
--------------------------------------------------------------------------------
/.imgs/modROS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tud-cor/FS19_modROS/4356362b6e04060cfee5c103cd249b896ccba8ab/.imgs/modROS.png
--------------------------------------------------------------------------------
/.luacheckrc:
--------------------------------------------------------------------------------
1 |
2 | std = "lua51+fs19_vars+fs19_other+fs19_funcs+modROS+ext_deps"
3 |
4 | -- don't complain about unused self args
5 | self = false
6 |
7 | ignore = {
8 | "631" -- line too long
9 | }
10 |
11 | -- don't complain about files not under our control
12 | exclude_files = {"src/utils/json.lua", "src/utils/shared_memory_segment.lua"}
13 |
14 | stds.modROS = {
15 | globals = {
16 | "ModROS",
17 | "g_modROSModDirectory",
18 | "g_modROSModName",
19 | "geometry_msgs_TransformStamped",
20 | "nav_msgs_Odometry",
21 | "ros",
22 | "rosgraph_msgs_Clock",
23 | "sensor_msgs_Imu",
24 | "sensor_msgs_LaserScan",
25 | "tf2_msgs_TFMessage",
26 | "vehicle_util",
27 | "mod_config",
28 | "frames",
29 | "Publisher",
30 | "WriteOnlyFileConnection",
31 | "LaserScanner",
32 | "RosVehicle",
33 | }
34 | }
35 |
36 | stds.ext_deps = {
37 | globals = {
38 | "json",
39 | "SharedMemorySegment"
40 | }
41 | }
42 |
43 | -- globals based on: https://github.com/scfmod/fs19_lua/blob/master/dump.lua
44 | stds.fs19_vars = {
45 | globals = {
46 | },
47 | read_globals = {
48 | "coroutine",
49 | "deform",
50 | "g_achievementManager",
51 | "g_achievementsScreen",
52 | "g_addCheatCommands",
53 | "g_addTestCommands",
54 | "g_ambientSoundManager",
55 | "g_analogStickHTolerance",
56 | "g_analogStickVTolerance",
57 | "g_animalDialog",
58 | "g_animalFoodManager",
59 | "g_animalManager",
60 | "g_animalNameManager",
61 | "g_animalScreen",
62 | "g_animationManager",
63 | "g_animCache",
64 | "g_aspectScaleX",
65 | "g_aspectScaleY",
66 | "g_asyncManager",
67 | "g_autoSaveManager",
68 | "g_availableLanguageNamesTable",
69 | "g_availableLanguagesTable",
70 | "g_baleTypeManager",
71 | "g_baseHUDFilename",
72 | "g_baseUIFilename",
73 | "g_baseUIPostfix",
74 | "g_brandColorManager",
75 | "g_brandManager",
76 | "g_buildName",
77 | "g_buildTypeParam",
78 | "g_careerScreen",
79 | "g_characterSelectionScreen",
80 | "g_chatDialog",
81 | "g_client",
82 | "g_clientInterpDelay",
83 | "g_clientInterpDelayAdjustDown",
84 | "g_clientInterpDelayAdjustUp",
85 | "g_clientInterpDelayBufferMax",
86 | "g_clientInterpDelayBufferMin",
87 | "g_clientInterpDelayBufferOffset",
88 | "g_clientInterpDelayBufferScale",
89 | "g_clientInterpDelayMax",
90 | "g_clientInterpDelayMin",
91 | "g_colorBg",
92 | "g_colorBgUVs",
93 | "g_colorPickerDialog",
94 | "g_configurationManager",
95 | "g_connectionFailedDialog",
96 | "g_connectionHoseManager",
97 | "g_connectionManager",
98 | "g_connectToMasterServerScreen",
99 | "g_createGameScreen",
100 | "g_creditsScreen",
101 | "g_curNumLoadingBarStep",
102 | "g_currentDt",
103 | "g_currentMission",
104 | "g_currentModDirectory", -- not listed on https://github.com/scfmod/fs19_lua/blob/master/dump.lua
105 | "g_currentModName", -- not listed on https://github.com/scfmod/fs19_lua/blob/master/dump.lua
106 | "g_cutterEffectManager",
107 | "g_debugManager",
108 | "g_dedicatedServerMaxFrameLimit",
109 | "g_dedicatedServerMinFrameLimit",
110 | "g_defaultCamera",
111 | "g_deferredLoadingManager",
112 | "g_densityMapHeightManager",
113 | "g_densityMapRevision",
114 | "g_denyAcceptDialog",
115 | "g_depthOfFieldManager",
116 | "g_difficultyScreen",
117 | "g_directSellDialog",
118 | "g_dlcModNameHasPrefix",
119 | "g_dlcsDirectories",
120 | "g_drawGuiHelper",
121 | "g_effectManager",
122 | "g_farmlandManager",
123 | "g_farmManager",
124 | "g_fieldManager",
125 | "g_fillTypeManager",
126 | "g_flightAndNoHUDKeysEnabled",
127 | "g_forceDefaultPCButtons",
128 | "g_forceNeedsDlcsAndModsReload",
129 | "g_fovYDefault",
130 | "g_fovYMax",
131 | "g_fovYMin",
132 | "g_fruitTypeManager",
133 | "g_gameplayHintManager",
134 | "g_gameRevision",
135 | "g_gameSettings",
136 | "g_gameStateManager",
137 | "g_gameStatsXMLPathgameStats.xml',",
138 | "g_gameVersion",
139 | "g_gameVersionDisplay",
140 | "g_gameVersionDisplayExtra",
141 | "g_gameVersionNotification",
142 | "g_gamingStationManager",
143 | "g_groundTypeManager",
144 | "g_gui",
145 | "g_guiHelperSteps",
146 | "g_hasLicenseError",
147 | "g_helperManager",
148 | "g_helpLineManager",
149 | "g_i18n",
150 | "g_i3DManager",
151 | "g_infoDialog",
152 | "g_inputBinding",
153 | "g_inputDisplayManager",
154 | "g_isAppSuspended",
155 | "g_isConsoleSimulationActive",
156 | "g_isDevelopmentVersion",
157 | "g_isPresentationVersion",
158 | "g_isPresentationVersionAIDeactivated",
159 | "g_isPresentationVersionAllMapsEnabled",
160 | "g_isPresentationVersionDlcEnabled",
161 | "g_isPresentationVersionHideMenuButtons",
162 | "g_isPresentationVersionLogoEnabled",
163 | "g_isPresentationVersionShopEnabled",
164 | "g_isPresentationVersionSpecialStore",
165 | "g_isPresentationVersionSpecialStorePath",
166 | "g_isReloadingDlcs",
167 | "g_isServerStreamingVersion",
168 | "g_isSignedIn",
169 | "g_joinGameScreen",
170 | "g_language",
171 | "g_languageShort",
172 | "g_languageSuffix",
173 | "g_lastCheckDlcPaths",
174 | "g_lastMousePosX",
175 | "g_lastMousePosY",
176 | "g_lastTouchPosX",
177 | "g_lastTouchPosY",
178 | "g_logManager",
179 | "g_mainScreen",
180 | "g_manualGearShift",
181 | "g_mapManager",
182 | "g_mapSelectionScreen",
183 | "g_masterServerConnection",
184 | "g_materialManager",
185 | "g_maxModDescVersion",
186 | "g_maxNumLoadingBarSteps",
187 | "g_maxNumRealVehicleLights",
188 | "g_maxUploadRate",
189 | "g_maxUploadRatePerClient",
190 | "g_menuMusic",
191 | "g_menuMusicIsPlayingStarted",
192 | "g_messageCenter",
193 | "g_messageDialog",
194 | "g_minModDescVersion",
195 | "g_mission00StartPoint",
196 | "g_missionManager",
197 | "g_modEventListeners",
198 | "g_modHubScreen",
199 | "g_modIsLoaded",
200 | "g_modManager",
201 | "g_modNameToDirectory",
202 | "g_modsDirectory",
203 | "g_modSelectionScreen",
204 | "g_mpLoadingScreen",
205 | "g_multiplayerScreen",
206 | "g_networkDebug",
207 | "g_networkDebugPrints",
208 | "g_networkTime",
209 | "g_npcManager",
210 | "g_packetPhysicsNetworkTime",
211 | "g_particleSystemManager",
212 | "g_passwordDialog",
213 | "g_physicsDt",
214 | "g_physicsDtLastValidNonInterpolated",
215 | "g_physicsDtNonInterpolated",
216 | "g_physicsDtUnclamped",
217 | "g_physicsNetworkTime",
218 | "g_physicsTimeLooped",
219 | "g_placeableTypeManager",
220 | "g_placementCollisionRevision",
221 | "g_plattformPrefix",
222 | "g_playerColors",
223 | "g_playerModelManager",
224 | "g_preorderBonusManager",
225 | "g_presentedScreenAspectRatio",
226 | "g_prevNetworkTime",
227 | "g_referenceScreenHeight",
228 | "g_referenceScreenWidth",
229 | "g_registeredConsoleCommands",
230 | "g_safeFrameOffsetX",
231 | "g_safeFrameOffsetY",
232 | "g_savegamePath",
233 | "g_savegameXML",
234 | "g_screenAspectRatio",
235 | "g_screenHeight",
236 | "g_screenshotsDirectory",
237 | "g_screenWidth",
238 | "g_selectMasterServerScreen",
239 | "g_sellItemDialog",
240 | "g_server",
241 | "g_serverDetailScreen",
242 | "g_serverMaxCapacity",
243 | "g_serverMinCapacity",
244 | "g_settingsLanguageGUI",
245 | "g_settingsScreen",
246 | "g_shopConfigScreen",
247 | "g_showDeeplinkingFailedMessage",
248 | "g_showDevelopmentWarnings",
249 | "g_showSafeFrame",
250 | "g_showWatermark",
251 | "g_siloDialog",
252 | "g_sleepManager",
253 | "g_soundManager",
254 | "g_soundMixer",
255 | "g_soundPlayer",
256 | "g_specializationManager",
257 | "g_splitShapesRevision",
258 | "g_splitTypeManager",
259 | "g_sprayTypeManager",
260 | "g_startupScreen",
261 | "g_storeManager",
262 | "g_tensionBeltManager",
263 | "g_terrainDeformationQueue",
264 | "g_terrainLodTextureRevision",
265 | "g_textInputDialog",
266 | "g_time",
267 | "g_tipCollisionRevision",
268 | "g_toolTypeManager",
269 | "g_treePlantManager",
270 | "g_tutorialScreen",
271 | "g_uiDebugEnabled",
272 | "g_uniqueDlcNamePrefix",
273 | "g_updateLoopIndex",
274 | "g_updateNetworkTime",
275 | "g_vehicleColors",
276 | "g_vehicleTypeManager",
277 | "g_weatherTypeManager",
278 | "g_wildlifeSpawnerManager",
279 | "g_woodCuttingMarkerEnabled",
280 | "g_workAreaTypeManager",
281 | "g_yesNoDialog",
282 | "io",
283 | "math",
284 | "modOnCreate",
285 | "ssIcePlane",
286 | "ssSeasonAdmirer",
287 | "ssSnowAdmirer",
288 | "string",
289 | "table",
290 | }
291 | }
292 |
293 | stds.fs19_other = {
294 | globals = {
295 | "VehicleTypeManager",
296 | },
297 | read_globals = {
298 | "_VERSION",
299 | "AbstractAnimalStrategy",
300 | "AbstractFieldMission",
301 | "AbstractManager",
302 | "AbstractMission",
303 | "AccessHandler",
304 | "AchievementManager",
305 | "AchievementMessage",
306 | "AchievementsScreen",
307 | "AIConveyorBelt",
308 | "AIConveyorBeltSetAngleEvent",
309 | "AIDriveStrategy",
310 | "AIDriveStrategyBaler",
311 | "AIDriveStrategyCollision",
312 | "AIDriveStrategyCombine",
313 | "AIDriveStrategyConveyor",
314 | "AIDriveStrategyStraight",
315 | "AIImplement",
316 | "AITurnStrategy",
317 | "AITurnStrategyBulb1",
318 | "AITurnStrategyBulb1Reverse",
319 | "AITurnStrategyBulb2",
320 | "AITurnStrategyBulb2Reverse",
321 | "AITurnStrategyBulb3",
322 | "AITurnStrategyBulb3Reverse",
323 | "AITurnStrategyDefault",
324 | "AITurnStrategyDefaultReverse",
325 | "AITurnStrategyHalfCircle",
326 | "AITurnStrategyHalfCircleReverse",
327 | "AIVehicle",
328 | "AIVehicleIsBlockedEvent",
329 | "AIVehicleSetStartedEvent",
330 | "AIVehicleUtil",
331 | "AmbientSoundManager",
332 | "AmbientSoundUtil",
333 | "Animal",
334 | "AnimalAddEvent",
335 | "AnimalCleanEvent",
336 | "AnimalController",
337 | "AnimalDealerEvent",
338 | "AnimalDialog",
339 | "AnimalFoodManager",
340 | "AnimalHusbandry",
341 | "AnimalHusbandryNoMorePalletSpaceEvent",
342 | "AnimalItem",
343 | "AnimalLoadingTrigger",
344 | "AnimalManager",
345 | "AnimalNameEvent",
346 | "AnimalNameManager",
347 | "AnimalRemoveEvent",
348 | "AnimalRidingEvent",
349 | "AnimalScreen",
350 | "AnimatedMapObject",
351 | "AnimatedObject",
352 | "AnimatedObjectEvent",
353 | "AnimatedVehicle",
354 | "AnimatedVehicleStartEvent",
355 | "AnimatedVehicleStopEvent",
356 | "Animation",
357 | "AnimationCache",
358 | "AnimationElement",
359 | "AnimationManager",
360 | "AnimCurve",
361 | "ArticulatedAxis",
362 | "AsyncManager",
363 | "Attachable",
364 | "AttacherJointControl",
365 | "AttacherJoints",
366 | "AudioGroup",
367 | "AutoSaveManager",
368 | "Bale",
369 | "BaleGrab",
370 | "BaleLoader",
371 | "BaleLoaderStateEvent",
372 | "BaleMission",
373 | "Baler",
374 | "BalerCreateBaleEvent",
375 | "BalerSetBaleTimeEvent",
376 | "BalerSetIsUnloadingBaleEvent",
377 | "BaleType",
378 | "BaleTypeManager",
379 | "BaleWrapper",
380 | "BaleWrapperStateEvent",
381 | "BanStorage",
382 | "Barrier",
383 | "BaseMaterial",
384 | "BaseMission",
385 | "BaseMissionFinishedLoadingEvent",
386 | "BaseMissionReadyEvent",
387 | "Basketball",
388 | "BasketTrigger",
389 | "BeehivePlaceable",
390 | "Bga",
391 | "BgaPlaceable",
392 | "BgaSellStation",
393 | "Binding",
394 | "BitmapElement",
395 | "BoxLayoutElement",
396 | "Brand",
397 | "BrandColorManager",
398 | "BrandManager",
399 | "BreadcrumbsElement",
400 | "BunkerSilo",
401 | "BunkerSiloActivatable",
402 | "BunkerSiloCloseEvent",
403 | "BunkerSiloCompacter",
404 | "BunkerSiloInteractor",
405 | "BunkerSiloOpenEvent",
406 | "BunkerSiloPlaceable",
407 | "Butterfly",
408 | "ButtonElement",
409 | "ButtonOverlay",
410 | "BuyableBale",
411 | "BuyHandToolEvent",
412 | "BuyingStation",
413 | "BuyingStationPlaceable",
414 | "BuyObjectEvent",
415 | "BuyPlaceableEvent",
416 | "BuyVehicleEvent",
417 | "CameraFlightManager",
418 | "CameraPath",
419 | "Can",
420 | "CareerScreen",
421 | "CCTDrivable",
422 | "Chainsaw",
423 | "ChainsawCutEvent",
424 | "ChainsawDelimbEvent",
425 | "ChainsawSoundStateActive",
426 | "ChainsawSoundStateCut",
427 | "ChainsawSoundStateIdle",
428 | "ChainsawSoundStateQuicktap",
429 | "ChainsawSoundStateStart",
430 | "ChainsawSoundStateStop",
431 | "ChainsawStateEvent",
432 | "ChainsawUtil",
433 | "ChangeLoanEvent",
434 | "ChangeVehicleConfigEvent",
435 | "CharacterCreationScreen",
436 | "ChatDialog",
437 | "ChatEvent",
438 | "ChatWindow",
439 | "CheatMoneyEvent",
440 | "CheckedOptionElement",
441 | "ChurchClock",
442 | "ClassIds",
443 | "ClassUtil",
444 | "Client",
445 | "ClientStartMissionEvent",
446 | "CloudUpdater",
447 | "Colorizer",
448 | "ColorPickerDialog",
449 | "Combine",
450 | "CombineStrawEnableEvent",
451 | "ConfigurationManager",
452 | "ConfigurationUtil",
453 | "Connection",
454 | "ConnectionFailedDialog",
455 | "ConnectionHoseManager",
456 | "ConnectionHoses",
457 | "ConnectionHoseType",
458 | "ConnectionManager",
459 | "ConnectionRequestAnswerEvent",
460 | "ConnectionRequestEvent",
461 | "ConnectToMasterServerScreen",
462 | "ContextActionDisplay",
463 | "ContractingStateEvent",
464 | "ControlsController",
465 | "ConveyorBelt",
466 | "ConveyorBeltEffect",
467 | "Cover",
468 | "CrabSteering",
469 | "Crawlers",
470 | "CreateGameScreen",
471 | "CreditsScreen",
472 | "CrowSoundStateBusy",
473 | "CrowSoundStateCalmAir",
474 | "CrowSoundStateCalmGround",
475 | "CrowSoundStateDefault",
476 | "CrowSoundStateTakeOff",
477 | "CrowStateDefault",
478 | "CrowStateFly",
479 | "CrowStateFlyGlide",
480 | "CrowStateIdleAttention",
481 | "CrowStateIdleEat",
482 | "CrowStateIdleWalk",
483 | "CrowStateLand",
484 | "CrowStateTakeOff",
485 | "CrowsWildlife",
486 | "CultivateMission",
487 | "Cultivator",
488 | "Cutter",
489 | "CutterEffect",
490 | "CutterEffectManager",
491 | "CutterEffectType",
492 | "Cylindered",
493 | "CylinderedEasyControlChangeEvent",
494 | "CylinderedFoldable",
495 | "DailySound",
496 | "Dashboard",
497 | "DataGrid",
498 | "DealerFarmStrategie",
499 | "DealerStrategie",
500 | "DealerTrailerStrategie",
501 | "DebugCube",
502 | "DebugGizmo",
503 | "DebugInfoTable",
504 | "DebugManager",
505 | "DebugRendering",
506 | "DebugText",
507 | "DebugUtil",
508 | "DeferredLoadingManager",
509 | "DensityMapFilter",
510 | "DensityMapHeightManager",
511 | "DensityMapHeightModifier",
512 | "DensityMapHeightUtil",
513 | "DensityMapModifier",
514 | "DenyAcceptDialog",
515 | "DepthOfFieldManager",
516 | "DialogElement",
517 | "DifficultyScreen",
518 | "DigitalDisplay",
519 | "DirectSellDialog",
520 | "Dischargeable",
521 | "DisplayActionBinding",
522 | "Dog",
523 | "DogBall",
524 | "DogFeedEvent",
525 | "DogFetchItemEvent",
526 | "DogFollowEvent",
527 | "Doghouse",
528 | "DogPetEvent",
529 | "Drivable",
530 | "DynamicallyLoadedParts",
531 | "DynamicMountAttacher",
532 | "DynamicMountUtil",
533 | "EconomyManager",
534 | "EditFarmDialog",
535 | "Effect",
536 | "EffectManager",
537 | "ElkTrigger",
538 | "Enterable",
539 | "Environment",
540 | "EnvironmentTimeEvent",
541 | "Event",
542 | "EventIds",
543 | "Farm",
544 | "FarmCreateUpdateEvent",
545 | "FarmDestroyEvent",
546 | "FarmhousePlaceable",
547 | "Farmland",
548 | "FarmlandInitialStateEvent",
549 | "FarmlandManager",
550 | "FarmlandStateEvent",
551 | "FarmManager",
552 | "FarmsInitialStateEvent",
553 | "FarmStats",
554 | "FarmTrailerEvent",
555 | "FertilizeMission",
556 | "FertilizingCultivator",
557 | "FertilizingSowingMachine",
558 | "Field",
559 | "FieldCropsQuery",
560 | "FieldCropsUpdaterConstructor",
561 | "FieldInfoDisplay",
562 | "FieldManager",
563 | "FieldUtil",
564 | "FileAccess",
565 | "Files",
566 | "FillActivatable",
567 | "FillLevelListener",
568 | "FillLevelsDisplay",
569 | "FillPlane",
570 | "FillTrigger",
571 | "FillTriggerPlaceable",
572 | "FillTriggerVehicle",
573 | "FillType",
574 | "FillTypeCategory",
575 | "FillTypeManager",
576 | "FillUnit",
577 | "FillUnitUnloadEvent",
578 | "FillVolume",
579 | "FinanceStats",
580 | "FinanceStatsEvent",
581 | "FlowLayoutElement",
582 | "FocusManager",
583 | "FogStateEvent",
584 | "FogUpdater",
585 | "Foldable",
586 | "FoldableSetFoldDirectionEvent",
587 | "FoliageBending",
588 | "FoliageBendingSystem",
589 | "FoliageTransformGroupConstructor",
590 | "FoliageXmlUtil",
591 | "FollowerSound",
592 | "ForageWagon",
593 | "FrameElement",
594 | "FrameReferenceElement",
595 | "FrontloaderAttacher",
596 | "FruitPreparer",
597 | "FruitType",
598 | "FruitTypeCategory",
599 | "FruitTypeConverter",
600 | "FruitTypeManager",
601 | "FSBaseMission",
602 | "FSCareerMissionInfo",
603 | "FSDensityMapModifier",
604 | "FSDensityMapUtil",
605 | "FSMissionInfo",
606 | "FSMUtil",
607 | "FSTutorialMissionInfo",
608 | "GameInfoDisplay",
609 | "GamepadCategories",
610 | "GamepadHelper",
611 | "GamepadSigninScreen",
612 | "GamePausedDisplay",
613 | "GamePauseEvent",
614 | "GameplayHintManager",
615 | "GameSettings",
616 | "GameState",
617 | "GameStateManager",
618 | "GamingStationManager",
619 | "GetAdminAnswerEvent",
620 | "GetAdminEvent",
621 | "GetBansEvent",
622 | "Graph",
623 | "GreatDemandsEvent",
624 | "GreatDemandSpecs",
625 | "GreenhousePlaceable",
626 | "GreenhousePlaceableWaterTankActivatable",
627 | "GreenhouseSetIsWaterTankFillingEvent",
628 | "GroundAdjustedNodes",
629 | "GroundReference",
630 | "GroundTypeManager",
631 | "GS_INPUT_HELP_MODE_AUTO",
632 | "GS_INPUT_HELP_MODE_GAMEPAD",
633 | "GS_INPUT_HELP_MODE_KEYBOARD",
634 | "GS_IS_CONSOLE_VERSION",
635 | "GS_IS_MAC_APP_STORE_VERSION",
636 | "GS_IS_STEAM_VERSION",
637 | "GS_MONEY_DOLLAR",
638 | "GS_MONEY_EURO",
639 | "GS_MONEY_POUND",
640 | "GS_PERFORMANCE_CLASS_PRESETS",
641 | "GS_PLATFORM_TYPE",
642 | "GS_PLATFORM_TYPE_ANDROID",
643 | "GS_PLATFORM_TYPE_IOS",
644 | "GS_PLATFORM_TYPE_PC",
645 | "GS_PLATFORM_TYPE_PS4",
646 | "GS_PLATFORM_TYPE_SWITCH",
647 | "GS_PLATFORM_TYPE_XBOXONE",
648 | "GS_PRIO_HIGH",
649 | "GS_PRIO_LOW",
650 | "GS_PRIO_NORMAL",
651 | "GS_PRIO_VERY_HIGH",
652 | "GS_PRIO_VERY_LOW",
653 | "GS_PRODUCT_ID",
654 | "GS_PROFILE_HIGH",
655 | "GS_PROFILE_LOW",
656 | "GS_PROFILE_MEDIUM",
657 | "GS_PROFILE_VERY_HIGH",
658 | "Gui",
659 | "GuiDataSource",
660 | "GuiElement",
661 | "GuiMixin",
662 | "GuiOverlay",
663 | "GuiProfile",
664 | "GuiSoundPlayer",
665 | "GuiTopDownCamera",
666 | "GuiUtils",
667 | "HandTool",
668 | "HarvestMission",
669 | "HeatingPlantPlaceable",
670 | "HelperManager",
671 | "HelpIcons",
672 | "HelpLineManager",
673 | "HighPressureWasher",
674 | "HighPressureWasherActivatable",
675 | "HighPressureWasherLance",
676 | "Honk",
677 | "HonkEvent",
678 | "HookLiftContainer",
679 | "HookLiftTrailer",
680 | "Horse",
681 | "HotspotTrigger",
682 | "HPWLanceStateEvent",
683 | "HPWPlaceableTurnOnEvent",
684 | "HTMLUtil",
685 | "HUD",
686 | "HUDDisplayElement",
687 | "HUDElement",
688 | "HUDFrameElement",
689 | "HUDPopupMessage",
690 | "HUDTextDisplay",
691 | "HusbandryModuleAnimal",
692 | "HusbandryModuleBase",
693 | "HusbandryModuleFood",
694 | "HusbandryModuleFoodSpillage",
695 | "HusbandryModuleLiquidManure",
696 | "HusbandryModuleManure",
697 | "HusbandryModuleMilk",
698 | "HusbandryModulePallets",
699 | "HusbandryModuleStraw",
700 | "HusbandryModuleWater",
701 | "I18N",
702 | "I3DManager",
703 | "I3DUtil",
704 | "IKChain",
705 | "IKChains",
706 | "IKUtil",
707 | "InAppPurchase",
708 | "IndexChangeSubjectMixin",
709 | "IndexStateElement",
710 | "InfoDialog",
711 | "InGameIcon",
712 | "IngameMap",
713 | "IngameMapElement",
714 | "InGameMenu",
715 | "InGameMenuAnimalsFrame",
716 | "InGameMenuContractsFrame",
717 | "InGameMenuFinancesFrame",
718 | "InGameMenuGameSettingsFrame",
719 | "InGameMenuGeneralSettingsFrame",
720 | "InGameMenuHelpFrame",
721 | "InGameMenuMapFrame",
722 | "InGameMenuMultiplayerFarmsFrame",
723 | "InGameMenuMultiplayerUsersFrame",
724 | "InGameMenuPricesFrame",
725 | "InGameMenuStatisticsFrame",
726 | "InGameMenuTutorialFrame",
727 | "InGameMenuVehiclesFrame",
728 | "Input",
729 | "InputAction",
730 | "InputBinding",
731 | "InputDevice",
732 | "InputDisplayManager",
733 | "InputEvent",
734 | "InputGlyphElement",
735 | "InputHelpDisplay",
736 | "InputHelpElement",
737 | "InsideBuildingTrigger",
738 | "InterpolationTime",
739 | "InterpolatorAngle",
740 | "InterpolatorPosition",
741 | "InterpolatorQuaternion",
742 | "InterpolatorValue",
743 | "JigglingParts",
744 | "JoinGameScreen",
745 | "JointConstructor",
746 | "JumpEvent",
747 | "KeyboardHelper",
748 | "KickBanEvent",
749 | "KickBanNotificationEvent",
750 | "Landscaping",
751 | "LandscapingScreen",
752 | "LandscapingScreenController",
753 | "LandscapingSculptEvent",
754 | "Leveler",
755 | "LevelerEffect",
756 | "Lighting",
757 | "Lights",
758 | "LightWildlife",
759 | "LightWildlifeAnimal",
760 | "LightWildlifeStateDefault",
761 | "ListElement",
762 | "ListItemElement",
763 | "ListUtil",
764 | "LivestockTrailer",
765 | "LoadingStation",
766 | "LoadTrigger",
767 | "LoadTriggerSetIsLoadingEvent",
768 | "LoanTrigger",
769 | "Locomotive",
770 | "LogGrab",
771 | "LogManager",
772 | "MainScreen",
773 | "ManureBarrel",
774 | "MapDataGrid",
775 | "MapHotspot",
776 | "MapManager",
777 | "MapOverlayGenerator",
778 | "MapPerformanceTestUtil",
779 | "MapSelectionScreen",
780 | "MasterServerConnection",
781 | "MaterialManager",
782 | "MaterialType",
783 | "MaterialUtil",
784 | "MathUtil",
785 | "MeshEvent",
786 | "MessageCenter",
787 | "MessageDialog",
788 | "MessageIds",
789 | "MessageType",
790 | "Mission00",
791 | "MissionCancelEvent",
792 | "MissionCollaborators",
793 | "MissionDismissEvent",
794 | "MissionDynamicInfoEvent",
795 | "MissionFinishedEvent",
796 | "MissionInfo",
797 | "MissionManager",
798 | "MissionPhysicsObject",
799 | "MissionStartedEvent",
800 | "MissionStartEvent",
801 | "MixerWagon",
802 | "MixerWagonBaleNotAcceptedEvent",
803 | "MixerWagonHUDExtension",
804 | "ModCategoryInfo",
805 | "ModHubCategoriesFrame",
806 | "ModHubController",
807 | "ModHubDetailsFrame",
808 | "ModHubItemsFrame",
809 | "ModHubLoadingFrame",
810 | "ModHubScreen",
811 | "ModInfo",
812 | "ModManager",
813 | "ModSelectionScreen",
814 | "MoneyChangeEvent",
815 | "MoneyType",
816 | "MorphPositionEffect",
817 | "Motorized",
818 | "Mountable",
819 | "MountableObject",
820 | "MouseHelper",
821 | "Mower",
822 | "MowerToggleWindrowDropEvent",
823 | "MPLoadingScreen",
824 | "MultiplayerAvailability",
825 | "MultiplayerScreen",
826 | "MultiTextOptionElement",
827 | "MultiValueTween",
828 | "NATType",
829 | "Network",
830 | "NetworkNode",
831 | "NetworkUtil",
832 | "NightGlower",
833 | "NightIllumination",
834 | "Nightlight",
835 | "Nightlight2",
836 | "NightlightFlicker",
837 | "NPCManager",
838 | "Object",
839 | "ObjectChangeUtil",
840 | "ObjectFarmChangeEvent",
841 | "ObjectIds",
842 | "ObjectSpawner",
843 | "OilPump",
844 | "OnCreateLoadedObjectEvent",
845 | "Overlay",
846 | "PagingElement",
847 | "PalletSellTrigger",
848 | "ParticleEffect",
849 | "ParticleSystemManager",
850 | "ParticleType",
851 | "ParticleUtil",
852 | "PedestrianSystem",
853 | "PhysicsObject",
854 | "Pickup",
855 | "PickupSetStateEvent",
856 | "Pipe",
857 | "PipeEffect",
858 | "Placeable",
859 | "PlaceableTypeManager",
860 | "Placeholders",
861 | "PlacementScreen",
862 | "PlacementScreenController",
863 | "PlacementUtil",
864 | "PlantLimitToFieldEvent",
865 | "PlatformPrivilegeUtil",
866 | "Player",
867 | "PlayerModelManager",
868 | "PlayerPermissionsEvent",
869 | "PlayerPickUpObjectEvent",
870 | "PlayerSetFarmAnswerEvent",
871 | "PlayerSetFarmEvent",
872 | "PlayerSetHandToolEvent",
873 | "PlayerStateActivateObject",
874 | "PlayerStateAnimalFeed",
875 | "PlayerStateAnimalInteract",
876 | "PlayerStateAnimalPet",
877 | "PlayerStateAnimalRide",
878 | "PlayerStateBase",
879 | "PlayerStateCrouch",
880 | "PlayerStateCycleHandtool",
881 | "PlayerStateDrop",
882 | "PlayerStateFall",
883 | "PlayerStateIdle",
884 | "PlayerStateJump",
885 | "PlayerStateMachine",
886 | "PlayerStatePickup",
887 | "PlayerStateRun",
888 | "PlayerStateSwim",
889 | "PlayerStateThrow",
890 | "PlayerStateUseLight",
891 | "PlayerStateWalk",
892 | "PlayerStyle",
893 | "PlayerSwitchedFarmEvent",
894 | "PlayerTeleportEvent",
895 | "PlayerThrowObjectEvent",
896 | "PlayerToggleLightEvent",
897 | "PlaySampleMixin",
898 | "Plow",
899 | "PlowLimitToFieldEvent",
900 | "PlowMission",
901 | "PlowRotationEvent",
902 | "PolygonChain",
903 | "PowerConsumer",
904 | "PowerTakeOffs",
905 | "PreorderBonusManager",
906 | "PresenceModes",
907 | "PricingDynamics",
908 | "RailroadCrossing",
909 | "RailroadVehicle",
910 | "RainDropFactorTrigger",
911 | "RandomlyMovingParts",
912 | "RandomSound",
913 | "RaycastUtil",
914 | "ReceivingHopper",
915 | "ReceivingHopperSetCreateBoxesEvent",
916 | "RemovePlayerFromFarmEvent",
917 | "RenderElement",
918 | "RenderText",
919 | "RequestMoneyChangeEvent",
920 | "ResetVehicleEvent",
921 | "RestartManager",
922 | "Reverb",
923 | "ReverseDriving",
924 | "ReverseDrivingSetStateEvent",
925 | "Rideable",
926 | "RideableAnimal",
927 | "RidgeMarker",
928 | "RidgeMarkerSetStateEvent",
929 | "Roller",
930 | "Ropes",
931 | "RotationAnimation",
932 | "Rotator",
933 | "RoundStatusBar",
934 | "SaveEvent",
935 | "Savegame",
936 | "SavegameController",
937 | "SaveGameResolvePolicy",
938 | "SavegameSettingsEvent",
939 | "SCFDebugTesting",
940 | "ScreenElement",
941 | "ScrollingAnimation",
942 | "SelectMasterServerScreen",
943 | "SellHandToolEvent",
944 | "SellingStation",
945 | "SellingStationPlaceable",
946 | "SellItemDialog",
947 | "SellPlaceableEvent",
948 | "SellVehicleEvent",
949 | "SemiTrailerFront",
950 | "SendLocomotiveToSplinePositionEvent",
951 | "Server",
952 | "ServerDetailScreen",
953 | "ServerSettingsDialog",
954 | "SetCoverStateEvent",
955 | "SetCrabSteeringEvent",
956 | "SetCruiseControlSpeedEvent",
957 | "SetCruiseControlStateEvent",
958 | "SetDensityMapEvent",
959 | "SetDischargeStateEvent",
960 | "SetFillUnitIsFillingEvent",
961 | "SetMotorTurnedOnEvent",
962 | "SetPipeStateEvent",
963 | "SetSeedIndexEvent",
964 | "SetSplitShapesEvent",
965 | "SettingsAdvancedFrame",
966 | "SettingsConsoleFrame",
967 | "SettingsControlsFrame",
968 | "SettingsDeviceFrame",
969 | "SettingsDisplayFrame",
970 | "SettingsGeneralFrame",
971 | "SettingsModel",
972 | "SettingsScreen",
973 | "SetTurnedOnEvent",
974 | "SetWorkModeEvent",
975 | "Shader",
976 | "ShaderPlaneEffect",
977 | "ShakeAnimation",
978 | "Ship",
979 | "ShopCategoriesFrame",
980 | "ShopConfigScreen",
981 | "ShopController",
982 | "ShopDisplayItem",
983 | "ShopItemsFrame",
984 | "ShopLandscapingFrame",
985 | "ShopMenu",
986 | "ShopTrigger",
987 | "Shovel",
988 | "ShutdownEvent",
989 | "SideNotification",
990 | "SiloDialog",
991 | "SiloExtensionPlaceable",
992 | "SiloPlaceable",
993 | "SimParticleSystem",
994 | "SimpleState",
995 | "SimpleStateMachine",
996 | "SleepDialog",
997 | "SleepManager",
998 | "SleepRequestEvent",
999 | "SleepResponseEvent",
1000 | "SlideDoorTrigger",
1001 | "SliderElement",
1002 | "SlopeCompensation",
1003 | "SlurrySideToSideEffect",
1004 | "SolarCollectorPlaceable",
1005 | "SoundManager",
1006 | "SoundMixer",
1007 | "SoundModifierType",
1008 | "SoundNode",
1009 | "SoundPlayer",
1010 | "SowingMachine",
1011 | "SowMission",
1012 | "SpeakerDisplay",
1013 | "SpecializationManager",
1014 | "SpecializationUtil",
1015 | "SpeedMeterDisplay",
1016 | "SpeedRotatingParts",
1017 | "SplineUtil",
1018 | "SplineVehicle",
1019 | "SplitTypeManager",
1020 | "Sprayer",
1021 | "SprayMission",
1022 | "SprayType",
1023 | "SprayTypeManager",
1024 | "StableListElement",
1025 | "StartMissionInfo",
1026 | "StartSleepStateEvent",
1027 | "StartupScreen",
1028 | "StatusBar",
1029 | "StopSleepStateEvent",
1030 | "Storage",
1031 | "Store",
1032 | "StoreItemUtil",
1033 | "StoreManager",
1034 | "StrawBlower",
1035 | "StringUtil",
1036 | "StumpCutter",
1037 | "SunAdmirer",
1038 | "Suspensions",
1039 | "TabbedMenu",
1040 | "TabbedMenuFrameElement",
1041 | "TabbedMenuWithDetails",
1042 | "TableElement",
1043 | "TableHeaderElement",
1044 | "Tedder",
1045 | "TemperatureUpdater",
1046 | "TensionBeltGeometryConstructor",
1047 | "TensionBeltManager",
1048 | "TensionBeltObject",
1049 | "TensionBelts",
1050 | "TensionBeltsActivatable",
1051 | "TensionBeltsEvent",
1052 | "TensionBeltsRefreshEvent",
1053 | "TerrainDeformation",
1054 | "TerrainDeformationQueue",
1055 | "TerrainDetailDistanceConstructor",
1056 | "TerrainLoadFlags",
1057 | "TextElement",
1058 | "TextInputDialog",
1059 | "TextInputElement",
1060 | "TextureArrayConstructor",
1061 | "TimedVisibility",
1062 | "TimerElement",
1063 | "TipEffect",
1064 | "TipOccluder",
1065 | "TireTrackSystem",
1066 | "ToggleButtonElement",
1067 | "ToolType",
1068 | "ToolTypeManager",
1069 | "TopNotification",
1070 | "TourIcons",
1071 | "TrafficSystem",
1072 | "Trailer",
1073 | "TrailerFarmStrategie",
1074 | "TrailerToggleTipSideEvent",
1075 | "TrainPlaceable",
1076 | "TransferMoneyDialog",
1077 | "TransferMoneyEvent",
1078 | "TransportMission",
1079 | "TransportMissionTrigger",
1080 | "TrashBag",
1081 | "TreeGrowEvent",
1082 | "TreePlaceable",
1083 | "TreePlanter",
1084 | "TreePlanterActivatable",
1085 | "TreePlanterLoadPalletEvent",
1086 | "TreePlantEvent",
1087 | "TreePlantManager",
1088 | "TreeSaw",
1089 | "TurnOnVehicle",
1090 | "Tutorial",
1091 | "TutorialScreen",
1092 | "Tween",
1093 | "TweenSequence",
1094 | "UnBanDialog",
1095 | "UnbanEvent",
1096 | "UnloadFeedingTrough",
1097 | "UnloadingStation",
1098 | "UnloadTrigger",
1099 | "UpdateSplitShapesEvent",
1100 | "UploadState",
1101 | "Upnp",
1102 | "User",
1103 | "UserDataEvent",
1104 | "UserEvent",
1105 | "UserManager",
1106 | "Utils",
1107 | "ValueBuffer",
1108 | "Vehicle",
1109 | "VehicleAttachEvent",
1110 | "VehicleBrokenEvent",
1111 | "VehicleBundleAttachEvent",
1112 | "VehicleCamera",
1113 | "VehicleCharacter",
1114 | "VehicleDebug",
1115 | "VehicleDetachEvent",
1116 | "VehicleEnterRequestEvent",
1117 | "VehicleEnterResponseEvent",
1118 | "VehicleHUDExtension",
1119 | "VehicleHudUtils",
1120 | "VehicleLeaveEvent",
1121 | "VehicleLowerImplementEvent",
1122 | "VehicleMotor",
1123 | "VehiclePlaceable",
1124 | "VehicleRemoveEvent",
1125 | "VehicleSchemaDisplay",
1126 | "VehicleSchemaOverlayData",
1127 | "VehicleSellingPoint",
1128 | "VehicleSetBeaconLightEvent",
1129 | "VehicleSetLightEvent",
1130 | "VehicleSetTurnLightEvent",
1131 | "VehicleShopBase",
1132 | "VendingMachine",
1133 | "VideoElement",
1134 | "VisualTrailer",
1135 | "VoteDialog",
1136 | "Washable",
1137 | "WaterLog",
1138 | "Watermill",
1139 | "WaterTower",
1140 | "WaterTrailer",
1141 | "WaterTrailerActivatable",
1142 | "WaterTrailerSetIsFillingEvent",
1143 | "Wearable",
1144 | "WearableRepairEvent",
1145 | "Weather",
1146 | "WeatherAddObjectEvent",
1147 | "WeatherFrontUpdater",
1148 | "WeatherInstance",
1149 | "WeatherObject",
1150 | "WeatherObjectRain",
1151 | "WeatherType",
1152 | "WeatherTypeManager",
1153 | "Weeder",
1154 | "WeedMission",
1155 | "WeighStation",
1156 | "Wheels",
1157 | "WheelsUtil",
1158 | "WildlifeSpawner",
1159 | "Windmill",
1160 | "WindObject",
1161 | "WindObjectChangedEvent",
1162 | "Windrower",
1163 | "WindrowerEffect",
1164 | "WindTurbinePlaceable",
1165 | "WindUpdater",
1166 | "Wipers",
1167 | "WoodCrusher",
1168 | "WoodCrusherPlaceable",
1169 | "WoodHarvester",
1170 | "WoodHarvesterCutTreeEvent",
1171 | "WoodHarvesterOnCutTreeEvent",
1172 | "WoodHarvesterOnDelimbTreeEvent",
1173 | "WoodSellEvent",
1174 | "WoodSellStationPlaceable",
1175 | "WorkArea",
1176 | "WorkAreaType",
1177 | "WorkAreaTypeManager",
1178 | "WorkMode",
1179 | "WorkParticles",
1180 | "Workshop",
1181 | "XMLUtil",
1182 | "YesNoDialog",
1183 | }
1184 | }
1185 |
1186 | stds.fs19_funcs = {
1187 | read_globals = {
1188 | "acceptedGameCreate",
1189 | "acceptedGameInvite",
1190 | "acceptedGameInvitePerformConnect",
1191 | "addConsoleCommand",
1192 | "addContactReport",
1193 | "addDensityMapHeightAtWorldLine",
1194 | "addDensityMapHeightAtWorldPos",
1195 | "addDensityMapHeightOcclusionArea",
1196 | "addDensityMapSyncerConnection",
1197 | "addDensityMapSyncerDensityMap",
1198 | "addDifferential",
1199 | "addFeedingPlace",
1200 | "addForce",
1201 | "addHusbandryAnimal",
1202 | "addImpulse",
1203 | "addJointBreakReport",
1204 | "addMilkingPlace",
1205 | "addModEventListener",
1206 | "addNotificationFilter",
1207 | "addParticleSystemSimulationTime",
1208 | "addReplacedCustomShader",
1209 | "addSplitShapeConnection",
1210 | "addSplitShapesShaderParameterOverwrite",
1211 | "addTerrainDeformationArea",
1212 | "addTerrainDeformationCircle",
1213 | "addTerrainUpdateConnection",
1214 | "addTimer",
1215 | "addToPhysics",
1216 | "addTorque",
1217 | "addTorqueImpulse",
1218 | "addTrackPoint",
1219 | "addTrafficSystemPlayer",
1220 | "addTrigger",
1221 | "addVehicleLink",
1222 | "addWakeUpReport",
1223 | "aimCamera",
1224 | "appIsSuspended",
1225 | "applyTerrainDeformation",
1226 | "areAchievementsAvailable",
1227 | "areStatsAvailable",
1228 | "asciiToUtf8",
1229 | "assert",
1230 | "assignAnimTrackClip",
1231 | "autoStartLocalSavegame",
1232 | "base64Decode",
1233 | "base64Encode",
1234 | "beginInputFuzzing",
1235 | "bitAND",
1236 | "bitHighestSet",
1237 | "bitNOT",
1238 | "bitOR",
1239 | "bitShiftLeft",
1240 | "bitShiftRight",
1241 | "bitXOR",
1242 | "buildNavMesh",
1243 | "buildNavPath",
1244 | "calcDistanceFrom",
1245 | "calcDistanceSquaredFrom",
1246 | "calculateFovY",
1247 | "cancelAllStreamedI3DFiles",
1248 | "cancelTerrainDeformation",
1249 | "catmullRomInterpolator1",
1250 | "catmullRomInterpolator3",
1251 | "centerHeadTracking",
1252 | "checkForNewDlcs",
1253 | "Class",
1254 | "cleanUpRenderingResources",
1255 | "clearAnimTrackClip",
1256 | "clearTerrainDeformationAreas",
1257 | "clone",
1258 | "cloneAnimCharacterSet",
1259 | "closeIntervalTimer",
1260 | "collectgarbage",
1261 | "companionDebugDraw",
1262 | "computeWheelShapeTireForces",
1263 | "conditionalAnimationDebugDraw",
1264 | "conditionalAnimationRegisterParameter",
1265 | "conditionalAnimationZeroiseTrackTimes",
1266 | "connectToServer",
1267 | "consoleCommandChangeLanguage",
1268 | "consoleCommandCleanI3DCache",
1269 | "consoleCommandDrawGuiHelper",
1270 | "consoleCommandDrawRawInput",
1271 | "consoleCommandFuzzInput",
1272 | "consoleCommandReloadCurrentGui",
1273 | "consoleCommandSetDebugRenderingMode",
1274 | "consoleCommandSetHighQuality",
1275 | "consoleCommandShowSafeFrame",
1276 | "consoleCommandSuspendApp",
1277 | "consoleCommandToggleUiDebug",
1278 | "consoleSetPowerConsumer",
1279 | "consoleSetWiperState",
1280 | "controlVehicle",
1281 | "copyFile",
1282 | "createAnimalCompanionManager",
1283 | "createAnimalHusbandry",
1284 | "createAudioSource",
1285 | "createBitVectorMap",
1286 | "createCamera",
1287 | "createCCT",
1288 | "createConditionalAnimation",
1289 | "createDensityMapHeightUpdater",
1290 | "createDensityMapSyncer",
1291 | "createDensityMapVisualizationOverlay",
1292 | "createFile",
1293 | "createFillPlaneShape",
1294 | "createFolder",
1295 | "createFoliageBendingRectangle",
1296 | "createFoliageBendingSystem",
1297 | "createImageOverlay",
1298 | "createImageOverlayWithTexture",
1299 | "createLightSource",
1300 | "createLowResCollisionHandler",
1301 | "createNavMesh",
1302 | "createNavPath",
1303 | "createPedestrianSystem",
1304 | "createRenderOverlay",
1305 | "createReverbEffect",
1306 | "createSample",
1307 | "createSoundPlayer",
1308 | "createStream",
1309 | "createStreamedSample",
1310 | "createTerrainDeformation",
1311 | "createTerrainDetailUpdater",
1312 | "createTerrainLayerTexture",
1313 | "createTrack",
1314 | "createTrafficSystem",
1315 | "createTransformGroup",
1316 | "createTyreTrackSystem",
1317 | "createVideoOverlay",
1318 | "createWebImageOverlay",
1319 | "createWheelShape",
1320 | "createXMLFile",
1321 | "cutTrack",
1322 | "delete",
1323 | "deleteFile",
1324 | "deleteFolder",
1325 | "destroyFoliageBendingObject",
1326 | "destroyLowResCollisionHandler",
1327 | "destroyTrack",
1328 | "disableAnimTrack",
1329 | "doExit",
1330 | "dofile",
1331 | "draw",
1332 | "drawDebugArrow",
1333 | "drawDebugLine",
1334 | "drawDebugPoint",
1335 | "drawDebugTriangle",
1336 | "enableAnimTrack",
1337 | "enableDevelopmentControls",
1338 | "enableTerrainDeformationMode",
1339 | "enableTerrainDeformationPaintingMode",
1340 | "enableTerrainDeformationSmoothingMode",
1341 | "endFrameRepeatMode",
1342 | "entityExists",
1343 | "eraseParallelogram",
1344 | "error",
1345 | "executeSettingsChange",
1346 | "exportScenegraphToGraphviz",
1347 | "exportScenegraphToGraphvizRec",
1348 | "extraUpdatePhysics",
1349 | "fileExists",
1350 | "fileWrite",
1351 | "fillPlaneAdd",
1352 | "filterText",
1353 | "findAndRemoveSplitShapeAttachments",
1354 | "findPolyline",
1355 | "findSplitShape",
1356 | "finishedUserProfileSync",
1357 | "finishWriteSplitShapesServerEvents",
1358 | "flushPhysicsCaches",
1359 | "flushWebCache",
1360 | "forceEndFrameRepeatMode",
1361 | "gcinfo",
1362 | "generateDensityMapVisualizationOverlay",
1363 | "get4kAvailable",
1364 | "getAchievement",
1365 | "getAdaptiveVsync",
1366 | "getAngularDamping",
1367 | "getAngularVelocity",
1368 | "getAnimalCompanionNeedNetworkUpdate",
1369 | "getAnimalFromCollisionNode",
1370 | "getAnimalPosition",
1371 | "getAnimalRotation",
1372 | "getAnimalShaderParameter",
1373 | "getAnimCharacterSet",
1374 | "getAnimClipDuration",
1375 | "getAnimClipIndex",
1376 | "getAnimNumOfClips",
1377 | "getAnimTrackAssignedClip",
1378 | "getAnimTrackBlendWeight",
1379 | "getAnimTrackTime",
1380 | "getAppBasePath",
1381 | "getAtmosphereCornettAsymetryFactor",
1382 | "getAtmosphereMieScale",
1383 | "getAudioSourceAutoPlay",
1384 | "getAudioSourceInnerRange",
1385 | "getAudioSourceRange",
1386 | "getAudioSourceSample",
1387 | "getAudioSourceTickInaudible",
1388 | "getAutoPerformanceClass",
1389 | "getBitVectorMapNumChannels",
1390 | "getBitVectorMapParallelogram",
1391 | "getBitVectorMapPoint",
1392 | "getBitVectorMapSize",
1393 | "getBloomMagnitude",
1394 | "getBloomMaskThreshold",
1395 | "getBloomQuality",
1396 | "getBrightness",
1397 | "getCamera",
1398 | "getCanRenderUnicode",
1399 | "getCCTCollisionFlags",
1400 | "getCenterOfMass",
1401 | "getChild",
1402 | "getChildAt",
1403 | "getChildIndex",
1404 | "getClipDistance",
1405 | "getClipDistancesWithLOD",
1406 | "getCloudQuality",
1407 | "getCollisionMask",
1408 | "getCompanionClosestDistance",
1409 | "getConditionalAnimationBoolValue",
1410 | "getConditionalAnimationFloatValue",
1411 | "getCorrectTextSize",
1412 | "getCropsGrowthNextState",
1413 | "getCropsGrowthStateTime",
1414 | "getCullOverride",
1415 | "getCurrentMasterVolume",
1416 | "getDate",
1417 | "getDateAt",
1418 | "getDateDiffSeconds",
1419 | "getDebugRenderingMode",
1420 | "getDensity",
1421 | "getDensityAtWorldPos",
1422 | "getDensityHeightAtWorldPos",
1423 | "getDensityMapCollisionHeightAtWorldPos",
1424 | "getDensityMapFilename",
1425 | "getDensityMapHeightFirstChannel",
1426 | "getDensityMapHeightNumChannels",
1427 | "getDensityMapHeightTypeAtWorldLine",
1428 | "getDensityMapHeightTypeAtWorldPos",
1429 | "getDensityMapMaxHeight",
1430 | "getDensityMapSize",
1431 | "getDensityNormalAtWorldPos",
1432 | "getDensityRegion",
1433 | "getDensityRegionWorld",
1434 | "getDiscretePerformanceSetting",
1435 | "getDlcPath",
1436 | "getDoFblendWeights",
1437 | "getDoFparams",
1438 | "getEffectiveClipDistancesWithLOD",
1439 | "getEffectiveVisibility",
1440 | "getEmitCountScale",
1441 | "getEmitStartTime",
1442 | "getEmitStopTime",
1443 | "getEmitterShape",
1444 | "getEmitterSurfaceSize",
1445 | "getEngineRevision",
1446 | "getExposureKeyValue",
1447 | "getExposureRange",
1448 | "getExposureTau",
1449 | "getFarClip",
1450 | "getfenv",
1451 | "getFileIdHasSplitShapes",
1452 | "getFileMD5",
1453 | "getFiles",
1454 | "getFillPlaneHeightAtLocalPos",
1455 | "getFilterAnisotropy",
1456 | "getFilterTrilinear",
1457 | "getFogPlaneHeight",
1458 | "getFogPlaneMieScale",
1459 | "getFoliageViewDistance",
1460 | "getFoliageViewDistanceCoeff",
1461 | "getFovY",
1462 | "getFullscreen",
1463 | "getGamepadAxisLabel",
1464 | "getGamepadAxisPhysicalName",
1465 | "getGamepadButtonLabel",
1466 | "getGamepadButtonPhysicalName",
1467 | "getGamepadCategory",
1468 | "getGamepadDefaultDeadzone",
1469 | "getGamepadEnabled",
1470 | "getGamepadId",
1471 | "getGamepadMappedUnknownAxis",
1472 | "getGamepadMappedUnknownButton",
1473 | "getGamepadName",
1474 | "getGamepadProductId",
1475 | "getGamepadVendorId",
1476 | "getGamepadVersionId",
1477 | "getGamepadVibrationEnabled",
1478 | "getGameRevisionExtraText",
1479 | "getGameTerritory",
1480 | "getGeometry",
1481 | "getGPUDriverVersion",
1482 | "getGPUName",
1483 | "getGPUVendor",
1484 | "getGravityDirection",
1485 | "getHasClassId",
1486 | "getHasGamepadAxis",
1487 | "getHasGamepadButton",
1488 | "getHasShaderParameter",
1489 | "getHasShadowFocusBox",
1490 | "getHasTerrainNormalMapping",
1491 | "getHaveAchievementsChanged",
1492 | "getHdrAvailable",
1493 | "getHeadTrackingRotation",
1494 | "getHeadTrackingTranslation",
1495 | "getHeadTrackingType",
1496 | "getHmdYaw",
1497 | "getInputAxis",
1498 | "getInputButton",
1499 | "getIsBadUserReputation",
1500 | "getIsCompound",
1501 | "getIsCompoundChild",
1502 | "getIsDensityMapVisualizationOverlayReady",
1503 | "getIsGamepadMappingReliable",
1504 | "getIsInCameraFrustum",
1505 | "getIsLanguageEnabled",
1506 | "getIsOrthographic",
1507 | "getIsPhysicsUpdateIndexSimulated",
1508 | "getIsSleeping",
1509 | "getIsSoundPlayerChannelStreamed",
1510 | "getIsSplitShapeSplit",
1511 | "getIsValidModDir",
1512 | "getKeyName",
1513 | "getLanguage",
1514 | "getLanguageCode",
1515 | "getLanguageName",
1516 | "getLevenshteinDistance",
1517 | "getLightColor",
1518 | "getLightRange",
1519 | "getLightScatteringDirection",
1520 | "getLinearDamping",
1521 | "getLinearVelocity",
1522 | "getLoadNamedInterpolatorCurve",
1523 | "getLocalLinearVelocity",
1524 | "getLODDistanceCoeff",
1525 | "getMass",
1526 | "getMasterVolume",
1527 | "getMaterial",
1528 | "getMaxNumOfParticles",
1529 | "getMaxNumShadowLights",
1530 | "getMD5",
1531 | "getmetatable",
1532 | "getMinClipDistance",
1533 | "getModCategoryName",
1534 | "getModDependency",
1535 | "getModDownloadAvailability",
1536 | "getModDownloadPath",
1537 | "getModFreeSpaceKb",
1538 | "getModHubRating",
1539 | "getModId",
1540 | "getModInstallPath",
1541 | "getModMetaAttributeBool",
1542 | "getModMetaAttributeInt",
1543 | "getModMetaAttributeString",
1544 | "getModNameAndBaseDirectory",
1545 | "getModNumDependencies",
1546 | "getModUseAvailability",
1547 | "getModUsedSpaceKb",
1548 | "getMoonBrightnessScale",
1549 | "getMoonSizeScale",
1550 | "getMotorRotationSpeed",
1551 | "getMotorTorque",
1552 | "getMouseButtonName",
1553 | "getMSAA",
1554 | "getMultiplayerAvailability",
1555 | "getName",
1556 | "getNATType",
1557 | "getNavMeshDistanceToWall",
1558 | "getNavPathDirection",
1559 | "getNavPathHasValidSlope",
1560 | "getNavPathIsValid",
1561 | "getNavPathLength",
1562 | "getNavPathNumOfWaypoints",
1563 | "getNavPathOrientation",
1564 | "getNavPathPosition",
1565 | "getNavPathWaypoint",
1566 | "getNearClip",
1567 | "getNeoMode",
1568 | "getNetworkError",
1569 | "getNormalizedScreenValues",
1570 | "getNormalizedUVs",
1571 | "getNormalizedValues",
1572 | "getNotification",
1573 | "getNumDlcPaths",
1574 | "getNumMaterials",
1575 | "getNumModCategories",
1576 | "getNumOfChildren",
1577 | "getNumOfContactReports",
1578 | "getNumOfGamepads",
1579 | "getNumOfLanguages",
1580 | "getNumOfMods",
1581 | "getNumOfNotifications",
1582 | "getNumOfParticlesToEmitPerMs",
1583 | "getNumOfProcessors",
1584 | "getNumOfScreenModes",
1585 | "getNumOfSplitShapes",
1586 | "getNumOfTriggers",
1587 | "getNumSoundPlayerChannels",
1588 | "getNumSoundPlayerItems",
1589 | "getObjectMask",
1590 | "getOrthographicHeight",
1591 | "getOSVersionName",
1592 | "getOverallVisibility",
1593 | "getP2PNodeId",
1594 | "getParent",
1595 | "getParticleSystemAverageSpeed",
1596 | "getParticleSystemLifespan",
1597 | "getParticleSystemNormalSpeed",
1598 | "getParticleSystemSpeed",
1599 | "getParticleSystemSpeedRandom",
1600 | "getParticleSystemSpriteScaleX",
1601 | "getParticleSystemSpriteScaleXGain",
1602 | "getParticleSystemSpriteScaleY",
1603 | "getParticleSystemSpriteScaleYGain",
1604 | "getParticleSystemTangentSpeed",
1605 | "getPedestrianSystemNightTimeRange",
1606 | "getPerformanceClass",
1607 | "getPerlinNoise2D",
1608 | "getPhysicsDt",
1609 | "getPhysicsDtNonInterpolated",
1610 | "getPhysicsDtUnclamped",
1611 | "getPhysicsUpdateIndex",
1612 | "getProcessorFrequency",
1613 | "getProcessorName",
1614 | "getProjectionOffset",
1615 | "getQuaternion",
1616 | "getRandomPlayerColor",
1617 | "getReflectionMapRatio",
1618 | "getRenderDriver",
1619 | "getResolutionScaling",
1620 | "getRigidBodyType",
1621 | "getRootNode",
1622 | "getRotation",
1623 | "getSampleDuration",
1624 | "getSamplePitch",
1625 | "getSamplePlayOffset",
1626 | "getSamplePlayTimeLeft",
1627 | "getSampleVelocity",
1628 | "getSampleVolume",
1629 | "getScale",
1630 | "getScreenAspectRatio",
1631 | "getScreenHdrOutput",
1632 | "getScreenMode",
1633 | "getScreenModeInfo",
1634 | "getShaderParameter",
1635 | "getShaderQuality",
1636 | "getShaderTimeSec",
1637 | "getShadowMapFilterSize",
1638 | "getShadowMapSize",
1639 | "getShadowQuality",
1640 | "getSoundPlayerChannelName",
1641 | "getSoundPlayerItemName",
1642 | "getSplineCV",
1643 | "getSplineDirection",
1644 | "getSplineLength",
1645 | "getSplineNumOfCV",
1646 | "getSplineOrientation",
1647 | "getSplinePosition",
1648 | "getSplitShapePlaneExtents",
1649 | "getSplitShapeStats",
1650 | "getSplitType",
1651 | "getSSAOIntensity",
1652 | "getSSAOQuality",
1653 | "getStartMode",
1654 | "getStartParameters",
1655 | "getStreamedSampleVolume",
1656 | "getSunBrightnessScale",
1657 | "getSunSizeScale",
1658 | "getSystemLanguage",
1659 | "getTerrainAttributesAtWorldPos",
1660 | "getTerrainDeformationBlockedAreaMapSize",
1661 | "getTerrainDetailByName",
1662 | "getTerrainDetailName",
1663 | "getTerrainDetailNumChannels",
1664 | "getTerrainDetailViewDistance",
1665 | "getTerrainHeightAtWorldPos",
1666 | "getTerrainHeightMapFilename",
1667 | "getTerrainLayerAtWorldPos",
1668 | "getTerrainLayerName",
1669 | "getTerrainLayerNumOfSubLayers",
1670 | "getTerrainLayerSubLayer",
1671 | "getTerrainLodBlendDistances",
1672 | "getTerrainLodBlendDynamicDistances",
1673 | "getTerrainLODDistanceCoeff",
1674 | "getTerrainLodNormalMapFilename",
1675 | "getTerrainLodTypeMapFilename",
1676 | "getTerrainNormalAtWorldPos",
1677 | "getTerrainNumOfLayers",
1678 | "getTerrainSize",
1679 | "getText3DHeight",
1680 | "getText3DLength",
1681 | "getText3DLineLength",
1682 | "getText3DWidth",
1683 | "getTextHeight",
1684 | "getTextLength",
1685 | "getTextLineLength",
1686 | "getTextureResolution",
1687 | "getTextWidth",
1688 | "getTime",
1689 | "getTimeSec",
1690 | "getTotalSystemMemory",
1691 | "getTrafficSystemNightTimeRange",
1692 | "getTranslation",
1693 | "getTyreTracksSegmentsCoeff",
1694 | "getUniqueUserId",
1695 | "getUseDoF",
1696 | "getUseLightScattering",
1697 | "getUserAttribute",
1698 | "getUserId",
1699 | "getUserName",
1700 | "getUserProfileAppPath",
1701 | "getVelocityAtLocalPos",
1702 | "getVelocityAtWorldPos",
1703 | "getVideoOverlayCurrentTime",
1704 | "getVideoOverlayDuration",
1705 | "getViewDistanceCoeff",
1706 | "getVisibility",
1707 | "getVolume",
1708 | "getVolumeMeshTessellationCoeff",
1709 | "getVsync",
1710 | "getWheelShapeAxleSpeed",
1711 | "getWheelShapeContactForce",
1712 | "getWheelShapeContactNormal",
1713 | "getWheelShapeContactObject",
1714 | "getWheelShapeContactPoint",
1715 | "getWheelShapePosition",
1716 | "getWheelShapeSlip",
1717 | "getWorldQuaternion",
1718 | "getWorldRotation",
1719 | "getWorldTranslation",
1720 | "getXMLBool",
1721 | "getXMLFloat",
1722 | "getXMLInt",
1723 | "getXMLRootName",
1724 | "getXMLString",
1725 | "hasNativeAchievementGUI",
1726 | "hasXMLProperty",
1727 | "haveModsChanged",
1728 | "hideAnimal",
1729 | "imeAbort",
1730 | "imeGetCursorPos",
1731 | "imeGetLastString",
1732 | "imeIsComplete",
1733 | "imeIsOpen",
1734 | "imeIsSupported",
1735 | "imeOpen",
1736 | "inAppFinishPendingPurchase",
1737 | "inAppFinishPurchase",
1738 | "inAppGetNumPendingPurchases",
1739 | "inAppGetPendingPurchaseProductId",
1740 | "inAppGetProductDescription",
1741 | "inAppGetProductPrice",
1742 | "inAppInit",
1743 | "inAppIsLoaded",
1744 | "inAppStartPurchase",
1745 | "init",
1746 | "initAchievements",
1747 | "InitClientOnce",
1748 | "initConditionalAnimation",
1749 | "initDensityMapHeightTypeProperties",
1750 | "InitEventClass",
1751 | "initModDownloadManager",
1752 | "InitObjectClass",
1753 | "InitStaticEventClass",
1754 | "InitStaticObjectClass",
1755 | "inspectTableAndPrint",
1756 | "installMod",
1757 | "ipairs",
1758 | "is4kVideoMode",
1759 | "isAbsolutPath",
1760 | "isAnimalVisible",
1761 | "isAnimTrackClipAssigned",
1762 | "isAnimTrackEnabled",
1763 | "isGameFullyInstalled",
1764 | "isGamepadSigninPending",
1765 | "isHeadTrackingAvailable",
1766 | "isHusbandryReady",
1767 | "isModUpdateRunning",
1768 | "isSamplePlaying",
1769 | "isSoundPlayerLoaded",
1770 | "isSoundPlayerPlaying",
1771 | "isUsingHmd",
1772 | "isVideoOverlayPlaying",
1773 | "keyEvent",
1774 | "linearInterpolator1",
1775 | "linearInterpolator2",
1776 | "linearInterpolator3",
1777 | "linearInterpolator4",
1778 | "linearInterpolatorN",
1779 | "linearInterpolatorTransRotScale",
1780 | "link",
1781 | "load",
1782 | "loadAmbientSound",
1783 | "loadBitVectorMapFromFile",
1784 | "loadBitVectorMapNew",
1785 | "loadCropsGrowthStateFromFile",
1786 | "loadDlcs",
1787 | "loadDlcsDirectories",
1788 | "loadDlcsFromDirectory",
1789 | "loadfile",
1790 | "loadI3DFile",
1791 | "loadInterpolator1Curve",
1792 | "loadInterpolator2Curve",
1793 | "loadInterpolator3Curve",
1794 | "loadInterpolator4Curve",
1795 | "loadLanguageSettings",
1796 | "loadMod",
1797 | "loadModDesc",
1798 | "loadMods",
1799 | "loadSample",
1800 | "loadServerSettings",
1801 | "loadSplitShapesFromFile",
1802 | "loadStreamedSample",
1803 | "loadstring",
1804 | "loadTerrainDetailUpdaterStateFromFile",
1805 | "loadUserSettings",
1806 | "loadXMLFile",
1807 | "loadXMLFileFromMemory",
1808 | "localDirectionToLocal",
1809 | "localDirectionToWorld",
1810 | "localRotationToLocal",
1811 | "localRotationToWorld",
1812 | "localToLocal",
1813 | "localToWorld",
1814 | "log",
1815 | "makeSplittable",
1816 | "masterServerAddAvailableMod",
1817 | "masterServerAddAvailableModEnd",
1818 | "masterServerAddAvailableModStart",
1819 | "masterServerAddDlc",
1820 | "masterServerAddDlcEnd",
1821 | "masterServerAddDlcStart",
1822 | "masterServerAddServer",
1823 | "masterServerAddServerMod",
1824 | "masterServerAddServerModEnd",
1825 | "masterServerAddServerModStart",
1826 | "masterServerDisconnect",
1827 | "masterServerInit",
1828 | "masterServerReconnect",
1829 | "masterServerRequestConnectionToServer",
1830 | "masterServerRequestFilteredServers",
1831 | "masterServerRequestServerDetails",
1832 | "masterServerSetCallbacks",
1833 | "masterServerSetNumPlayers",
1834 | "masterServerSetServerInfo",
1835 | "mathEulerRotateVector",
1836 | "mathEulerToQuaternion",
1837 | "mathQuaternionRotateVector",
1838 | "meshNetworkAddNode",
1839 | "meshNetworkBegin",
1840 | "meshNetworkBeginConfig",
1841 | "meshNetworkEnd",
1842 | "meshNetworkEndConfig",
1843 | "meshNetworkGetNodeStatusForApp",
1844 | "modDownloadManagerLoaded",
1845 | "modDownloadManagerUpdateSync",
1846 | "mouseEvent",
1847 | "moveCCT",
1848 | "navMeshRaycast",
1849 | "netCloseConnection",
1850 | "netGetAndResetConnectionSendStats",
1851 | "netGetBandwidthEstimate",
1852 | "netGetConnectionStats",
1853 | "netGetDefaultLocalIp",
1854 | "netGetHostByAddr",
1855 | "netGetTime",
1856 | "netSendStream",
1857 | "netSetIncomingPassword",
1858 | "netSetIsEventProcessingEnabled",
1859 | "netSetMaximumIncomingConnections",
1860 | "netShutdown",
1861 | "netStartup",
1862 | "new2DLayer",
1863 | "newproxy",
1864 | "next",
1865 | "nextMessageTypeId",
1866 | "notificationsLoaded",
1867 | "onBlockedListChanged",
1868 | "onDeepLinkingFailed",
1869 | "onFriendListChanged",
1870 | "OnInGameMenuMenu",
1871 | "OnLoadingScreen",
1872 | "onOkSigninAccept",
1873 | "onShowDeepLinkingErrorMsg",
1874 | "openIntervalTimer",
1875 | "openMpFriendInvitation",
1876 | "openNativeHelpMenu",
1877 | "openWebFile",
1878 | "overlapBox",
1879 | "overlapSphere",
1880 | "pairs",
1881 | "pauseSoundPlayer",
1882 | "pauseStreamedSample",
1883 | "pcall",
1884 | "playSample",
1885 | "playSoundPlayer",
1886 | "playStreamedSample",
1887 | "playVideoOverlay",
1888 | "prepareSaveBitVectorMapToFile",
1889 | "prepareSaveDensityMapToFile",
1890 | "prepareSaveSplitShapesToFile",
1891 | "prepareSaveTerrainHeightMap",
1892 | "prepareSaveTerrainLodTypeMap",
1893 | "prepareSplitShapesServerWriteUpdateStream",
1894 | "print",
1895 | "print_r",
1896 | "printCallstack",
1897 | "printf",
1898 | "printScenegraph",
1899 | "printScenegraphRec",
1900 | "printStatsOverlay",
1901 | "project",
1902 | "projectToCamera",
1903 | "promptUserConfirmScreenMode",
1904 | "quaternionInterpolator",
1905 | "quaternionInterpolator2",
1906 | "rawequal",
1907 | "rawget",
1908 | "rawset",
1909 | "raycastAll",
1910 | "raycastClosest",
1911 | "readAnimalCompanionManagerFromStream",
1912 | "readBitVectorMapFromStream",
1913 | "readDensityDataFromStream",
1914 | "readDensityMapSyncerServerUpdateFromStream",
1915 | "readIntervalTimerMs",
1916 | "readSplitShapeIdFromStream",
1917 | "readSplitShapesClientUpdateFromStream",
1918 | "readSplitShapesFromStream",
1919 | "readSplitShapesServerEventFromStream",
1920 | "readSplitShapesServerUpdateFromStream",
1921 | "readTerrainUpdateStream",
1922 | "readTrafficSystemFromStream",
1923 | "registerGlobalActionEvents",
1924 | "registerHandTool",
1925 | "registerObjectClassName",
1926 | "reloadDlcsAndMods",
1927 | "removeAllDifferentials",
1928 | "removeCCT",
1929 | "removeConsoleCommand",
1930 | "removeContactReport",
1931 | "removeDensityMapSyncerConnection",
1932 | "removeFromPhysics",
1933 | "removeHusbandryAnimal",
1934 | "removeJoint",
1935 | "removeJointBreakReport",
1936 | "removeModEventListener",
1937 | "removeSplitShapeAttachments",
1938 | "removeSplitShapeConnection",
1939 | "removeSplitShapesShaderParameterOverwrite",
1940 | "removeTerrainUpdateConnection",
1941 | "removeTimer",
1942 | "removeTrafficSystemPlayer",
1943 | "removeTrigger",
1944 | "removeWakeUpReport",
1945 | "removeXMLProperty",
1946 | "render360Screenshot",
1947 | "renderEnvProbe",
1948 | "renderOverlay",
1949 | "renderScreenshot",
1950 | "renderText",
1951 | "renderText3D",
1952 | "replaceUnrenderableCharacters",
1953 | "reportAnimalThreat",
1954 | "requestExit",
1955 | "requestGamepadSignin",
1956 | "resetAutoExposure",
1957 | "resetDensityMapVisualizationOverlay",
1958 | "resetEmitStartTimer",
1959 | "resetEmitStopTimer",
1960 | "resetModOnCreateFunctions",
1961 | "resetMultiplayerChecks",
1962 | "resetNumOfEmittedParticles",
1963 | "resetSplitShapes",
1964 | "resetTrafficSystem",
1965 | "restartApplication",
1966 | "resumeStreamedSample",
1967 | "rotate",
1968 | "rotateAboutLocalAxis",
1969 | "saveBitVectorMapToFile",
1970 | "saveCancelUpdateList",
1971 | "saveCropsGrowthStateToFile",
1972 | "saveDeleteSavegame",
1973 | "saveDensityMapToFile",
1974 | "saveGetHasSpaceForSaveGame",
1975 | "saveGetInfo",
1976 | "saveGetInfoById",
1977 | "saveGetNumOfSaveGames",
1978 | "saveGetUploadState",
1979 | "saveHardwareScalability",
1980 | "savePreparedBitVectorMapToFile",
1981 | "savePreparedDensityMapToFile",
1982 | "savePreparedSplitShapesToFile",
1983 | "savePreparedTerrainHeightMap",
1984 | "savePreparedTerrainLodTypeMap",
1985 | "saveReadSavegameCancel",
1986 | "saveReadSavegameFinish",
1987 | "saveReadSavegameGetProgress",
1988 | "saveReadSavegameHasProgress",
1989 | "saveReadSavegameStart",
1990 | "saveResetStorageDeviceSelection",
1991 | "saveResolveConflict",
1992 | "saveScreenshot",
1993 | "saveSetCloudErrorCallback",
1994 | "saveSplitShapesToFile",
1995 | "saveTerrainDetailUpdaterStateToFile",
1996 | "saveTerrainHeightMap",
1997 | "saveTerrainLodNormalMap",
1998 | "saveTerrainLodTypeMap",
1999 | "saveUpdateList",
2000 | "saveWriteSavegameFinish",
2001 | "saveWriteSavegameStart",
2002 | "saveXMLFile",
2003 | "saveXMLFileTo",
2004 | "saveXMLFileToMemory",
2005 | "searchText",
2006 | "select",
2007 | "setAdaptiveVsync",
2008 | "setAngularDamping",
2009 | "setAngularVelocity",
2010 | "setAnimalDaytime",
2011 | "setAnimalInteressNode",
2012 | "setAnimalShaderParameter",
2013 | "setAnimalTextureTile",
2014 | "setAnimTrackBlendWeight",
2015 | "setAnimTrackLoopState",
2016 | "setAnimTrackSpeedScale",
2017 | "setAnimTrackTime",
2018 | "setAtmosphereCornettAsymetryFactor",
2019 | "setAtmosphereMieScale",
2020 | "setAtmosphereSecondaryLightSource",
2021 | "setAudioCullingWorldProperties",
2022 | "setAudioGroupVolume",
2023 | "setAudioSourceAutoPlay",
2024 | "setAudioSourceInnerRange",
2025 | "setAudioSourceRange",
2026 | "setAudioSourceTickInaudible",
2027 | "setBitVectorMapParallelogram",
2028 | "setBloomMagnitude",
2029 | "setBloomMaskThreshold",
2030 | "setBloomQuality",
2031 | "setBrightness",
2032 | "setCamera",
2033 | "setCaption",
2034 | "setCCTPosition",
2035 | "setCenterOfMass",
2036 | "setClipDistance",
2037 | "setCloudFront",
2038 | "setCloudQuality",
2039 | "setCollisionMask",
2040 | "setColorGradingSettings",
2041 | "setCompanionArriveSteeringParameters",
2042 | "setCompanionBehaviorIdleStay",
2043 | "setCompanionBehaviorIdleWander",
2044 | "setCompanionBehaviorWanderParameters",
2045 | "setCompanionCommonSteeringParameters",
2046 | "setCompanionDaytime",
2047 | "setCompanionFeed",
2048 | "setCompanionFetch",
2049 | "setCompanionFollowEntity",
2050 | "setCompanionGotoEntity",
2051 | "setCompanionPet",
2052 | "setCompanionPosition",
2053 | "setCompanionsPhysicsUpdate",
2054 | "setCompanionSteeringTarget",
2055 | "setCompanionSteeringWeights",
2056 | "setCompanionsVisibility",
2057 | "setCompanionThreat",
2058 | "setCompanionTrigger",
2059 | "setCompanionWanderSteeringParameters",
2060 | "setCompanionWaterLevel",
2061 | "setConditionalAnimationBoolValue",
2062 | "setConditionalAnimationFloatValue",
2063 | "setConditionalAnimationSpecificParameterIds",
2064 | "setCropsEnableGrowth",
2065 | "setCropsGrowthMask",
2066 | "setCropsGrowthNextState",
2067 | "setCropsGrowthStateTime",
2068 | "setCropsIgnoreDensityChanges",
2069 | "setCropsMaxNumCellsPerFrame",
2070 | "setCropsNumGrowthStates",
2071 | "setCullOverride",
2072 | "setCurrentMasterVolume",
2073 | "setCurrentProcessPriority",
2074 | "setDebugRenderingMode",
2075 | "setDensityMapHeightCollisionMap",
2076 | "setDensityMapHeightTypeProperties",
2077 | "setDensityMapSyncerLostPacket",
2078 | "setDensityMapVisualizationOverlayGrowthStateColor",
2079 | "setDensityMapVisualizationOverlayStateBorderColor",
2080 | "setDensityMapVisualizationOverlayStateColor",
2081 | "setDensityMapVisualizationOverlayTypeColor",
2082 | "setDensityMapVisualizationOverlayTypedStateColor",
2083 | "setDensityMapVisualizationOverlayUpdateTimeLimit",
2084 | "setDirection",
2085 | "setDiscretePerformanceSetting",
2086 | "setDoFblendWeights",
2087 | "setDoFparams",
2088 | "setDropCountScale",
2089 | "setEmitCountScale",
2090 | "setEmitStartTime",
2091 | "setEmitStopTime",
2092 | "setEmitterShape",
2093 | "setEmittingState",
2094 | "setEnableAmbientSound",
2095 | "setEnableBetaMods",
2096 | "setEnvMap",
2097 | "setExposureKeyValue",
2098 | "setExposureRange",
2099 | "setExposureTau",
2100 | "setFarClip",
2101 | "setfenv",
2102 | "setFileLogPrefixTimestamp",
2103 | "setFillPlaneMaxPhysicalSurfaceAngle",
2104 | "setFilterAnisotropy",
2105 | "setFilterTrilinear",
2106 | "setFogPlaneHeight",
2107 | "setFogPlaneMieScale",
2108 | "setFoliageBendingSystem",
2109 | "setFoliageViewDistanceCoeff",
2110 | "setFovY",
2111 | "setFramerateLimiter",
2112 | "setFrictionVelocity",
2113 | "setFullscreen",
2114 | "setGamepadDeadzone",
2115 | "setGamepadDefaultDeadzone",
2116 | "setGamepadDigitalOutput",
2117 | "setGamepadEnabled",
2118 | "setGamepadVibration",
2119 | "setGamepadVibrationEnabled",
2120 | "setGlobalCloudState",
2121 | "setHasShadowFocusBox",
2122 | "setHasTerrainNormalMapping",
2123 | "setInvertStereoRendering",
2124 | "setIsCompound",
2125 | "setIsCompoundChild",
2126 | "setIsOrthographic",
2127 | "setJointDrive",
2128 | "setJointFrame",
2129 | "setJointPosition",
2130 | "setJointRotationLimit",
2131 | "setJointRotationLimitForceLimit",
2132 | "setJointRotationLimitSpring",
2133 | "setJointTranslationLimit",
2134 | "setJointTranslationLimitForceLimit",
2135 | "setJointTranslationLimitSpring",
2136 | "setLanguage",
2137 | "setLightColor",
2138 | "setLightCullingWorldProperties",
2139 | "setLightRange",
2140 | "setLightScatteringColor",
2141 | "setLightScatteringDirection",
2142 | "setLightShadowMap",
2143 | "setLinearDamping",
2144 | "setLinearVelocity",
2145 | "setLODDistanceCoeff",
2146 | "setLowResCollisionHandlerTerrainRootNode",
2147 | "setLuaErrorHandler",
2148 | "setMass",
2149 | "setMasterVolume",
2150 | "setMaterial",
2151 | "setMaterialDiffuseMap",
2152 | "setMaterialNormalMap",
2153 | "setMaxNumOfParticles",
2154 | "setMaxNumOfReflectionPlanes",
2155 | "setMaxNumShadowLights",
2156 | "setmetatable",
2157 | "setMilkingPlaceDoors",
2158 | "setMinClipDistance",
2159 | "setModDownloadManagerRecommenderParams",
2160 | "setModHubRating",
2161 | "setModInstalled",
2162 | "setMoonBrightnessScale",
2163 | "setMoonSizeScale",
2164 | "setMotorProperties",
2165 | "setMSAA",
2166 | "setName",
2167 | "setNearClip",
2168 | "setNumOfParticlesToEmitPerMs",
2169 | "setObjectMask",
2170 | "setOrthographicHeight",
2171 | "setOverlayColor",
2172 | "setOverlayLayer",
2173 | "setOverlayRotation",
2174 | "setOverlayUVs",
2175 | "setPairCollision",
2176 | "setParticleSystemLifespan",
2177 | "setParticleSystemNormalSpeed",
2178 | "setParticleSystemSpeed",
2179 | "setParticleSystemSpeedRandom",
2180 | "setParticleSystemSpriteScaleX",
2181 | "setParticleSystemSpriteScaleXGain",
2182 | "setParticleSystemSpriteScaleY",
2183 | "setParticleSystemSpriteScaleYGain",
2184 | "setParticleSystemTangentSpeed",
2185 | "setParticleSystemTimeScale",
2186 | "setPedestrianSystemDaytime",
2187 | "setPedestrianSystemEnabled",
2188 | "setPedestrianSystemNightTimeRange",
2189 | "setPerformanceClass",
2190 | "setPolylineTranslation",
2191 | "setPresenceMode",
2192 | "setProjectionOffset",
2193 | "setQuaternion",
2194 | "setReflectionMapObjectMasks",
2195 | "setReflectionMapRatio",
2196 | "setReflectionMapScaling",
2197 | "setRenderOverlayAspectRatio",
2198 | "setRenderOverlayCamera",
2199 | "setResolutionScaling",
2200 | "setRigidBodyType",
2201 | "setRootNode",
2202 | "setRotation",
2203 | "setSampleFrequencyFilter",
2204 | "setSampleGroup",
2205 | "setSamplePitch",
2206 | "setSampleVelocity",
2207 | "setSampleVolume",
2208 | "setScale",
2209 | "setSceneBrightness",
2210 | "setScreenHdrOutput",
2211 | "setScreenMode",
2212 | "setShaderParameter",
2213 | "setShaderQuality",
2214 | "setShadowFocusBox",
2215 | "setShadowMapFilterSize",
2216 | "setShadowMapSize",
2217 | "setShadowQuality",
2218 | "setShapeCullingWorldProperties",
2219 | "setSharedShaderParameter",
2220 | "setShowMouseCursor",
2221 | "setSolverIterationCount",
2222 | "setSoundPlayerChannel",
2223 | "setSoundPlayerItem",
2224 | "setSplitShapesFileIdMapping",
2225 | "setSplitShapesLoadingFileId",
2226 | "setSplitShapesNextFileId",
2227 | "setSplitShapesWorldCompressionParams",
2228 | "setSSAOIntensity",
2229 | "setSSAOQuality",
2230 | "setStartMode",
2231 | "setStereoRendering",
2232 | "setStreamedSampleGroup",
2233 | "setStreamedSampleVolume",
2234 | "setStreamLowPriorityI3DFiles",
2235 | "setSunBrightnessScale",
2236 | "setSunIsPrimary",
2237 | "setSunSizeScale",
2238 | "setTerrainDeformationBlockedAreaMap",
2239 | "setTerrainDeformationBlockedAreaMaxDisplacement",
2240 | "setTerrainDeformationDynamicObjectCollisionMask",
2241 | "setTerrainDeformationDynamicObjectMaxDisplacement",
2242 | "setTerrainDeformationOutsideAreaBrush",
2243 | "setTerrainDeformationOutsideAreaConstraints",
2244 | "setTerrainDeformationSmoothingAmount",
2245 | "setTerrainHeightAtWorldPos",
2246 | "setTerrainLayerAtWorldPos",
2247 | "setTerrainLoadDirectory",
2248 | "setTerrainLodBlendDistances",
2249 | "setTerrainLodBlendDynamicDistances",
2250 | "setTerrainLODDistanceCoeff",
2251 | "setTextAlignment",
2252 | "setTextBold",
2253 | "setTextColor",
2254 | "setTextDepthTestEnabled",
2255 | "setTextLineBounds",
2256 | "setTextLineHeightScale",
2257 | "setTextRenderOverlay",
2258 | "setTextureResolution",
2259 | "setTextVerticalAlignment",
2260 | "setTextWidthScale",
2261 | "setTextWrapWidth",
2262 | "setTimerTime",
2263 | "setTrafficSystemDaytime",
2264 | "setTrafficSystemEnabled",
2265 | "setTrafficSystemNightTimeRange",
2266 | "setTrafficSystemUseOutdoorAudioSetup",
2267 | "setTranslation",
2268 | "setTyreTracksSegementsCoeff",
2269 | "setUpdateCycleTime",
2270 | "setUpdateDeltaValue",
2271 | "setUpdateMask",
2272 | "setUpdateMaskFromInfoLayer",
2273 | "setUpdateMinMaxValue",
2274 | "setUseDoF",
2275 | "setUseKinematicSplitShapes",
2276 | "setUseLightScattering",
2277 | "setUserAttribute",
2278 | "setUserConfirmScreenMode",
2279 | "setVideoOverlayPosition",
2280 | "setVideoOverlayVolume",
2281 | "setViewDistanceCoeff",
2282 | "setViewport",
2283 | "setVisibility",
2284 | "setVolumeMeshTessellationCoeff",
2285 | "setVsync",
2286 | "setWheelShapeAutoHoldBrakeForce",
2287 | "setWheelShapeDirection",
2288 | "setWheelShapeForcePoint",
2289 | "setWheelShapeProps",
2290 | "setWheelShapeSteeringCenter",
2291 | "setWheelShapeTireFriction",
2292 | "setWheelShapeWidth",
2293 | "setWindowFocus",
2294 | "setWindVelocity",
2295 | "setWorldQuaternion",
2296 | "setWorldRotation",
2297 | "setWorldTranslation",
2298 | "setXMLBool",
2299 | "setXMLFloat",
2300 | "setXMLInt",
2301 | "setXMLString",
2302 | "showAnimal",
2303 | "showGameInstallProgress",
2304 | "showSigninScreen",
2305 | "showSoundPlayerContentRatingWarning",
2306 | "showUserProfile",
2307 | "simulateParticleSystems",
2308 | "simulatePhysics",
2309 | "simulatePhysicsTimeScale",
2310 | "smoothDensityMapHeightAtWorldPos",
2311 | "source",
2312 | "splitShape",
2313 | "startDevClient",
2314 | "startDevServer",
2315 | "startFrameRepeatMode",
2316 | "startServerGame",
2317 | "startUpdatePendingMods",
2318 | "startWriteSplitShapesServerEvents",
2319 | "statsGet",
2320 | "statsGetIndex",
2321 | "statsSet",
2322 | "stopSample",
2323 | "stopStreamedSample",
2324 | "stopVideoOverlay",
2325 | "storeAreDlcsCorrupted",
2326 | "storeBeginUserSignIn",
2327 | "storeGetBuyPageState",
2328 | "storeGetNumProducts",
2329 | "storeGetOnlineState",
2330 | "storeGetProductInfo",
2331 | "storeGetProductPrice",
2332 | "storeHasNativeGUI",
2333 | "storeHaveDlcsChanged",
2334 | "storeOpenBuyPage",
2335 | "storeRequestCloseBuyPage",
2336 | "streamAlignReadToByteBoundary",
2337 | "streamAlignWriteToByteBoundary",
2338 | "streamGetIpAndPort",
2339 | "streamGetNumOfUnreadBits",
2340 | "streamGetReadOffset",
2341 | "streamGetWriteOffset",
2342 | "streamI3DFile",
2343 | "streamReadBool",
2344 | "streamReadFloat32",
2345 | "streamReadInt16",
2346 | "streamReadInt32",
2347 | "streamReadInt8",
2348 | "streamReadIntN",
2349 | "streamReadManualTimestamp",
2350 | "streamReadString",
2351 | "streamReadUInt16",
2352 | "streamReadUInt8",
2353 | "streamReadUIntN",
2354 | "streamSetReadOffset",
2355 | "streamSetWriteOffset",
2356 | "streamWriteBool",
2357 | "streamWriteFloat32",
2358 | "streamWriteInt16",
2359 | "streamWriteInt32",
2360 | "streamWriteInt8",
2361 | "streamWriteIntN",
2362 | "streamWriteManualTimestamp",
2363 | "streamWriteStream",
2364 | "streamWriteString",
2365 | "streamWriteTimestamp",
2366 | "streamWriteUInt16",
2367 | "streamWriteUInt8",
2368 | "streamWriteUIntN",
2369 | "syncProfileFiles",
2370 | "testSplitShape",
2371 | "toggleShowFPS",
2372 | "toggleStatsOverlay",
2373 | "toggleVisibility",
2374 | "tonumber",
2375 | "tostring",
2376 | "touchEvent",
2377 | "traceOff",
2378 | "traceOn",
2379 | "translate",
2380 | "type",
2381 | "unicodeToUtf8",
2382 | "uninstallMod",
2383 | "unlink",
2384 | "unloadAmbientSound",
2385 | "unlockAchievement",
2386 | "unpack",
2387 | "unProject",
2388 | "unregisterObjectClassName",
2389 | "update",
2390 | "updateAmbientSound",
2391 | "updateAspectRatio",
2392 | "updateConditionalAnimation",
2393 | "updateDifferential",
2394 | "updateFeedingPlace",
2395 | "updateLoadingBar",
2396 | "updateLoadingBarProgress",
2397 | "updateMod",
2398 | "updatePlacementCollisionMap",
2399 | "updateRenderOverlay",
2400 | "updateTerrainCollisionMap",
2401 | "updateVideoOverlay",
2402 | "upnpAddPortMapping",
2403 | "upnpDiscover",
2404 | "upnpRemovePortMapping",
2405 | "usleep",
2406 | "utf8Strlen",
2407 | "utf8Substr",
2408 | "utf8ToLower",
2409 | "utf8ToUnicode",
2410 | "utf8ToUpper",
2411 | "verifyDlcs",
2412 | "watchTable",
2413 | "watchTableLive",
2414 | "worldDirectionToLocal",
2415 | "worldRotationToLocal",
2416 | "worldToLocal",
2417 | "wrapMousePosition",
2418 | "writeAnimalCompanionManagerToStream",
2419 | "writeBitVectorMapToStream",
2420 | "writeDensityDataToStream",
2421 | "writeDensityMapSyncerServerUpdateToStream",
2422 | "writeSplitShapeIdToStream",
2423 | "writeSplitShapesClientUpdateToStream",
2424 | "writeSplitShapesServerEventToStream",
2425 | "writeSplitShapesServerUpdateToStream",
2426 | "writeSplitShapesToStream",
2427 | "writeTerrainDeformationBlockedAreas",
2428 | "writeTerrainUpdateStream",
2429 | "writeTrafficSystemToStream",
2430 | "xpcall",
2431 | }
2432 | }
2433 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FS19_modROS
2 |
3 | ## Development status
4 |
5 | As of 2021-12-08, this mod is not under active development any more.
6 |
7 | It will most likely remain functional (as FarmSim19 is not expected to change significantly), but it's not feature complete (see the issue tracker for open issues).
8 |
9 |
10 | ## Overview
11 |
12 | This mod for Farming Simulator 2019 allows autonomous driving of FarmSim vehicles with the ROS navigation stack.
13 |
14 | The mod itself is hosted in this repository.
15 | [tud-cor/fs_mod_ros_windows](https://github.com/tud-cor/fs_mod_ros_windows) contains the companion Python scripts which implement a bridge between `modROS` and ROS 1 (using `rospy`).
16 | [tud-cor/fs_mod_ros](https://github.com/tud-cor/fs_mod_ros) contains two example ROS packages which show how to interact with FarmSim19 running `modROS`.
17 |
18 |
19 | ### ROS message support
20 |
21 | In its current state, `modROS` publishes four types of messages:
22 |
23 | - `rosgraph_msgs/Clock`: in-game simulated clock. This message stops being published when the game is paused/exited
24 | - `nav_msgs/Odometry`: ground-truth `Pose` and `Twist` of vehicles based on their in-game position and orientation
25 | - `sensor_msgs/LaserScan`: data from five virtual laser scanners (parallel planes) (but see [#10](https://github.com/tud-cor/FS19_modROS/issues/10))
26 | - `sensor_msgs/Imu`: from a simulated IMU (but see [#6](https://github.com/tud-cor/FS19_modROS/issues/6))
27 |
28 | In addition, there is preliminary support for input into Farming Simulator:
29 |
30 | - `geometry_msgs/Twist`: controls the currently active vehicle (used by the demos in [tud-cor/fs_mod_ros](https://github.com/tud-cor/fs_mod_ros)). Behaviour is similar to - but not identical to - a regular ROS `Twist` interface to a vehicle (velocity mapping is not 1-to-1 yet due to how FarmSim controls vehicles)
31 |
32 | Support for additional message types may be added in the future, but is limited by what the Farming Simulator Lua API exposes.
33 |
34 |
35 | ## ⚠️ Warning and disclaimer
36 |
37 | `modROS` uses memory modification techniques which *could* be considered harmful by anti-cheat systems which are often included in games with on-line gameplay.
38 |
39 | While the manifest clearly marks `modROS` as incompatible with multiplayer game sessions, and the authors have not experienced any problems so far, we feel we must warn users and strongly recommend against ever trying to enable the mod in multiplayer games, nor run any of the scripts in [tud-cor/fs_mod_ros_windows](https://github.com/tud-cor/fs_mod_ros_windows) while playing on-line.
40 | Users cannot hold the authors of `modROS` responsible for loss of (on-line or other) functionality in Farming Simulator 19, nor for any damages related to or as a consequence of such loss of functionality.
41 |
42 |
43 | ## Status
44 |
45 | Some parts are still under development.
46 |
47 |
48 | ## Requirements
49 |
50 | * Windows 10
51 | * Farming Simulator 19
52 |
53 | Both the Steam version of Farming Simulator and the version distributed as a stand-alone purchase have been tested.
54 |
55 |
56 | ## Building
57 |
58 | #### Installing the mod in Farming Simulator 19
59 |
60 | __Note: The following instructions assume the default paths to various system folders are used on your machine. If not, please update the paths in the relevant places.__
61 |
62 | 1. Clone the mod or download the `.zip` at any location
63 |
64 | ```cmd
65 | git clone https://github.com/tud-cor/FS19_modROS modROS
66 | ```
67 |
68 | 2. Moving mod files to the `mods` directory:
69 | In order for FarmSim to detect `modROS`, you either have to move the folder [modROS](https://github.com/tud-cor/FS19_modROS) to the `mods` directory (`%USERPROFILE%\Documents\My Games\FarmingSimulator2019\mods`) or create a symbolic link from the `modROS` folder and drop it in the `FarmingSimulator2019\mods` directory.
70 |
71 | The authors have used [hardlinkshellext/linkshellextension](https://schinagl.priv.at/nt/hardlinkshellext/linkshellextension.html) which makes this an easy process.
72 |
73 | 3. If you've sucessfully installed the mod, it should be listed on the *Installed* tab of the *Mods* section in FarmSim (`modROS` is shown with a red square):
74 |
75 | 
76 |
77 | More information on installing mods in Farming Simulator 2019 can be found [here](http://www.farmingsimulator19mods.com/how-to-install-farming-simulator-2019-19-mods/).
78 |
79 | 4. Enable the Developer Console in Farming Simulator. Tutorial can be found [here](https://www.youtube.com/watch?v=_hYbnu6nJsQ).
80 |
81 |
82 | #### ROS nodes in Windows
83 | To start transmitting messages between Farmsim and ROS, please first go to [fs_mod_ros_windows](https://github.com/tud-cor/fs_mod_ros_windows).
84 |
85 | #### Optional
86 | If you would like to have a simulated RGB camera (not required to run navigation stack in ROS) in Farsmsim using screen capture, please refer to [`d3dshot_screen_grabber`](https://github.com/tud-cor/d3dshot_screen_grabber)
87 |
88 |
89 | ## Running
90 |
91 | To publish data, you need to first run a ROS node-`all_in_one_publisher.py`. Please follow the instructions [here](https://github.com/tud-cor/fs_mod_ros_windows#publishing-data).
92 |
93 | **Note: Before proceeding to the next step, make sure you see *waiting for client from FarmSim19* in the cmd window**
94 |
95 |
96 | Open Farming Simulator 19 and switch the in-game console to command mode by pressing the tilde key (~) twice. More information on how to use console command in game can be found [here](https://wiki.nitrado.net/en/Admin_Commands_for_Farming_Simulator_19).
97 |
98 |
99 | To publish data, execute the following command in the FarmSim console:
100 |
101 | ```
102 | rosPubMsg true
103 | ```
104 |
105 | If you want to stop publishing data, simply execute:
106 |
107 | ```
108 | rosPubMsg false
109 | ```
110 |
111 |
112 | #### Subscribing data
113 |
114 | Please follow the instructions [here](https://github.com/tud-cor/fs_mod_ros_windows#subscribing-data) to run the ROS node- `cm_vel_subscriber.py` first.
115 |
116 |
117 |
118 | To give control of the manned vehicle to ROS, execute the following command in the FarmSim console:
119 |
120 | ```
121 | rosControlVehicle true
122 | ```
123 |
124 | If you want to stop subscribing and gain control back in FarmSim, so you can drive around the farm yourself:
125 |
126 | ```
127 | rosControlVehicle false
128 | ```
129 |
130 | #### Optional
131 | Force-center the camera if you use [`d3dshot_screen_grabber`](https://github.com/tud-cor/d3dshot_screen_grabber) to get a simulated RGB camera.
132 |
133 | This command is used to fix the camera view while capturing the screen. In FarmSim, the camera view is dynamic when one moves the cursor. In order to simulate the rgb sensor, the camera view should be fixed at one angle as it is mounted on the vehicle.
134 |
135 | To force-center the current camera, execute the following command in the FarmSim console:
136 |
137 | ```
138 | forceCenteredCamera true
139 | ```
140 |
141 | Stop forcing the camera:
142 |
143 | ```
144 | forceCenteredCamera false
145 | ```
146 |
147 | #### ROS Navigation stack
148 | Once you have all the required components, please refer to [fs_mod_ros](https://github.com/tud-cor/fs_mod_ros) to run ROS navigation stack on Linux.
149 |
--------------------------------------------------------------------------------
/modDesc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mod ROS
5 |
6 |
7 |
8 |
12 |
13 |
14 | tckarenchiang
15 | 0.0.3.0
16 | store.dds
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/loader.lua:
--------------------------------------------------------------------------------
1 | --[[
2 |
3 | Copyright (c) 2021, TU Delft
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 |
18 | author: Ting-Chia Chiang, G.A. vd. Hoorn
19 | maintainer: Ting-Chia Chiang, G.A. vd. Hoorn
20 |
21 | --]]
22 |
23 | local directory = g_currentModDirectory
24 | local modName = g_currentModName
25 |
26 | g_modROSModDirectory = directory
27 | g_modROSModName = modName
28 |
29 | -- ROS 'messages'
30 | source(Utils.getFilename("src/msgs/geometry_msgs_transform_stamped.lua", directory))
31 | source(Utils.getFilename("src/msgs/nav_msgs_odometry.lua", directory))
32 | source(Utils.getFilename("src/msgs/rosgraph_msgs_clock.lua", directory))
33 | source(Utils.getFilename("src/msgs/sensor_msgs_imu.lua", directory))
34 | source(Utils.getFilename("src/msgs/sensor_msgs_laser_scan.lua", directory))
35 | source(Utils.getFilename("src/msgs/tf2_msgs_tf_message.lua", directory))
36 |
37 | -- third party utilities
38 | source(Utils.getFilename("src/utils/json.lua", directory))
39 | source(Utils.getFilename("src/utils/shared_memory_segment.lua", directory))
40 | source(Utils.getFilename("src/utils/vehicle_util.lua", directory))
41 |
42 | -- our own utilities
43 | source(Utils.getFilename("src/utils/frames.lua", directory))
44 | source(Utils.getFilename("src/utils/ros.lua", directory))
45 |
46 | -- "ROS"
47 | source(Utils.getFilename("src/ros/WriteOnlyFileConnection.lua", directory))
48 | source(Utils.getFilename("src/ros/Publisher.lua", directory))
49 |
50 | -- main/default configuration
51 | -- TODO: add UI for all of this
52 | source(Utils.getFilename("src/mod_config.lua", directory))
53 |
54 | -- main file
55 | source(Utils.getFilename("src/modROS.lua", directory))
56 |
57 | -- LaserScanner class
58 | source(Utils.getFilename("src/utils/LaserScanner.lua", directory))
59 |
60 |
61 | local function validateVehicleTypes()
62 | ModROS.installSpecializations(g_vehicleTypeManager, g_specializationManager, directory, modName)
63 | end
64 |
65 | local function init()
66 | VehicleTypeManager.validateVehicleTypes = Utils.prependedFunction(VehicleTypeManager.validateVehicleTypes, validateVehicleTypes)
67 | end
68 |
69 | init()
70 |
--------------------------------------------------------------------------------
/src/modROS.lua:
--------------------------------------------------------------------------------
1 | --[[
2 |
3 | Copyright (c) 2021, TU Delft
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 |
18 | name: modROS.lua
19 | version: 0.0.1
20 | description:
21 | This mod for Farming Simulator 2019 allows autonomous driving of FarmSim vehicles with the ROS navigation stack.
22 | There are three console commands in this mod for now:
23 | The first one is to publish data, the second one is to subscribe data and the last one is to force-center the camera
24 | ------------------------------------------------
25 | ------------------------------------------------
26 |
27 | A: Publishing data
28 | 1. sim time publisher - publish in-game simulated clock. This message stops being published when the game is paused/exited
29 | 2. odom publisher - publish ground-truth Pose and Twist of vehicles based on their in-game position and orientation
30 | 3. laser scan publisher - publish the laser scan data
31 | 4. imu publisher - publish the imu data (especially the acc info)
32 | 5. A command for writing all messages to a named pipe: "rosPubMsg true/false"
33 |
34 | ------------------------------------------------
35 | ------------------------------------------------
36 |
37 | B. Subscribing data
38 | 1. ros_cmd_teleop subscriber - give the vehicle control to ROS
39 | 2. A command for taking over control of a vehicle in the game : "rosControlVehicle true/false"
40 |
41 | ------------------------------------------------
42 | ------------------------------------------------
43 |
44 | C. Force-centering the camera
45 | 1. A command for force-centering the current camera: "forceCenteredCamera true/false"
46 |
47 | ------------------------------------------------
48 | ------------------------------------------------
49 |
50 | author: Ting-Chia Chiang, G.A. vd. Hoorn
51 | maintainer: Ting-Chia Chiang, G.A. vd. Hoorn
52 |
53 |
54 | --]]
55 |
56 | -- ModROS class is not local here
57 | -- it's now in the global scope so the installSpecializations(..) can be called in loader.lua
58 | ModROS = {}
59 | ModROS.MOD_DIR = g_modROSModDirectory
60 | ModROS.MOD_NAME = g_modROSModName
61 | ModROS.MOD_VERSION = g_modManager.nameToMod[ModROS.MOD_NAME]["version"]
62 |
63 | local function center_camera_func()
64 | local camIdx = g_currentMission.controlledVehicle.spec_enterable.camIndex
65 | local camera = g_currentMission.controlledVehicle.spec_enterable.cameras[camIdx]
66 | camera.rotX = camera.origRotX
67 | camera.rotY = camera.origRotY
68 | end
69 |
70 | function ModROS:loadMap()
71 | self.last_read = ""
72 | self.buf = SharedMemorySegment:init(64)
73 | self.sec = 0
74 | self.nsec = 0
75 | self.l_v_x_0 = 0
76 | self.l_v_y_0 = 0
77 | self.l_v_z_0 = 0
78 |
79 | -- initialise connection to the Python side (but do not connect it yet)
80 | self.path = "\\\\.\\pipe\\FS19_modROS_pipe"
81 | self._conx = WriteOnlyFileConnection.new(self.path)
82 |
83 | -- initialise no-namespace-specific publishers
84 | self._pub_tf = Publisher.new(self._conx, "tf", tf2_msgs_TFMessage)
85 | self._pub_clock = Publisher.new(self._conx, "clock", rosgraph_msgs_Clock)
86 |
87 | print("modROS (" .. ModROS.MOD_VERSION .. ") loaded")
88 | end
89 |
90 | function ModROS.installSpecializations(vehicleTypeManager, specializationManager, modDirectory, modName)
91 | specializationManager:addSpecialization("rosVehicle", "RosVehicle", Utils.getFilename("src/vehicles/RosVehicle.lua", modDirectory), nil) -- Nil is important here
92 |
93 | for typeName, typeEntry in pairs(vehicleTypeManager:getVehicleTypes()) do
94 | -- only add rosVehicle spec to vechile types thathave prerequiste drivable spec
95 | -- if there is no this condition, the will be added to all vehicle types regardless of having drivable spec as prerequisite
96 | -- there would be errors occur when running RosVehicle.prerequisitesPresent()
97 | -- hence, only if the prerequisites of specialization are fulfilled, specializations will be installed
98 | if SpecializationUtil.hasSpecialization(Drivable, typeEntry.specializations) then
99 | vehicleTypeManager:addSpecialization(typeName, modName .. ".rosVehicle")
100 | end
101 | end
102 |
103 | end
104 |
105 | function ModROS:update(dt)
106 | -- create TFMessage object
107 | self.tf_msg = tf2_msgs_TFMessage.new()
108 |
109 | if self.doPubMsg then
110 | -- avoid writing to the pipe if it isn't actually open
111 | if self._conx:is_connected() then
112 | self:publish_sim_time_func()
113 | self:publish_veh_odom_func()
114 | self:publish_laser_scan_func()
115 | self:publish_imu_func()
116 | self._pub_tf:publish(self.tf_msg)
117 |
118 | end
119 | end
120 |
121 | if self.doRosControl then
122 | self:subscribe_ROScontrol_func(dt)
123 | end
124 | if self.doCenterCamera then
125 | if g_currentMission.controlledVehicle == nil then
126 | print("You have left your vehicle! Stop force-centering camera")
127 | self.doCenterCamera = false
128 | else
129 | center_camera_func()
130 | end
131 | end
132 | end
133 |
134 |
135 | -- A.1 sim_time publisher: publish the farmsim time
136 | function ModROS:publish_sim_time_func()
137 | local msg = rosgraph_msgs_Clock.new()
138 | msg.clock = ros.Time.now()
139 | self._pub_clock:publish(msg)
140 | end
141 |
142 |
143 | -- A.2. odom publisher
144 | -- a function to publish ground-truth Pose and Twist of all vehicles (including non-drivable) based on their in-game position and orientation
145 | function ModROS:publish_veh_odom_func()
146 | -- FS time is "frozen" within a single call to update(..), so this
147 | -- will assign the same stamp to all Odometry messages
148 | local ros_time = ros.Time.now()
149 | for _, vehicle in pairs(g_currentMission.vehicles) do
150 | -- only if the vehicle is spec_rosVehicle, the pubOdom() can be called
151 | if vehicle.spec_rosVehicle then
152 | vehicle:pubOdom(ros_time, self.tf_msg)
153 | end
154 | end
155 | end
156 |
157 |
158 | -- A.3. laser scan publisher
159 | function ModROS:publish_laser_scan_func()
160 | -- FS time is "frozen" within a single call to update(..), so this
161 | -- will assign the same stamp to all LaserScan messages
162 | local ros_time = ros.Time.now()
163 | for _, vehicle in pairs(g_currentMission.vehicles) do
164 | -- only if the vehicle is spec_rosVehicle, the pubLaserScan() can be called
165 | if vehicle.spec_rosVehicle then
166 | vehicle:pubLaserScan(ros_time, self.tf_msg)
167 | end
168 | end
169 | end
170 |
171 |
172 | -- A.4. imu publisher
173 | -- a function to publish get the position and orientaion of unmanned or manned vehicle(s) get and write to the named pipe (symbolic link)
174 | function ModROS:publish_imu_func()
175 |
176 | local ros_time = ros.Time.now()
177 | for _, vehicle in pairs(g_currentMission.vehicles) do
178 | if vehicle.spec_rosVehicle then
179 | vehicle:pubImu(ros_time)
180 | end
181 | end
182 | end
183 |
184 | -- A.5. Console command allows to toggle publishers on/off: "rosPubMsg true/false"
185 | -- messages publisher console command
186 | addConsoleCommand("rosPubMsg", "write ros messages to named pipe", "rosPubMsg", ModROS)
187 | function ModROS:rosPubMsg(flag)
188 | if flag ~= nil and flag ~= "" and flag == "true" then
189 |
190 | if not self._conx:is_connected() then
191 | print("connecting to named pipe")
192 | local ret, err = self._conx:connect()
193 | if ret then
194 | print("Opened '" .. self._conx:get_uri() .. "'")
195 | else
196 | -- if not, print error to console and return
197 | print(("Could not connect: %s"):format(err))
198 | print("Possible reasons:")
199 | print(" - symbolic link was not created")
200 | print(" - the 'all_in_one_publisher.py' script is not running")
201 | return
202 | end
203 | end
204 | -- initialisation was successful
205 | self.doPubMsg = true
206 |
207 | elseif flag == nil or flag == "" or flag == "false" then
208 | self.doPubMsg = false
209 | print("stop publishing data, set true, if you want to publish Pose")
210 |
211 | local ret, err = self._conx:disconnect()
212 | if not ret then
213 | print(("Could not disconnect: %s"):format(err))
214 | else
215 | print("Disconnected")
216 | end
217 | end
218 | end
219 |
220 |
221 | -- B.1. ros_cmd_teleop subscriber
222 | -- a function to input the ROS geometry_msgs/Twist into the game to take over control of all vehicles
223 | function ModROS:subscribe_ROScontrol_func(dt)
224 | for _, vehicle in pairs(g_currentMission.vehicles) do
225 | if vehicle.spec_drivable then
226 | -- retrieve the first 32 chars from the buffer
227 | -- note: this does not remove them, it simply copies them
228 | local buf_read = self.buf:read(64)
229 |
230 | -- print to the game console if what we've found in the buffer is different
231 | -- from what was there the previous iteration
232 | -- the counter is just there to make sure we don't see the same line twice
233 | local allowedToDrive = false
234 | if buf_read ~= self.last_read and buf_read ~= "" then
235 | self.last_read = buf_read
236 | local read_str_list = {}
237 | -- loop over whitespace-separated components
238 | for read_str in string.gmatch(self.last_read, "%S+") do
239 | table.insert(read_str_list, read_str)
240 | end
241 |
242 | self.acc = tonumber(read_str_list[1])
243 | self.rotatedTime_param = tonumber(read_str_list[2])
244 | allowedToDrive = read_str_list[3]
245 | end
246 |
247 | if allowedToDrive == "true" then
248 | self.allowedToDrive = true
249 | elseif allowedToDrive == "false" then
250 | self.allowedToDrive = false
251 | end
252 |
253 | vehicle_util.ROSControl(vehicle, dt, self.acc, self.allowedToDrive, self.rotatedTime_param)
254 | end
255 | end
256 | end
257 |
258 |
259 |
260 | -- B.2. A command for taking over control of a vehicle in the game : "rosControlVehicle true/false"
261 |
262 | -- TODO Allow control of vehicles other than the 'active one'. (the console name has already been changed, but the implementation hasn't yet)
263 |
264 | -- console command to take over control of all vehicles in the game
265 | addConsoleCommand("rosControlVehicle", "let ROS control the current vehicle", "rosControlVehicle", ModROS)
266 | function ModROS:rosControlVehicle(flag)
267 | if flag ~= nil and flag ~= "" and flag == "true" then
268 | self.doRosControl = true
269 | print("start ROS teleoperation")
270 | elseif flag == nil or flag == "" or flag == "false" then
271 | self.doRosControl = false
272 | print("stop ROS teleoperation")
273 | end
274 | end
275 |
276 |
277 | -- C.1 A command for force-centering the current camera: "forceCenteredCamera true/false"
278 | -- centering the camera by setting the camera rotX, rotY to original angles
279 | addConsoleCommand("forceCenteredCamera", "force-center the current camera", "forceCenteredCamera", ModROS)
280 | function ModROS:forceCenteredCamera(flag)
281 | if flag ~= nil and flag ~= "" and flag == "true" then
282 | if g_currentMission.controlledVehicle ~= nil then
283 | print("start centering the camera")
284 | self.doCenterCamera = true
285 | else
286 | print("You have left your vehicle, come on! Please hop in one and type the command again!")
287 | end
288 | elseif flag == nil or flag == "" or flag == "false" then
289 | self.doCenterCamera = false
290 | print("stop centering the camera")
291 | end
292 | end
293 |
294 | addModEventListener(ModROS)
295 |
--------------------------------------------------------------------------------
/src/mod_config.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | mod_config =
21 | {
22 | control_only_active_vehicle = false,
23 | vehicle = {
24 | case_ih_7210_pro = {
25 | laser_scan = {
26 | enabled = true,
27 | num_rays = 64,
28 | num_layers = 2,
29 | angle_min = -math.pi,
30 | angle_max = math.pi,
31 | range_min = 0.1,
32 | range_max = 30,
33 | ignore_terrain = true,
34 | inter_layer_distance = 0.1,
35 | -- apply a transform to first laser scan frame
36 | laser_transform = {
37 | translation = {
38 | x = 0.0,
39 | -- This lowers the origin of the scanner to be more in at an expected hight
40 | -- since the original attachment point is on the bonnet and it's too high to see important obstacles
41 | y = -1.5,
42 | z = 0.0
43 | },
44 | rotation = {
45 | -- positive rotation over X rotates laser scanner down (ie: math.pi/6)
46 | x = 0.0,
47 | y = 0.0,
48 | z = 0.0
49 | }
50 | },
51 | laser_attachments = "raycastNode(0)"
52 | },
53 | -- the collision_mask for raycasting can be customized. Both
54 | -- decimal and hexadecimal notations are supported (ie: 9 and 0x9).
55 | -- if 'nil', the default mask will be used.
56 | -- TODO: describe what the "default mask" is exactly (which classes of objects are included / have their bit set to 1).
57 | raycast = {
58 | collision_mask = nil
59 | },
60 | imu = {
61 | enabled = true
62 | }
63 | },
64 | diesel_locomotive = {
65 | laser_scan = {
66 | enabled = false,
67 | num_rays = 64,
68 | num_layers = 2,
69 | angle_min = -math.pi,
70 | angle_max = math.pi,
71 | range_min = 0.1,
72 | range_max = 30,
73 | ignore_terrain = true,
74 | inter_layer_distance = 0.1,
75 | -- apply a transform to first laser scan frame
76 | laser_transform = {
77 | translation = {
78 | x = 0.0,
79 | -- This lowers the origin of the scanner to be more in at an expected hight
80 | -- since the original attachment point is on the bonnet and it's too high to see important obstacles
81 | y = -1.5,
82 | z = 0.0
83 | },
84 | rotation = {
85 | -- positive rotation over X rotates laser scanner down (ie: math.pi/6)
86 | x = 0.0,
87 | y = 0.0,
88 | z = 0.0
89 | }
90 | },
91 | laser_attachments = "raycastNode(0)"
92 | },
93 | -- the collision_mask for raycasting can be customized. Both
94 | -- decimal and hexadecimal notations are supported (ie: 9 and 0x9).
95 | raycast = {
96 | collision_mask = nil
97 | },
98 | imu = {
99 | enabled = false
100 | }
101 | },
102 | fiat_1300dt = {
103 | laser_scan = {
104 | enabled = true,
105 | num_rays = 64,
106 | num_layers = 2,
107 | angle_min = -math.pi,
108 | angle_max = math.pi,
109 | range_min = 0.1,
110 | range_max = 30,
111 | ignore_terrain = true,
112 | inter_layer_distance = 0.1,
113 | -- apply a transform to first laser scan frame
114 | laser_transform = {
115 | translation = {
116 | x = 0.0,
117 | -- This lowers the origin of the scanner to be more in at an expected hight
118 | -- since the original attachment point is on the bonnet and it's too high to see important obstacles
119 | y = -1.5,
120 | z = 0.0
121 | },
122 | rotation = {
123 | -- positive rotation over X rotates laser scanner down (ie: math.pi/6)
124 | x = 0.0,
125 | y = 0.0,
126 | z = 0.0
127 | }
128 | },
129 | laser_attachments = "raycastNode(0)"
130 | },
131 | -- the collision_mask for raycasting can be customized. Both
132 | -- decimal and hexadecimal notations are supported (ie: 9 and 0x9).
133 | raycast = {
134 | collision_mask = nil
135 | },
136 | imu = {
137 | enabled = true
138 | }
139 | },
140 | new_holland_tx_32 = {
141 | laser_scan = {
142 | enabled = true,
143 | num_rays = 64,
144 | num_layers = 2,
145 | angle_min = -math.pi,
146 | angle_max = math.pi,
147 | range_min = 0.1,
148 | range_max = 30,
149 | ignore_terrain = true,
150 | inter_layer_distance = 0.1,
151 | -- apply a transform to first laser scan frame
152 | laser_transform = {
153 | translation = {
154 | x = 0.0,
155 | -- This lowers the origin of the scanner to be more in at an expected hight
156 | -- since the original attachment point is on the bonnet and it's too high to see important obstacles
157 | y = -3,
158 | z = 0.0
159 | },
160 | rotation = {
161 | -- positive rotation over X rotates laser scanner down (ie: math.pi/6)
162 | x = 0.0,
163 | y = 0.0,
164 | z = 0.0
165 | }
166 | },
167 | laser_attachments = "raycastNode(0)"
168 | },
169 | -- the collision_mask for raycasting can be customized. Both
170 | -- decimal and hexadecimal notations are supported (ie: 9 and 0x9).
171 | raycast = {
172 | collision_mask = nil
173 | },
174 | imu = {
175 | enabled = true
176 | }
177 | },
178 | default_vehicle = {
179 | laser_scan = {
180 | enabled = true,
181 | num_rays = 64,
182 | num_layers = 2,
183 | angle_min = -math.pi,
184 | angle_max = math.pi,
185 | range_min = 0.1,
186 | range_max = 30,
187 | ignore_terrain = true,
188 | inter_layer_distance = 0.1,
189 | -- apply a transform to first laser scan frame
190 | laser_transform = {
191 | translation = {
192 | x = 0.0,
193 | -- This lowers the origin of the scanner to be more in at an expected hight
194 | -- since the original attachment point is on the bonnet and it's too high to see important obstacles
195 | y = -1.5,
196 | z = 0.0
197 | },
198 | rotation = {
199 | -- positive rotation over X rotates laser scanner down (ie: math.pi/6)
200 | x = 0.0,
201 | y = 0.0,
202 | z = 0.0
203 | }
204 | },
205 | laser_attachments = "raycastNode(0)"
206 | },
207 | -- the collision_mask for raycasting can be customized. Both
208 | -- decimal and hexadecimal notations are supported (ie: 9 and 0x9).
209 | raycast = {
210 | collision_mask = nil
211 | },
212 | imu = {
213 | enabled = true
214 | }
215 | },
216 | }
217 | }
218 |
219 | return mod_config
220 |
--------------------------------------------------------------------------------
/src/msgs/geometry_msgs_transform_stamped.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | -- geometry_msgs_TransformStamped class
21 | geometry_msgs_TransformStamped = {}
22 | geometry_msgs_TransformStamped.ROS_MSG_NAME = "geometry_msgs/TransformStamped"
23 |
24 | local geometry_msgs_TransformStamped_mt = Class(geometry_msgs_TransformStamped)
25 |
26 | function geometry_msgs_TransformStamped.new()
27 | local self = {}
28 | setmetatable(self, geometry_msgs_TransformStamped_mt)
29 |
30 | -- fields as defined by geometry_msgs/TransformStamped
31 | self.header = {
32 | frame_id = "",
33 | stamp = {
34 | secs = 0,
35 | nsecs = 0
36 | }
37 | }
38 | self.child_frame_id = ""
39 | self.transform = {
40 | translation = {
41 | x = 0.0,
42 | y = 0.0,
43 | z = 0.0
44 | },
45 | rotation = {
46 | x = 0.0,
47 | y = 0.0,
48 | z = 0.0,
49 | w = 0.0
50 | }
51 | }
52 |
53 | return self
54 | end
55 |
56 | function geometry_msgs_TransformStamped:delete()
57 | end
58 |
59 | function geometry_msgs_TransformStamped:set(frame_id, stamp, child_frame_id, tx, ty, tz, qx, qy, qz, qw)
60 | -- directly overwrite local fields
61 | self.header = {
62 | frame_id = frame_id,
63 | stamp = stamp
64 | }
65 | self.child_frame_id = child_frame_id
66 | self.transform = {
67 | translation = {
68 | x = tx,
69 | y = ty,
70 | z = tz
71 | },
72 | rotation = {
73 | x = qx,
74 | y = qy,
75 | z = qz,
76 | w = qw
77 | }
78 | }
79 | end
80 |
81 | function geometry_msgs_TransformStamped:to_json()
82 | return json.stringify(self)
83 | end
84 |
--------------------------------------------------------------------------------
/src/msgs/nav_msgs_odometry.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | nav_msgs_Odometry = {}
21 | nav_msgs_Odometry.ROS_MSG_NAME = "nav_msgs/Odometry"
22 |
23 | local nav_msgs_Odometry_mt = Class(nav_msgs_Odometry)
24 |
25 | function nav_msgs_Odometry.new()
26 | local self = {}
27 | setmetatable(self, nav_msgs_Odometry_mt)
28 |
29 | -- fields as defined by nav_msgs/Odometry
30 | self.header = {
31 | frame_id = "",
32 | stamp = {secs = 0, nsecs = 0}
33 | }
34 | self.child_frame_id = ""
35 | self.pose = {
36 | pose = {
37 | position = {
38 | x = 0.0,
39 | y = 0.0,
40 | z = 0.0
41 | },
42 | orientation = {
43 | x = 0.0,
44 | y = 0.0,
45 | z = 0.0,
46 | w = 0.0
47 | }
48 | }
49 | }
50 | self.twist = {
51 | twist = {
52 | linear = {
53 | x = 0.0,
54 | y = 0.0,
55 | z = 0.0
56 | },
57 | angular = {
58 | x = 0.0,
59 | y = 0.0,
60 | z = 0.0
61 | }
62 | }
63 | }
64 |
65 | return self
66 | end
67 |
68 | function nav_msgs_Odometry:delete()
69 | end
70 |
71 | function nav_msgs_Odometry:set(frame_id, stamp, child_frame_id, px, py, pz, qx, qy, qz, qw, tlx, tly, tlz, tax, tay, taz)
72 | -- directly overwrite local fields
73 | self.header = {
74 | frame_id = frame_id,
75 | stamp = stamp
76 | }
77 | self.child_frame_id = child_frame_id
78 | self.pose = {
79 | pose = {
80 | position = {
81 | x = pz,
82 | y = px,
83 | z = py
84 | },
85 | orientation = {
86 | x = qx,
87 | y = qy,
88 | z = qz,
89 | w = qw
90 | }
91 | }
92 | }
93 | self.twist = {
94 | twist = {
95 | linear = {
96 | x = tlx,
97 | y = tly,
98 | z = tlz
99 | },
100 | angular = {
101 | x = tax,
102 | y = tay,
103 | z = taz
104 | }
105 | }
106 | }
107 | end
108 |
109 | function nav_msgs_Odometry:to_json()
110 | return json.stringify(self)
111 | end
112 |
--------------------------------------------------------------------------------
/src/msgs/rosgraph_msgs_clock.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | -- rosgraph_msgs_Clock class
21 | rosgraph_msgs_Clock = {}
22 | rosgraph_msgs_Clock.ROS_MSG_NAME = "rosgraph_msgs/Clock"
23 |
24 | local rosgraph_msgs_Clock_mt = Class(rosgraph_msgs_Clock)
25 |
26 | function rosgraph_msgs_Clock.new()
27 | local self = {}
28 | setmetatable(self, rosgraph_msgs_Clock_mt)
29 |
30 | -- fields as defined by rosgraph_msgs/Clock
31 | self.clock = {secs = 0, nsecs = 0}
32 |
33 | return self
34 | end
35 |
36 | function rosgraph_msgs_Clock:delete()
37 | end
38 |
39 | function rosgraph_msgs_Clock:set(clock)
40 | -- directly overwrite local fields
41 | self.clock = clock
42 | end
43 |
44 | function rosgraph_msgs_Clock:to_json()
45 | return json.stringify(self)
46 | end
47 |
--------------------------------------------------------------------------------
/src/msgs/sensor_msgs_imu.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | -- sensor_msgs_Imu class
21 | sensor_msgs_Imu = {}
22 | sensor_msgs_Imu.ROS_MSG_NAME = "sensor_msgs/Imu"
23 |
24 | local sensor_msgs_Imu_mt = Class(sensor_msgs_Imu)
25 |
26 | function sensor_msgs_Imu.new()
27 | local self = {}
28 | setmetatable(self, sensor_msgs_Imu_mt)
29 |
30 | -- fields as defined by sensor_msgs/Imu
31 | self.header = {
32 | frame_id = "",
33 | stamp = {secs = 0, nsecs = 0}
34 | }
35 | self.orientation = {
36 | x = 0.0,
37 | y = 0.0,
38 | z = 0.0,
39 | w = 0.0
40 | }
41 | self.angular_velocity = {
42 | x = 0.0,
43 | y = 0.0,
44 | z = 0.0
45 | }
46 | self.linear_acceleration = {
47 | x = 0.0,
48 | y = 0.0,
49 | z = 0.0
50 | }
51 |
52 | return self
53 | end
54 |
55 | function sensor_msgs_Imu:delete()
56 | end
57 |
58 | function sensor_msgs_Imu:set(frame_id, stamp, qx, qy, qz, qw, avx, avy, avz, lax, lay, laz)
59 | -- directly overwrite local fields
60 | self.header = {
61 | frame_id = frame_id,
62 | stamp = stamp
63 | }
64 | self.orientation = {
65 | x = qx,
66 | y = qy,
67 | z = qz,
68 | w = qw
69 | }
70 | self.angular_velocity = {
71 | x = avx,
72 | y = avy,
73 | z = avz
74 | }
75 | self.linear_acceleration = {
76 | x = lax,
77 | y = lay,
78 | z = laz
79 | }
80 | end
81 |
82 | function sensor_msgs_Imu:to_json()
83 | return json.stringify(self)
84 | end
85 |
--------------------------------------------------------------------------------
/src/msgs/sensor_msgs_laser_scan.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | -- sensor_msgs_LaserScan class
21 | sensor_msgs_LaserScan = {}
22 | sensor_msgs_LaserScan.ROS_MSG_NAME = "sensor_msgs/LaserScan"
23 |
24 | local sensor_msgs_LaserScan_mt = Class(sensor_msgs_LaserScan)
25 |
26 | function sensor_msgs_LaserScan.new()
27 | local self = {}
28 | setmetatable(self, sensor_msgs_LaserScan_mt)
29 |
30 | -- fields as defined by sensor_msgs/LaserScan
31 | self.header = {
32 | frame_id = "",
33 | stamp = {secs = 0, nsecs = 0}
34 | }
35 | self.angle_min = 0.0
36 | self.angle_max = 0.0
37 | self.angle_increment = 0.0
38 | self.time_increment = 0.0
39 | self.scan_time = 0.0
40 | self.range_min = 0.0
41 | self.range_max = 0.0
42 | self.ranges = {}
43 | self.intensities = {}
44 |
45 | return self
46 | end
47 |
48 | function sensor_msgs_LaserScan:delete()
49 | end
50 |
51 | function sensor_msgs_LaserScan:set(
52 | frame_id,
53 | stamp,
54 | angle_min,
55 | angle_max,
56 | angle_increment,
57 | time_increment,
58 | scan_time,
59 | range_min,
60 | range_max,
61 | ranges,
62 | intensities)
63 | -- directly overwrite local fields
64 | self.header = {
65 | frame_id = frame_id,
66 | stamp = stamp
67 | }
68 | self.angle_min = angle_min
69 | self.angle_max = angle_max
70 | self.angle_increment = angle_increment
71 | self.time_increment = time_increment
72 | self.scan_time = scan_time
73 | self.range_min = range_min
74 | self.range_max = range_max
75 | self.ranges = ranges
76 | self.intensities = intensities
77 | end
78 |
79 | function sensor_msgs_LaserScan:to_json()
80 | return json.stringify(self)
81 | end
82 |
--------------------------------------------------------------------------------
/src/msgs/tf2_msgs_tf_message.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | -- tf2_msgs_TFMessage class
21 | tf2_msgs_TFMessage = {}
22 | tf2_msgs_TFMessage.ROS_MSG_NAME = "tf2_msgs/TFMessage"
23 |
24 | local tf2_msgs_TFMessage_mt = Class(tf2_msgs_TFMessage)
25 |
26 | function tf2_msgs_TFMessage.new()
27 | local self = {}
28 | setmetatable(self, tf2_msgs_TFMessage_mt)
29 |
30 | -- fields as defined by tf2_msgs/TFMessage
31 | self.transforms = {}
32 |
33 | return self
34 | end
35 |
36 | function tf2_msgs_TFMessage:delete()
37 | end
38 |
39 | function tf2_msgs_TFMessage:set(transforms)
40 | -- directly overwrite local fields
41 | self.transforms = transforms
42 | end
43 |
44 | function tf2_msgs_TFMessage:add_transform(transform)
45 | table.insert(self.transforms, transform)
46 | end
47 |
48 | function tf2_msgs_TFMessage:to_json()
49 | return json.stringify(self)
50 | end
51 |
--------------------------------------------------------------------------------
/src/ros/Publisher.lua:
--------------------------------------------------------------------------------
1 | --[[
2 |
3 | Copyright (c) 2021, TU Delft
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 |
18 | author: Ting-Chia Chiang, G.A. vd. Hoorn
19 | maintainer: Ting-Chia Chiang, G.A. vd. Hoorn
20 |
21 | --]]
22 |
23 | Publisher = {}
24 |
25 | local Publisher_mt = Class(Publisher)
26 |
27 |
28 | function Publisher.new(connection, topic_name, message_type)
29 | local self = {}
30 | setmetatable(self, Publisher_mt)
31 |
32 | if message_type['ROS_MSG_NAME'] == nil then
33 | -- TODO: implement proper logging
34 | print(("message_type must have ROS_MSG_NAME key, can't find it in '%s'"):format(message_type))
35 | return nil, "ctor error: invalid message_type"
36 | end
37 |
38 | -- NOTE: there is no locking, so concurrent access to the connection is not
39 | -- guarded against. Serialisation of access is responsibility of owner of
40 | -- the Publisher object
41 | self._conx = connection
42 |
43 | -- "topic_name" could be with or without namespace
44 | -- with e.g. "/odom"
45 | -- wihtout e.g. "clock"
46 | self._topic_name = topic_name
47 |
48 | -- we need this to be able to tell the Python side what sort of message
49 | -- we're serialising
50 | self._message_type_name = message_type.ROS_MSG_NAME
51 |
52 | return self
53 | end
54 |
55 | function Publisher:delete()
56 | -- nothing to do. Connection object is not owned by this Publisher
57 | end
58 |
59 | function Publisher:publish(msg)
60 | if msg.ROS_MSG_NAME ~= self._message_type_name then
61 | return nil, ("Can't publish '%s' with publisher of type '%s'"):format(msg.ROS_MSG_NAME, self._message_type_name)
62 | end
63 | if not self._conx:is_connected() then
64 | return nil, "Can't write to nil fd"
65 | end
66 |
67 | -- try writing the serialised message to the connection
68 | local ret, err = self._conx:write(self._topic_name .. "\n" .. msg.ROS_MSG_NAME .. "\n" .. msg:to_json())
69 | if not ret then
70 | return nil, "Error publishing message: '" .. err .. "'"
71 | end
72 | return ret
73 | end
74 |
--------------------------------------------------------------------------------
/src/ros/WriteOnlyFileConnection.lua:
--------------------------------------------------------------------------------
1 | --[[
2 |
3 | Copyright (c) 2021, TU Delft
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 |
18 | author: Ting-Chia Chiang, G.A. vd. Hoorn
19 | maintainer: Ting-Chia Chiang, G.A. vd. Hoorn
20 |
21 | --]]
22 |
23 | WriteOnlyFileConnection = {}
24 |
25 | local WriteOnlyFileConnection_mt = Class(WriteOnlyFileConnection)
26 |
27 |
28 | function WriteOnlyFileConnection.new(uri)
29 | local self = {}
30 | setmetatable(self, WriteOnlyFileConnection_mt)
31 |
32 | self._uri = uri
33 | self._fd = nil
34 |
35 | return self
36 | end
37 |
38 | function WriteOnlyFileConnection:delete()
39 | self:close()
40 | end
41 |
42 | function WriteOnlyFileConnection:get_uri()
43 | return self._uri
44 | end
45 |
46 | function WriteOnlyFileConnection:_open()
47 | -- NOTE: this is not guarded in any way
48 | -- TODO: allow specifying flags
49 | self._fd = io.open(self._uri, "w")
50 | if not self._fd then
51 | return nil, "Could not open uri: unknown reason (FS Lua does not provide one)"
52 | end
53 | return true
54 | end
55 |
56 | function WriteOnlyFileConnection:_close()
57 | -- NOTE: this is not guarded in any way
58 | self._fd:close()
59 | self._fd = nil
60 | return true
61 | end
62 |
63 | function WriteOnlyFileConnection:connect()
64 | -- only connect if we're not already connected
65 | if self:is_connected() then
66 | return nil, "Already connected"
67 | end
68 |
69 | local ret, err = self:_open()
70 | if not ret then
71 | return nil, "Could not connect: '" .. err .. "'"
72 | end
73 | return ret
74 | end
75 |
76 | function WriteOnlyFileConnection:disconnect()
77 | -- only disconnect if we're actually connected
78 | if not self:is_connected() then
79 | return nil, "Not connected"
80 | end
81 |
82 | local ret, err = self:_close()
83 | if not ret then
84 | return nil, "Could not disconnect: '" .. err .. "'"
85 | end
86 | return ret
87 | end
88 |
89 | function WriteOnlyFileConnection:get_fd()
90 | return self._fd
91 | end
92 |
93 | function WriteOnlyFileConnection:is_connected()
94 | --TODO: find a better way to figure out whether a file is still open.
95 | -- io.type(..) does not appear to be supported :(
96 | return (self._fd ~= nil)
97 | end
98 |
99 | function WriteOnlyFileConnection:write(data)
100 | if not self:is_connected() then
101 | return nil, "Not connected"
102 | end
103 | -- does write() return anything?
104 | self._fd:write(data)
105 | return true
106 | end
107 |
--------------------------------------------------------------------------------
/src/utils/LaserScanner.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | author: Ting-Chia Chiang
13 | author: G.A. vd. Hoorn
14 | --]]
15 |
16 | LaserScanner = {}
17 |
18 | local LaserScanner_mt = Class(LaserScanner)
19 |
20 | function LaserScanner.new(vehicle, vehicle_table)
21 | local self = {}
22 | setmetatable(self, LaserScanner_mt)
23 |
24 | -- store a reference to the table with settings for this scanner instance
25 | self.vehicle_table = vehicle_table
26 | -- store a reference to the vehicle this scanner is attached to
27 | self.vehicle = vehicle
28 |
29 | -- initial raycast distance
30 | self.INIT_RAY_DISTANCE = 1000
31 | -- set a raycast mask for a camera node which enables bits 5(unkown), 6(tractors), 7(combines), 8(trailers), 12(dynamic_objects)
32 | local RC_MASK_UNKNOWN5 = math.pow(2, 5)
33 | local RC_MASK_TRACTORS = math.pow(2, 6)
34 | local RC_MASK_COMBINES = math.pow(2, 7)
35 | local RC_MASK_TRAILERS = math.pow(2, 8)
36 | local RC_MASK_DYN_OBJS = math.pow(2, 12)
37 |
38 | -- if provided, use custom collision mask. If not, use default.
39 | if self.collision_mask then
40 | self.raycastMask = self.collision_mask
41 | -- print(("Using custom collision mask for laser scanner: 0x%08X"):format(self.raycastMask))
42 | else
43 | self.raycastMask = RC_MASK_UNKNOWN5 + RC_MASK_TRACTORS + RC_MASK_COMBINES + RC_MASK_TRAILERS + RC_MASK_DYN_OBJS
44 | -- print(("Using default collision mask for laser scanner: 0x%08X"):format(self.raycastMask))
45 | end
46 |
47 | self.cos = math.cos
48 | self.sin = math.sin
49 | self.radius = 0.2
50 | self.LS_FOV = self.vehicle_table.laser_scan.angle_max - self.vehicle_table.laser_scan.angle_min
51 | -- calculate nr of steps between rays
52 | self.delta_theta = self.LS_FOV / (self.vehicle_table.laser_scan.num_rays - 1)
53 |
54 | return self
55 | end
56 |
57 |
58 | function LaserScanner:getLaserData(laser_scan_array, x, y, z, dx_r, dy, dz_r)
59 | self.raycastDistance = self.INIT_RAY_DISTANCE
60 | raycastClosest(x, y, z, dx_r, dy, dz_r, "raycastCallback", self.vehicle_table.laser_scan.range_max, self, self.raycastMask)
61 | -- push back the self.raycastDistance to self.laser_scan_array table
62 | -- if self.raycastDistance is updated which mean there is object detected and raycastCallback is called
63 | -- otherwise, fill the range with self.INIT_RAY_DISTANCE (1000) (no object detected)
64 | -- if laser_scan.ignore_terrain is set true then ignore the terrain when detected
65 |
66 | if self.vehicle_table.laser_scan.ignore_terrain then
67 | -- this is a temporary method to filter out laser hits on the vehicle itself
68 | -- in FS, there are many vehicles composed of 2 components: the first component is the main part and the second component is mostly the axis object(s).
69 | -- however, some driveable vehicles do not have a 2nd component (e.g. diesel_locomotive). We need to exclude the condition of hitting 2nd component, if there exists no 2nd compoenent
70 | if not self.vehicle.components[2] then
71 | if self.raycastDistance ~= self.INIT_RAY_DISTANCE and self.raycastTransformId ~= g_currentMission.terrainRootNode and self.raycastTransformId ~= self.vehicle.components[1].node then
72 | table.insert(laser_scan_array, self.raycastDistance)
73 | else
74 | table.insert(laser_scan_array, self.INIT_RAY_DISTANCE)
75 | end
76 | else
77 | if self.raycastDistance ~= self.INIT_RAY_DISTANCE and self.raycastTransformId ~= g_currentMission.terrainRootNode and self.raycastTransformId ~= self.vehicle.components[1].node and self.raycastTransformId ~= self.vehicle.components[2].node then
78 | table.insert(laser_scan_array, self.raycastDistance)
79 | else
80 | table.insert(laser_scan_array, self.INIT_RAY_DISTANCE)
81 | end
82 | end
83 | else
84 | if self.raycastDistance ~= self.INIT_RAY_DISTANCE then
85 | table.insert(laser_scan_array, self.raycastDistance)
86 | else
87 | table.insert(laser_scan_array, self.INIT_RAY_DISTANCE)
88 | end
89 | end
90 | end
91 |
92 |
93 | function LaserScanner:raycastCallback(transformId, _, _, _, distance, _, _, _)
94 | self.raycastDistance = distance
95 | self.raycastTransformId = transformId
96 | -- for debugging
97 | -- self.object = g_currentMission:getNodeObject(self.raycastTransformId)
98 | -- print(string.format("hitted object is %s",getName(self.raycastTransformId)))
99 | -- print(string.format("hitted object id is %f",self.raycastTransformId))
100 | -- print(string.format("self.raycastDistance is %f",self.raycastDistance))
101 | -- print("v_id ",g_currentMission.controlledVehicle.components[1].node)
102 | end
103 |
104 |
105 | function LaserScanner:doScan(ros_time, tf_msg)
106 | local spec = self.vehicle.spec_rosVehicle
107 |
108 | for i = 0, spec.laser_scan_obj.vehicle_table.laser_scan.num_layers-1 do
109 | spec.laser_scan_array = {}
110 | -- get the (world) coordinate of each laser scanner's origin: (orig_x, orig_y, orig_z)
111 | -- "laser_dy" is added between the scanning planes, along +y direction (locally) from the lowest laser scan plane
112 | -- and all laser scan planes are parallel to each other
113 | local laser_dy = spec.laser_scan_obj.vehicle_table.laser_scan.inter_layer_distance * i
114 | local orig_x, orig_y, orig_z = localToWorld(spec.LaserFrameNode, 0, laser_dy, 0)
115 |
116 | for j = 0, (spec.laser_scan_obj.vehicle_table.laser_scan.num_rays - 1) do
117 | local seg_theta = j * spec.laser_scan_obj.delta_theta
118 | -- (i_laser_dx, 0 , i_laser_dz) is a local space direction to define the world space raycasting (scanning) direction
119 | local i_laser_dx = -spec.laser_scan_obj.sin(seg_theta) * spec.laser_scan_obj.radius
120 | local i_laser_dz = -spec.laser_scan_obj.cos(seg_theta) * spec.laser_scan_obj.radius
121 | local dx, dy, dz = localDirectionToWorld(spec.LaserFrameNode, i_laser_dx, 0 , i_laser_dz)
122 | spec.laser_scan_obj:getLaserData(spec.laser_scan_array, orig_x, orig_y, orig_z, dx, dy, dz)
123 | end
124 |
125 | -- create LaserScan instance
126 | local scan_msg = sensor_msgs_LaserScan.new()
127 |
128 | -- populate fields (not using LaserScan:set(..) here as this is much
129 | -- more readable than a long list of anonymous args)
130 | scan_msg.header.frame_id = spec.base_link_frame .."/laser_frame_" .. i
131 | scan_msg.header.stamp = ros_time
132 | -- with zero angle being forward along the x axis, scanning fov +-180 degrees
133 | scan_msg.angle_min = spec.laser_scan_obj.vehicle_table.laser_scan.angle_min
134 | scan_msg.angle_max = spec.laser_scan_obj.vehicle_table.laser_scan.angle_max
135 | scan_msg.angle_increment = spec.laser_scan_obj.LS_FOV / spec.laser_scan_obj.vehicle_table.laser_scan.num_rays
136 | -- assume sensor gives 50 scans per second
137 | scan_msg.time_increment = (1.0 / 50) / spec.laser_scan_obj.vehicle_table.laser_scan.num_rays
138 | --scan_msg.scan_time = 0.0 -- we don't set this field (TODO: should we?)
139 | scan_msg.range_min = spec.laser_scan_obj.vehicle_table.laser_scan.range_min
140 | scan_msg.range_max = spec.laser_scan_obj.vehicle_table.laser_scan.range_max
141 | scan_msg.ranges = spec.laser_scan_array
142 | --scan_msg.intensities = {} -- we don't set this field (TODO: should we?)
143 |
144 | -- publish the message
145 | spec.pub_scan:publish(scan_msg)
146 |
147 | -- convert to quaternion for ROS TF
148 | -- note the order of the axes here (see earlier comment about FS chirality)
149 | -- the rotation from base_link to raycastnode is the same as rotation from raycastnode to virtaul laser_frame_i as there is no rotation between base_link to raycastnode
150 | local q = ros.Transformations.quaternion_from_euler(spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.z, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.x, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.y)
151 |
152 | -- get the translation from base_link to laser_frame_i
153 | -- laser_dy is the offset from laser_frame_i to laser_frame_i+1
154 | local base_to_laser_x, base_to_laser_y, base_to_laser_z = localToLocal(spec.LaserFrameNode, self.vehicle.components[1].node, 0, laser_dy, 0)
155 |
156 | -- create single TransformStamped message
157 | local tf_base_link_laser_frame_i = geometry_msgs_TransformStamped.new()
158 | tf_base_link_laser_frame_i:set(
159 | spec.base_link_frame,
160 | ros_time,
161 | spec.base_link_frame .."/laser_frame_" .. i,
162 | -- note the order of the axes here (see earlier comment about FS chirality)
163 | base_to_laser_z,
164 | base_to_laser_x,
165 | base_to_laser_y,
166 | -- we don't need to swap the order of q, since the calculation of q is based on the ROS chirality
167 | q[1],
168 | q[2],
169 | q[3],
170 | q[4]
171 | )
172 | spec:addTF(tf_msg, tf_base_link_laser_frame_i)
173 | end
174 | end
175 |
--------------------------------------------------------------------------------
/src/utils/frames.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | frames = {}
21 |
22 | function frames.create_attached_node(parentNodeId, transformName, tran_x, tran_y, tran_z, rot_x, rot_y, rot_z)
23 | -- create a node
24 | local node = createTransformGroup(transformName)
25 | -- link the node to parentNodeId
26 | link(parentNodeId, node)
27 | -- apply a transfrom to the new node
28 | setTranslation(node, tran_x, tran_y, tran_z)
29 | setRotation(node, rot_x, rot_y, rot_z)
30 | return node
31 | end
32 |
33 | return frames
34 |
35 |
--------------------------------------------------------------------------------
/src/utils/json.lua:
--------------------------------------------------------------------------------
1 | --[[ json.lua
2 |
3 | A compact pure-Lua JSON library.
4 | The main functions are: json.stringify, json.parse.
5 |
6 | ## json.stringify:
7 |
8 | This expects the following to be true of any tables being encoded:
9 | * They only have string or number keys. Number keys must be represented as
10 | strings in json; this is part of the json spec.
11 | * They are not recursive. Such a structure cannot be specified in json.
12 |
13 | A Lua table is considered to be an array if and only if its set of keys is a
14 | consecutive sequence of positive integers starting at 1. Arrays are encoded like
15 | so: `[2, 3, false, "hi"]`. Any other type of Lua table is encoded as a json
16 | object, encoded like so: `{"key1": 2, "key2": false}`.
17 |
18 | Because the Lua nil value cannot be a key, and as a table value is considerd
19 | equivalent to a missing key, there is no way to express the json "null" value in
20 | a Lua table. The only way this will output "null" is if your entire input obj is
21 | nil itself.
22 |
23 | An empty Lua table, {}, could be considered either a json object or array -
24 | it's an ambiguous edge case. We choose to treat this as an object as it is the
25 | more general type.
26 |
27 | To be clear, none of the above considerations is a limitation of this code.
28 | Rather, it is what we get when we completely observe the json specification for
29 | as arbitrary a Lua object as json is capable of expressing.
30 |
31 | ## json.parse:
32 |
33 | This function parses json, with the exception that it does not pay attention to
34 | \u-escaped unicode code points in strings.
35 |
36 | It is difficult for Lua to return null as a value. In order to prevent the loss
37 | of keys with a null value in a json string, this function uses the one-off
38 | table value json.null (which is just an empty table) to indicate null values.
39 | This way you can check if a value is null with the conditional
40 | `val == json.null`.
41 |
42 | If you have control over the data and are using Lua, I would recommend just
43 | avoiding null values in your data to begin with.
44 |
45 | --]]
46 |
47 |
48 | json = {}
49 |
50 |
51 |
52 |
53 | -- Internal functions.
54 |
55 | local function kind_of(obj)
56 | if type(obj) ~= 'table' then return type(obj) end
57 | local i = 1
58 | for _ in pairs(obj) do
59 | if obj[i] ~= nil then i = i + 1 else return 'table' end
60 | end
61 | if i == 1 then return 'table' else return 'array' end
62 | end
63 |
64 | local function escape_str(s)
65 | local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'}
66 | local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'}
67 | for i, c in ipairs(in_char) do
68 | s = s:gsub(c, '\\' .. out_char[i])
69 | end
70 | return s
71 | end
72 |
73 | -- Returns pos, did_find; there are two cases:
74 | -- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.
75 | -- 2. Delimiter not found: pos = pos after leading space; did_find = false.
76 | -- This throws an error if err_if_missing is true and the delim is not found.
77 | local function skip_delim(str, pos, delim, err_if_missing)
78 | pos = pos + #str:match('^%s*', pos)
79 | if str:sub(pos, pos) ~= delim then
80 | if err_if_missing then
81 | error('Expected ' .. delim .. ' near position ' .. pos)
82 | end
83 | return pos, false
84 | end
85 | return pos + 1, true
86 | end
87 |
88 | -- Expects the given pos to be the first character after the opening quote.
89 | -- Returns val, pos; the returned pos is after the closing quote character.
90 | local function parse_str_val(str, pos, val)
91 | val = val or ''
92 | local early_end_error = 'End of input found while parsing string.'
93 | if pos > #str then error(early_end_error) end
94 | local c = str:sub(pos, pos)
95 | if c == '"' then return val, pos + 1 end
96 | if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end
97 | -- We must have a \ character.
98 | local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'}
99 | local nextc = str:sub(pos + 1, pos + 1)
100 | if not nextc then error(early_end_error) end
101 | return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))
102 | end
103 |
104 | -- Returns val, pos; the returned pos is after the number's final character.
105 | local function parse_num_val(str, pos)
106 | local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)
107 | local val = tonumber(num_str)
108 | if not val then error('Error parsing number at position ' .. pos .. '.') end
109 | return val, pos + #num_str
110 | end
111 |
112 |
113 | -- Public values and functions.
114 |
115 | function json.stringify(obj, as_key)
116 | local s = {} -- We'll build the string as an array of strings to be concatenated.
117 | local kind = kind_of(obj) -- This is 'array' if it's an array or type(obj) otherwise.
118 | if kind == 'array' then
119 | if as_key then error('Can\'t encode array as key.') end
120 | s[#s + 1] = '['
121 | for i, val in ipairs(obj) do
122 | if i > 1 then s[#s + 1] = ', ' end
123 | s[#s + 1] = json.stringify(val)
124 | end
125 | s[#s + 1] = ']'
126 | elseif kind == 'table' then
127 | if as_key then error('Can\'t encode table as key.') end
128 | s[#s + 1] = '{'
129 | for k, v in pairs(obj) do
130 | if #s > 1 then s[#s + 1] = ', ' end
131 | s[#s + 1] = json.stringify(k, true)
132 | s[#s + 1] = ':'
133 | s[#s + 1] = json.stringify(v)
134 | end
135 | s[#s + 1] = '}'
136 | elseif kind == 'string' then
137 | return '"' .. escape_str(obj) .. '"'
138 | elseif kind == 'number' then
139 | if as_key then return '"' .. tostring(obj) .. '"' end
140 | return tostring(obj)
141 | elseif kind == 'boolean' then
142 | return tostring(obj)
143 | elseif kind == 'nil' then
144 | return 'null'
145 | else
146 | error('Unjsonifiable type: ' .. kind .. '.')
147 | end
148 | return table.concat(s)
149 | end
150 |
151 | json.null = {} -- This is a one-off table to represent the null value.
152 |
153 | function json.parse(str, pos, end_delim)
154 | pos = pos or 1
155 | if pos > #str then error('Reached unexpected end of input.') end
156 | local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.
157 | local first = str:sub(pos, pos)
158 | if first == '{' then -- Parse an object.
159 | local obj, key, delim_found = {}, true, true
160 | pos = pos + 1
161 | while true do
162 | key, pos = json.parse(str, pos, '}')
163 | if key == nil then return obj, pos end
164 | if not delim_found then error('Comma missing between object items.') end
165 | pos = skip_delim(str, pos, ':', true) -- true -> error if missing.
166 | obj[key], pos = json.parse(str, pos)
167 | pos, delim_found = skip_delim(str, pos, ',')
168 | end
169 | elseif first == '[' then -- Parse an array.
170 | local arr, val, delim_found = {}, true, true
171 | pos = pos + 1
172 | while true do
173 | val, pos = json.parse(str, pos, ']')
174 | if val == nil then return arr, pos end
175 | if not delim_found then error('Comma missing between array items.') end
176 | arr[#arr + 1] = val
177 | pos, delim_found = skip_delim(str, pos, ',')
178 | end
179 | elseif first == '"' then -- Parse a string.
180 | return parse_str_val(str, pos + 1)
181 | elseif first == '-' or first:match('%d') then -- Parse a number.
182 | return parse_num_val(str, pos)
183 | elseif first == end_delim then -- End of an object or array.
184 | return nil, pos + 1
185 | else -- Parse true, false, or null.
186 | local literals = {['true'] = true, ['false'] = false, ['null'] = json.null}
187 | for lit_str, lit_val in pairs(literals) do
188 | local lit_end = pos + #lit_str - 1
189 | if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end
190 | end
191 | local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)
192 | error('Invalid json syntax starting at ' .. pos_info_str)
193 | end
194 | end
195 |
196 | return json
197 |
198 |
199 |
--------------------------------------------------------------------------------
/src/utils/ros.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: Ting-Chia Chiang
17 | author: G.A. vd. Hoorn
18 | --]]
19 |
20 | ros = {}
21 |
22 | ros.Names = {}
23 | ros.Transformations = {}
24 | ros.Time = {}
25 |
26 |
27 | -- function for legalizing a name for ROS resources
28 | function ros.Names.sanatize(veh_name)
29 | -- in order to meet the ROS naming conventions, we need to sanitize illegal names from FS by using
30 | -- 1. "%W" to replace every non-alphanumeric character with an underscore "_"
31 | -- 2. "+" modifier to get the longest sequence of non-alphanumeric character, i.e. "___" -> "_" (replace consecutive _ with single _)
32 | -- 3. :lower() to replace every uppercase letter with lowercase one
33 | local local_veh_name = veh_name:gsub("%W+", "_"):lower()
34 |
35 | -- make sure names do not start or end with underscores
36 | -- if it starts with an underscore, remove the first character
37 | -- if it ends with an underscore, remove the last character
38 | local_veh_name = local_veh_name:gsub("^_", "")
39 | local_veh_name = local_veh_name:gsub("_$", "")
40 |
41 | return local_veh_name
42 | end
43 |
44 |
45 | --- Construct a quaternion from the specified Euler angles.
46 | -- Function creates a table with four elements, representing a quaternion
47 | -- at the same angle as the result of the Euler angle rotations specified by
48 | -- the 'roll', 'pitch' and 'yaw' arguments.
49 | --
50 | -- NOTE: this follows ROS' conventions for order of arguments (RPY), order of
51 | -- rotations and order of quaternion vector elements (ie: qx, qy, qz, qw).
52 | --
53 | -- @param roll The roll angle
54 | -- @param pitch The pitch angle
55 | -- @param yaw The yaw angle
56 | -- @return a ROS compatible quaternion as a Lua table
57 | function ros.Transformations.quaternion_from_euler(roll, pitch, yaw)
58 | local ci = math.cos(roll / 2)
59 | local cj = math.cos(pitch / 2)
60 | local ck = math.cos(yaw / 2)
61 | local si = math.sin(roll / 2)
62 | local sj = math.sin(pitch / 2)
63 | local sk = math.sin(yaw / 2)
64 |
65 | local cc = ci * ck
66 | local cs = ci * sk
67 | local sc = si * ck
68 | local ss = si * sk
69 |
70 | return {
71 | cj * sc - sj * cs,
72 | cj * ss + sj * cc,
73 | cj * cs - sj * sc,
74 | cj * cc + sj * ss
75 | }
76 | end
77 |
78 |
79 | function ros.Time.now()
80 | -- precision: 48164266.436659 ms with 6 digits after decimal point which is in nanosecond
81 |
82 | local day_time = g_currentMission.environment.dayTime
83 | local floor = math.floor
84 |
85 | local secs_data = floor(day_time / 1000)
86 | local nsecs_data = floor((day_time - floor(day_time / 1000) * 1000) * 1e6)
87 |
88 | return {secs = secs_data, nsecs = nsecs_data}
89 | end
90 |
--------------------------------------------------------------------------------
/src/utils/shared_memory_segment.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | author: G.A. vd. Hoorn
17 | --]]
18 |
19 | SharedMemorySegment = {}
20 | SharedMemorySegment.__index = SharedMemorySegment
21 |
22 | function SharedMemorySegment:init(size)
23 | local segment = {}
24 | setmetatable(segment, SharedMemorySegment)
25 |
26 | -- describe the buffer
27 | segment.len = size
28 | segment.marker_start = "fs_lua_memorp_buffer_0012"
29 | segment.marker_end = "fs_lua_memorp_buffer_end_0012"
30 |
31 | -- number of chars we use to encode buffer length
32 | segment.len_marker_len = 1
33 |
34 | -- index at which the bytes we're interested in actually start.
35 | -- add an extra 1 because Lua is 1-indexed
36 | segment.data_start = segment.marker_start:len() + segment.len_marker_len + 1
37 |
38 | -- construct the 'buffer string', give it a special contents:
39 | --
40 | -- - first the start sentinel value
41 | -- - then the length of the actual buffer in bytes as a single character
42 | -- - then we make some space by adding 'len' spaces
43 | -- - finally the end sentinel value
44 | segment.segment_data = segment.marker_start .. string.char(segment.len) .. string.rep(" ", segment.len) .. segment.marker_end
45 |
46 | return segment
47 | end
48 |
49 |
50 | function SharedMemorySegment:read(len)
51 | -- if no length specified, return the entire buffer
52 | len = len or self.len
53 |
54 | -- TODO: is this -1 necessary?
55 | return self.segment_data:sub(self.data_start, self.data_start + len - 1)
56 | end
57 |
58 |
59 | function SharedMemorySegment:length()
60 | return self.len
61 | end
62 |
63 |
--------------------------------------------------------------------------------
/src/utils/vehicle_util.lua:
--------------------------------------------------------------------------------
1 | vehicle_util = {}
2 |
3 | function vehicle_util.ROSControl(self, dt, acceleration, allowedToDrive, rotatedTime)
4 | if acceleration ~= nil and rotatedTime ~= nil and allowedToDrive ~= nil then
5 | self.rotatedTime = rotatedTime
6 | if self.rotatedTime > self.maxRotTime then
7 | self.rotatedTime = self.maxRotTime
8 | elseif self.rotatedTime < self.minRotTime then
9 | self.rotatedTime = self.minRotTime
10 | end
11 |
12 | -- if self.rotatedTime = 7 turn left
13 | -- if self.rotatedTime = -7 turn right
14 |
15 | if self.firstTimeRun then
16 | -- print(self.firstTimeRun)
17 |
18 | local acc = acceleration
19 |
20 | -- set speed limit
21 | local motor = self.spec_motorized.motor
22 | motor:setSpeedLimit(25)
23 | motor:setAccelerationLimit(5)
24 | -- motor:setMotorRotationAccelerationLimit(150)
25 |
26 | if not allowedToDrive then
27 | acc = 0
28 | end
29 | -- the last argument if set false, the acceleration needs to be 0 before a change of direction is allowed
30 | vehicle_util.upROSControlledWheels(
31 | self,
32 | dt,
33 | self.lastSpeedReal * self.movingDirection,
34 | acc,
35 | not allowedToDrive,
36 | true
37 | )
38 | -- unit of lastSpeedReal m/ms
39 | end
40 | end
41 | end
42 |
43 | function vehicle_util.upROSControlledWheels(self, dt, currentSpeed, acceleration, doHandbrake, stopAndGoBraking)
44 | local acceleratorPedal = 0
45 | local brakePedal = 0
46 | local reverserDirection = 1
47 | if self.spec_drivable ~= nil then
48 | reverserDirection = self.spec_drivable.reverserDirection
49 | acceleration = acceleration * reverserDirection
50 | end
51 |
52 | local motor = self.spec_motorized.motor
53 | local absCurrentSpeed = math.abs(currentSpeed)
54 | local accSign = MathUtil.sign(acceleration)
55 | self.nextMovingDirection = Utils.getNoNil(self.nextMovingDirection, 0)
56 |
57 | local automaticBrake = false
58 | if math.abs(acceleration) < 0.001 then
59 | automaticBrake = true
60 |
61 | -- Non-stop&go only allows change of direction if the vehicle speed is smaller than 1km/h or the direction has already changed (e.g. because the brakes are not hard enough)
62 | if stopAndGoBraking or currentSpeed * self.nextMovingDirection < 0.0003 then
63 | self.nextMovingDirection = 0
64 | end
65 | else
66 | -- Disable the known moving direction if the vehicle is driving more than 5km/h (0.0014 * 3600 = 5.04km/h) in the opposite direction
67 | if self.nextMovingDirection * currentSpeed < -0.0014 then
68 | self.nextMovingDirection = 0
69 | end
70 | -- Continue accelerating if we want to go in the same direction
71 | -- or if the vehicle is only moving slowly in the wrong direction (0.0003 * 3600 = 1.08 km/h) and we are allowed to change direction
72 | if
73 | accSign == self.nextMovingDirection or
74 | (currentSpeed * accSign > -0.0003 and (stopAndGoBraking or self.nextMovingDirection == 0))
75 | then
76 | acceleratorPedal = acceleration
77 | brakePedal = 0
78 | self.nextMovingDirection = accSign
79 | else
80 | acceleratorPedal = 0
81 | brakePedal = math.abs(acceleration)
82 | if stopAndGoBraking then
83 | self.nextMovingDirection = accSign
84 | end
85 | end
86 | end
87 | if automaticBrake then
88 | acceleratorPedal = 0
89 | end
90 | acceleratorPedal = motor:updateGear(acceleratorPedal, dt)
91 |
92 | if motor.gear == 0 and motor.targetGear ~= 0 then
93 | -- brake automatically if the vehicle is rolling backwards while shifting
94 | if currentSpeed * MathUtil.sign(motor.targetGear) < 0 then
95 | automaticBrake = true
96 | end
97 | end
98 | if automaticBrake then
99 | local isSlow = absCurrentSpeed < motor.lowBrakeForceSpeedLimit
100 | local isArticulatedSteering =
101 | self.spec_articulatedAxis ~= nil and self.spec_articulatedAxis.componentJoint ~= nil and
102 | math.abs(self.rotatedTime) > 0.01
103 | if (isSlow or doHandbrake) and not isArticulatedSteering then
104 | brakePedal = 1
105 | else
106 | -- interpolate between lowBrakeForce and 1 if speed is below 3.6 km/h
107 | local factor = math.min(absCurrentSpeed / 0.001, 1)
108 | brakePedal = MathUtil.lerp(1, motor.lowBrakeForceScale, factor)
109 | end
110 | end
111 |
112 | -- this getSmoothedAcceleratorAndBrakePedals doens't work properly, don't use!
113 | -- acceleratorPedal, brakePedal = WheelsUtil.getSmoothedAcceleratorAndBrakePedals(self, acceleratorPedal, brakePedal, dt)
114 | -- print(acceleratorPedal, brakePedal)
115 |
116 | local maxSpeed = motor:getMaximumForwardSpeed() * 3.6
117 | if self.movingDirection < 0 then
118 | maxSpeed = motor:getMaximumBackwardSpeed() * 3.6
119 | end
120 | --active braking if over the speed limit
121 | local overSpeedLimit = self:getLastSpeed() - math.min(motor:getSpeedLimit(), maxSpeed)
122 | if overSpeedLimit > 0 then
123 | brakePedal = math.max(math.min(math.pow(overSpeedLimit + 0.8, 2) - 1, 1), brakePedal) -- start to brake over 0.2km/h
124 | acceleratorPedal = 0.3 * math.max(1 - overSpeedLimit / 0.2, 0) * acceleratorPedal -- fadeout the accelerator pedal over 0.2km/h, but immediately reduce to 30% (don't set to 0 directly so that the physics engine can still compensate if the brakes are too hard)
125 | end
126 | if next(self.spec_motorized.differentials) ~= nil and self.spec_motorized.motorizedNode ~= nil then
127 | local absAcceleratorPedal = math.abs(acceleratorPedal)
128 | local minGearRatio, maxGearRatio = motor:getMinMaxGearRatio()
129 | local maxSpeed
130 | if maxGearRatio >= 0 then
131 | maxSpeed = motor:getMaximumForwardSpeed()
132 | else
133 | maxSpeed = motor:getMaximumBackwardSpeed()
134 | end
135 | local acceleratorPedalControlsSpeed = false
136 | if acceleratorPedalControlsSpeed then
137 | maxSpeed = maxSpeed * absAcceleratorPedal
138 | if absAcceleratorPedal > 0.001 then
139 | absAcceleratorPedal = 1
140 | end
141 | end
142 | maxSpeed = math.min(maxSpeed, motor:getSpeedLimit() / 3.6)
143 | local maxAcceleration = motor:getAccelerationLimit()
144 | local maxMotorRotAcceleration = motor:getMotorRotationAccelerationLimit()
145 | local minMotorRpm, maxMotorRpm = motor:getRequiredMotorRpmRange()
146 | local neededPtoTorque = PowerConsumer.getTotalConsumedPtoTorque(self) / motor:getPtoMotorRpmRatio()
147 | controlVehicle(
148 | self.spec_motorized.motorizedNode,
149 | absAcceleratorPedal,
150 | maxSpeed,
151 | maxAcceleration,
152 | minMotorRpm * math.pi / 30,
153 | maxMotorRpm * math.pi / 30,
154 | maxMotorRotAcceleration,
155 | minGearRatio,
156 | maxGearRatio,
157 | motor:getMaxClutchTorque(),
158 | neededPtoTorque
159 | )
160 | end
161 | self:brake(brakePedal)
162 | end
163 |
--------------------------------------------------------------------------------
/src/vehicles/RosVehicle.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Copyright (c) 2021, TU Delft
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | author: Ting-Chia Chiang
13 | author: G.A. vd. Hoorn
14 | --]]
15 | -- source(Utils.getFilename("src/modROS.lua", g_modROSModDirectory))
16 |
17 | RosVehicle = {}
18 |
19 | -- RosVehicle.MOD_DIR = g_modROSModDirectory
20 | -- RosVehicle.MOD_NAME = g_modROSModName
21 |
22 |
23 | function RosVehicle.prerequisitesPresent(specializations)
24 | -- make spec as a prerequisite for rosVehicle since we only control vehicles which are drivable
25 | -- if a vehicle does not have drivable spec, an error will occur
26 | -- Not all prerequisites of specialization modROS.rosVehicle are fulfilled
27 | return SpecializationUtil.hasSpecialization(Drivable, specializations)
28 | end
29 |
30 |
31 | function RosVehicle.initSpecialization()
32 | end
33 |
34 |
35 | function RosVehicle.registerFunctions(vehicleType)
36 | SpecializationUtil.registerFunction(vehicleType, "addTF", RosVehicle.addTF)
37 | SpecializationUtil.registerFunction(vehicleType, "pubImu", RosVehicle.pubImu)
38 | SpecializationUtil.registerFunction(vehicleType, "pubLaserScan", RosVehicle.pubLaserScan)
39 | SpecializationUtil.registerFunction(vehicleType, "pubOdom", RosVehicle.pubOdom)
40 | end
41 |
42 |
43 | function RosVehicle.registerEventListeners(vehicleType)
44 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", RosVehicle)
45 | -- SpecializationUtil.registerEventListener(vehicleType, "onUpdate", RosVehicle)
46 | end
47 |
48 |
49 | -- -- rosVehicle spec own update
50 | -- function RosVehicle:onUpdate(dt)
51 |
52 | -- end
53 |
54 |
55 | -- this will be loaded for every rosVehicle vehicle before starting the game
56 | function RosVehicle:onLoad()
57 | -- rosVehicle namespace
58 | self.spec_rosVehicle = self["spec_" .. g_modROSModName .. ".rosVehicle"]
59 | local spec = self.spec_rosVehicle
60 | -- General rosVehicle variables
61 |
62 | -- there are two veh_name variables, one is with an id number and the other is without
63 | -- because there could be situations where the same vehicle model is spawned more than once in the FS world
64 | -- Hence, to create unique topic names for each vehicle, the name with id is necessary
65 |
66 | -- variables without id are used as keys to retrieve config settings/tables
67 | -- .id is initialized by FS
68 | spec.ros_veh_name_with_id = ros.Names.sanatize(self:getFullName() .. "_" .. self.id)
69 | spec.ros_veh_name = ros.Names.sanatize(self:getFullName())
70 | spec.base_link_frame = spec.ros_veh_name_with_id .. "/base_link"
71 | spec.component_1_node = self.components[1].node
72 | if not spec.component_1_node then
73 | print(spec.ros_veh_name_with_id .. " does not have components[1].node")
74 | print("Can not publish odom, scan and imu messages for " .. spec.ros_veh_name_with_id)
75 | end
76 | -- Laser scanner initialization
77 |
78 | -- if there is no custom laser scanner setting for this vehicle, use the default settings to initialize an object of LaserScanner class
79 | -- note: a laser scanner is always mounted in the default settings
80 | if not mod_config.vehicle[spec.ros_veh_name] then
81 | spec.laser_scan_obj = LaserScanner.new(self, mod_config.vehicle["default_vehicle"])
82 | -- if the custom laser scanner is mounted (parameter enabled = true), initialize an object of LaserScanner class
83 | elseif mod_config.vehicle[spec.ros_veh_name].laser_scan.enabled then
84 | spec.laser_scan_obj = LaserScanner.new(self, mod_config.vehicle[spec.ros_veh_name])
85 | end
86 |
87 | -- only if the object of LaserScanner class was initialized (the laser scanner is enabled), initialize camera settings
88 | if spec.laser_scan_obj then
89 | -- store the individual vehicle config file in the specialization to avoid reloading in the loop
90 | spec.instance_veh = VehicleCamera:new(self, RosVehicle)
91 | spec.xml_path = spec.instance_veh.vehicle.configFileName
92 | spec.xmlFile = loadXMLFile("vehicle", spec.xml_path)
93 | -- get the cameraRaycast node 2(on top of ) which is 0 index .raycastNode(0)
94 | -- get the cameraRaycast node 3 (in the rear) which is 1 index .raycastNode(1)
95 | local cameraKey = string.format("vehicle.enterable.cameras.camera(%d).%s", 0, spec.laser_scan_obj.vehicle_table.laser_scan.laser_attachments)
96 | XMLUtil.checkDeprecatedXMLElements(spec.xmlFile, spec.xml_path, cameraKey .. "#index", "#node") -- FS17 to FS19
97 | local camIndexStr = getXMLString(spec.xmlFile, cameraKey .. "#node")
98 | spec.instance_veh.cameraNode =
99 | I3DUtil.indexToObject(
100 | spec.instance_veh.vehicle.components,
101 | camIndexStr,
102 | spec.instance_veh.vehicle.i3dMappings
103 | )
104 | if spec.instance_veh.cameraNode == nil then
105 | print(spec.ros_veh_name_with_id .. " does not have cameraNode")
106 | print("Can not publish laser scan messages for " .. spec.ros_veh_name)
107 | end
108 | -- create laser_frame_1 attached to raycastNode (x left, y up, z into the page)
109 | -- and apply a transform to the self.laser_frame_1
110 | local tran_x, tran_y, tran_z = spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.translation.x, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.translation.y, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.translation.z
111 | local rot_x, rot_y, rot_z = spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.x, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.y, spec.laser_scan_obj.vehicle_table.laser_scan.laser_transform.rotation.z
112 | local laser_frame_1 = frames.create_attached_node(spec.instance_veh.cameraNode, self:getFullName(), tran_x, tran_y, tran_z, rot_x, rot_y, rot_z)
113 | spec.LaserFrameNode = laser_frame_1
114 |
115 | -- Imu initialization
116 |
117 | -- initialize linear velocity and time(s) for Imu messages
118 | spec.l_v_x_0 = 0
119 | spec.l_v_y_0 = 0
120 | spec.l_v_z_0 = 0
121 | spec.sec = 0
122 | else
123 | print("An object of LaserScanner class for " .. spec.ros_veh_name_with_id .. "was not initialized")
124 | print("Can not publish laser scan messages for " .. spec.ros_veh_name_with_id)
125 | print("Possible reason:")
126 | print(" - there is no laser_scan.enabled configured in mod_config.lua")
127 | print(" - laser_scan.enabled is set false")
128 | end
129 |
130 | -- initialize publishers for Odometry, LaserScan and Imu messages for each rosVehicle
131 | spec.pub_odom = Publisher.new(ModROS._conx, spec.ros_veh_name_with_id .."/odom", nav_msgs_Odometry)
132 | spec.pub_scan = Publisher.new(ModROS._conx, spec.ros_veh_name_with_id .."/scan", sensor_msgs_LaserScan)
133 | spec.pub_imu = Publisher.new(ModROS._conx, spec.ros_veh_name_with_id .."/imu", sensor_msgs_Imu)
134 | end
135 |
136 |
137 | function RosVehicle:pubOdom(ros_time, tf_msg)
138 |
139 | local spec = self.spec_rosVehicle
140 | local vehicle_base_link = spec.base_link_frame
141 |
142 | -- retrieve the vehicle node we're interested in:
143 | -- A drivable vehicle is often composed of 2 components and the first component is the main part.
144 | -- The second component is mostly the axis object. Hence we take component1 as our vehicle
145 | -- The components can be checked/viewed in each vehicle's 3D model.
146 |
147 | -- if a vehicle somehow does not have self.components[1].node
148 | -- stop publishing odometry and return
149 | if not spec.component_1_node then return end
150 |
151 | local veh_node = spec.component_1_node
152 |
153 | -- retrieve global (ie: world) coordinates of this node
154 | local p_x, p_y, p_z = getWorldTranslation(veh_node)
155 |
156 | -- retrieve global (ie: world) quaternion of this node
157 | local q_x, q_y, q_z, q_w = getWorldQuaternion(veh_node)
158 |
159 | -- get twist data
160 | local l_v_x, l_v_y, l_v_z = getLocalLinearVelocity(veh_node)
161 | -- we don't use getAngularVelocity(veh_node) here as the return value is wrt the world frame not local frame
162 |
163 |
164 | -- convert y up world to z up world (farmsim coordinate system: x right, z towards me, y up; ROS: y right, x towards me, z up)
165 | -- https://stackoverflow.com/questions/16099979/can-i-switch-x-y-z-in-a-quaternion
166 | -- https://gamedev.stackexchange.com/questions/129204/switch-axes-and-handedness-of-a-quaternion
167 | -- https://stackoverflow.com/questions/18818102/convert-quaternion-representing-rotation-from-one-coordinate-system-to-another
168 |
169 |
170 | -- create nav_msgs/Odometry instance
171 | local odom_msg = nav_msgs_Odometry.new()
172 |
173 | -- populate fields (not using Odometry:set(..) here as this is much
174 | -- more readable than a long list of anonymous args)
175 | odom_msg.header.frame_id = "odom"
176 | odom_msg.header.stamp = ros_time
177 | odom_msg.child_frame_id = vehicle_base_link
178 | -- note the order of the axes here (see earlier comment about FS chirality)
179 | odom_msg.pose.pose.position.x = p_z
180 | odom_msg.pose.pose.position.y = p_x
181 | odom_msg.pose.pose.position.z = p_y
182 | -- note again the order of the axes
183 | odom_msg.pose.pose.orientation.x = q_z
184 | odom_msg.pose.pose.orientation.y = q_x
185 | odom_msg.pose.pose.orientation.z = q_y
186 | odom_msg.pose.pose.orientation.w = q_w
187 | -- since the train returns nil when passed to getLocalLinearVelocity, set 0 to prevent an error
188 | if l_v_x == nil then
189 | odom_msg.twist.twist.linear.x = 0
190 | odom_msg.twist.twist.linear.y = 0
191 | odom_msg.twist.twist.linear.z = 0
192 | else
193 | -- note again the order of the axes
194 | odom_msg.twist.twist.linear.x = l_v_z
195 | odom_msg.twist.twist.linear.y = l_v_x
196 | odom_msg.twist.twist.linear.z = l_v_y
197 | end
198 | -- TODO get AngularVelocity wrt local vehicle frame
199 | -- since the farmsim "getAngularVelocity()" can't get body-local angular velocity, we don't set odom_msg.twist.twist.angular for now
200 | -- publish the message
201 | spec.pub_odom:publish(odom_msg)
202 |
203 | -- get tf from odom to vehicles
204 | local tf_odom_vehicle_link = geometry_msgs_TransformStamped.new()
205 | tf_odom_vehicle_link:set("odom", ros_time, vehicle_base_link, p_z, p_x, p_y, q_z, q_x, q_y, q_w)
206 | -- update the transforms_array
207 | self:addTF(tf_msg, tf_odom_vehicle_link)
208 |
209 | end
210 |
211 |
212 | function RosVehicle:addTF(tf_msg, TransformStamped)
213 | tf_msg:add_transform(TransformStamped)
214 | end
215 |
216 |
217 | function RosVehicle:pubLaserScan(ros_time, tf_msg)
218 | local spec = self.spec_rosVehicle
219 | -- only if
220 | -- the object of LaserScanner class was initialized in onload()
221 | -- and the component 1 node exists
222 | -- and the cameraNode exists
223 | -- then publish the LaserScan message
224 | -- otherwise return
225 | if spec.laser_scan_obj and spec.component_1_node and spec.instance_veh.cameraNode then
226 | spec.laser_scan_obj:doScan(ros_time, tf_msg)
227 | else
228 | return
229 | end
230 | end
231 |
232 |
233 | function RosVehicle:pubImu(ros_time)
234 |
235 | local spec = self.spec_rosVehicle
236 |
237 | -- if a vehicle somehow does not have self.components[1].node
238 | -- stop publishing imu and return
239 | if not spec.component_1_node then return end
240 |
241 | -- if there are no custom settings for this vehicle, use the default settings
242 | if not mod_config.vehicle[spec.ros_veh_name] then
243 | spec.imu = mod_config.vehicle["default_vehicle"].imu.enabled
244 | else
245 | spec.imu = mod_config.vehicle[spec.ros_veh_name].imu.enabled
246 | end
247 |
248 | -- if imu of this vehicle is disabled, return
249 | if not spec.imu then return end
250 |
251 | -- retrieve the vehicle node we're interested in
252 | local veh_node = spec.component_1_node
253 |
254 | -- retrieve global (ie: world) coordinates of this node
255 | local q_x, q_y, q_z, q_w = getWorldQuaternion(veh_node)
256 |
257 | -- get twist data and calculate acc info
258 |
259 | -- check getVelocityAtWorldPos and getVelocityAtLocalPos
260 | -- local linear vel: Get velocity at local position of transform object; "getLinearVelocity" is the the velocity wrt world frame
261 | -- local l_v_z max is around 8(i guess the unit is m/s here) when reach 30km/hr(shown in speed indicator)
262 | local l_v_x, l_v_y, l_v_z = getLocalLinearVelocity(veh_node)
263 | -- we don't use getAngularVelocity(veh_node) here as the return value is wrt the world frame not local frame
264 |
265 | -- TODO add condition to filter out the vehicle: train because it does not have velocity info
266 | -- for now we'll just use 0.0 as a replacement value
267 | if not l_v_x then l_v_x = 0.0 end
268 | if not l_v_y then l_v_y = 0.0 end
269 | if not l_v_z then l_v_z = 0.0 end
270 |
271 | -- calculation of linear acceleration in x,y,z directions
272 | local acc_x = (l_v_x - spec.l_v_x_0) / (g_currentMission.environment.dayTime / 1000 - spec.sec)
273 | local acc_y = (l_v_y - spec.l_v_y_0) / (g_currentMission.environment.dayTime / 1000 - spec.sec)
274 | local acc_z = (l_v_z - spec.l_v_z_0) / (g_currentMission.environment.dayTime / 1000 - spec.sec)
275 | -- update the linear velocity and time
276 | spec.l_v_x_0 = l_v_x
277 | spec.l_v_y_0 = l_v_y
278 | spec.l_v_z_0 = l_v_z
279 | spec.sec = g_currentMission.environment.dayTime / 1000
280 |
281 |
282 | -- create sensor_msgs/Imu instance
283 | local imu_msg = sensor_msgs_Imu.new()
284 | -- populate fields (not using sensor_msgs_Imu:set(..) here as this is much
285 | -- more readable than a long list of anonymous args)
286 | imu_msg.header.frame_id = "base_link"
287 | imu_msg.header.stamp = ros_time
288 | -- note the order of the axes here (see earlier comment about FS chirality)
289 | imu_msg.orientation.x = q_z
290 | imu_msg.orientation.y = q_x
291 | imu_msg.orientation.z = q_y
292 | imu_msg.orientation.w = q_w
293 | -- TODO get AngularVelocity wrt local vehicle frame
294 | -- since the farmsim `getAngularVelocity()` can't get body-local angular velocity, we don't set imu_msg.angular_velocity for now
295 |
296 | -- note again the order of the axes
297 | imu_msg.linear_acceleration.x = acc_z
298 | imu_msg.linear_acceleration.y = acc_x
299 | imu_msg.linear_acceleration.z = acc_y
300 |
301 | -- publish the message
302 | spec.pub_imu:publish(imu_msg)
303 |
304 | end
305 |
--------------------------------------------------------------------------------
/store.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tud-cor/FS19_modROS/4356362b6e04060cfee5c103cd249b896ccba8ab/store.dds
--------------------------------------------------------------------------------